+ gcc_assert (fraction >= 0);
+
+ if (num < MAX_SAFE_MULTIPLIER)
+ for (i = 0; i < nbbs; i++)
+ {
+ edge_iterator ei;
+ bbs[i]->frequency = RDIV (bbs[i]->frequency * num, den);
+ if (bbs[i]->count <= MAX_SAFE_MULTIPLIER)
+ bbs[i]->count = RDIV (bbs[i]->count * num, den);
+ else
+ bbs[i]->count = RDIV (bbs[i]->count * fraction, 65536);
+ FOR_EACH_EDGE (e, ei, bbs[i]->succs)
+ if (bbs[i]->count <= MAX_SAFE_MULTIPLIER)
+ e->count = RDIV (e->count * num, den);
+ else
+ e->count = RDIV (e->count * fraction, 65536);
+ }
+ else
+ for (i = 0; i < nbbs; i++)
+ {
+ edge_iterator ei;
+ if (sizeof (gcov_type) > sizeof (int))
+ bbs[i]->frequency = RDIV (bbs[i]->frequency * num, den);
+ else
+ bbs[i]->frequency = RDIV (bbs[i]->frequency * fraction, 65536);
+ bbs[i]->count = RDIV (bbs[i]->count * fraction, 65536);
+ FOR_EACH_EDGE (e, ei, bbs[i]->succs)
+ e->count = RDIV (e->count * fraction, 65536);
+ }
+}
+
+/* Data structures used to maintain mapping between basic blocks and
+ copies. */
+static htab_t bb_original;
+static htab_t bb_copy;
+
+/* And between loops and copies. */
+static htab_t loop_copy;
+static alloc_pool original_copy_bb_pool;
+
+struct htab_bb_copy_original_entry
+{
+ /* Block we are attaching info to. */
+ int index1;
+ /* Index of original or copy (depending on the hashtable) */
+ int index2;
+};
+
+static hashval_t
+bb_copy_original_hash (const void *p)
+{
+ const struct htab_bb_copy_original_entry *data
+ = ((const struct htab_bb_copy_original_entry *)p);
+
+ return data->index1;
+}
+static int
+bb_copy_original_eq (const void *p, const void *q)
+{
+ const struct htab_bb_copy_original_entry *data
+ = ((const struct htab_bb_copy_original_entry *)p);
+ const struct htab_bb_copy_original_entry *data2
+ = ((const struct htab_bb_copy_original_entry *)q);
+
+ return data->index1 == data2->index1;
+}
+
+/* Initialize the data structures to maintain mapping between blocks
+ and its copies. */
+void
+initialize_original_copy_tables (void)
+{
+ gcc_assert (!original_copy_bb_pool);
+ original_copy_bb_pool
+ = create_alloc_pool ("original_copy",
+ sizeof (struct htab_bb_copy_original_entry), 10);
+ bb_original = htab_create (10, bb_copy_original_hash,
+ bb_copy_original_eq, NULL);
+ bb_copy = htab_create (10, bb_copy_original_hash, bb_copy_original_eq, NULL);
+ loop_copy = htab_create (10, bb_copy_original_hash, bb_copy_original_eq, NULL);
+}
+
+/* Free the data structures to maintain mapping between blocks and
+ its copies. */
+void
+free_original_copy_tables (void)
+{
+ gcc_assert (original_copy_bb_pool);
+ htab_delete (bb_copy);
+ htab_delete (bb_original);
+ htab_delete (loop_copy);
+ free_alloc_pool (original_copy_bb_pool);
+ bb_copy = NULL;
+ bb_original = NULL;
+ loop_copy = NULL;
+ original_copy_bb_pool = NULL;
+}
+
+/* Removes the value associated with OBJ from table TAB. */
+
+static void
+copy_original_table_clear (htab_t tab, unsigned obj)
+{
+ void **slot;
+ struct htab_bb_copy_original_entry key, *elt;
+
+ if (!original_copy_bb_pool)
+ return;
+
+ key.index1 = obj;
+ slot = htab_find_slot (tab, &key, NO_INSERT);
+ if (!slot)
+ return;
+
+ elt = (struct htab_bb_copy_original_entry *) *slot;
+ htab_clear_slot (tab, slot);
+ pool_free (original_copy_bb_pool, elt);
+}
+
+/* Sets the value associated with OBJ in table TAB to VAL.
+ Do nothing when data structures are not initialized. */
+
+static void
+copy_original_table_set (htab_t tab, unsigned obj, unsigned val)
+{
+ struct htab_bb_copy_original_entry **slot;
+ struct htab_bb_copy_original_entry key;
+
+ if (!original_copy_bb_pool)
+ return;
+
+ key.index1 = obj;
+ slot = (struct htab_bb_copy_original_entry **)
+ htab_find_slot (tab, &key, INSERT);
+ if (!*slot)