+2005-03-18 Jan Hubicka <jh@suse.cz>
+ Dale Johannesen <dalej@apple.com>
+
+ * basic-block.h (scale_bbs_frequencies_int,
+ scale_bbs_frequencies_gcov_type): Declare.
+ * cfg.c (RDIV): New macro.
+ (update_bb_frequency_for_threading): Fix.
+ * basic-block.h (scale_bbs_frequencies_int,
+ scale_bbs_frequencies_gcov_type): New.
+ * cfgloopmanip.c (scale_bbs_frequencies): Kill.
+ (scale_loop_frequencies, duplicate_loop_to_header_edge): Use
+ scale_bbs_frequencies_int.
+ * tree-ssa-loop-ch.c (copy_loop_headers): Fix profiling info.
+
2005-03-18 Kazu Hirata <kazu@cs.umass.edu>
* config/m32r/m32r-protos.h: Remove the prototypes for
extern void brief_dump_cfg (FILE *);
extern void clear_edges (void);
extern rtx first_insn_after_basic_block_note (basic_block);
+extern void scale_bbs_frequencies_int (basic_block *, int, int, int);
+extern void scale_bbs_frequencies_gcov_type (basic_block *, int, gcov_type,
+ gcov_type);
/* Structure to group all of the information to process IF-THEN and
IF-THEN-ELSE blocks for the conditional execution support. This
/* Indicate the presence of the profile. */
enum profile_status profile_status;
\f
+#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
+
/* Called once at initialization time. */
void
}
else if (prob != REG_BR_PROB_BASE)
{
- int scale = REG_BR_PROB_BASE / prob;
+ int scale = 65536 * REG_BR_PROB_BASE / prob;
FOR_EACH_EDGE (c, ei, bb->succs)
- c->probability *= scale;
+ c->probability *= scale / 65536;
}
if (bb != taken_edge->src)
if (taken_edge->count < 0)
taken_edge->count = 0;
}
+
+/* Multiply all frequencies of basic blocks in array BBS of length NBBS
+ by NUM/DEN, in int arithmetic. May lose some accuracy. */
+void
+scale_bbs_frequencies_int (basic_block *bbs, int nbbs, int num, int den)
+{
+ int i;
+ edge e;
+ for (i = 0; i < nbbs; i++)
+ {
+ edge_iterator ei;
+ bbs[i]->frequency = (bbs[i]->frequency * num) / den;
+ bbs[i]->count = RDIV (bbs[i]->count * num, den);
+ FOR_EACH_EDGE (e, ei, bbs[i]->succs)
+ e->count = (e->count * num) /den;
+ }
+}
+
+/* Multiply all frequencies of basic blocks in array BBS of length NBBS
+ by NUM/DEN, in gcov_type arithmetic. More accurate than previous
+ function but considerably slower. */
+void
+scale_bbs_frequencies_gcov_type (basic_block *bbs, int nbbs, gcov_type num,
+ gcov_type den)
+{
+ int i;
+ edge e;
+
+ for (i = 0; i < nbbs; i++)
+ {
+ edge_iterator ei;
+ bbs[i]->frequency = (bbs[i]->frequency * num) / den;
+ bbs[i]->count = RDIV (bbs[i]->count * num, den);
+ FOR_EACH_EDGE (e, ei, bbs[i]->succs)
+ e->count = (e->count * num) /den;
+ }
+}
static void fix_bb_placements (struct loops *, basic_block);
static void place_new_loop (struct loops *, struct loop *);
static void scale_loop_frequencies (struct loop *, int, int);
-static void scale_bbs_frequencies (basic_block *, int, int, int);
static basic_block create_preheader (struct loop *, int);
static void fix_irreducible_loops (basic_block);
static void unloop (struct loops *, struct loop *);
free (bbs);
}
-/* Multiply all frequencies of basic blocks in array BBS of length NBBS
- by NUM/DEN. */
-static void
-scale_bbs_frequencies (basic_block *bbs, int nbbs, int num, int den)
-{
- int i;
- edge e;
-
- for (i = 0; i < nbbs; i++)
- {
- edge_iterator ei;
- bbs[i]->frequency = (bbs[i]->frequency * num) / den;
- bbs[i]->count = RDIV (bbs[i]->count * num, den);
- FOR_EACH_EDGE (e, ei, bbs[i]->succs)
- e->count = (e->count * num) /den;
- }
-}
-
/* Multiply all frequencies in LOOP by NUM/DEN. */
static void
scale_loop_frequencies (struct loop *loop, int num, int den)
basic_block *bbs;
bbs = get_loop_body (loop);
- scale_bbs_frequencies (bbs, loop->num_nodes, num, den);
+ scale_bbs_frequencies_int (bbs, loop->num_nodes, num, den);
free (bbs);
}
/* Set counts and frequencies. */
if (flags & DLTHE_FLAG_UPDATE_FREQ)
{
- scale_bbs_frequencies (new_bbs, n, scale_act, REG_BR_PROB_BASE);
+ scale_bbs_frequencies_int (new_bbs, n, scale_act, REG_BR_PROB_BASE);
scale_act = RDIV (scale_act * scale_step[j], REG_BR_PROB_BASE);
}
}
set_immediate_dominator (CDI_DOMINATORS, e->dest, e->src);
if (flags & DLTHE_FLAG_UPDATE_FREQ)
{
- scale_bbs_frequencies (bbs, n, scale_main, REG_BR_PROB_BASE);
+ scale_bbs_frequencies_int (bbs, n, scale_main, REG_BR_PROB_BASE);
free (scale_step);
}
unsigned i;
struct loop *loop;
basic_block header;
- edge exit;
- basic_block *bbs;
+ edge exit, entry;
+ basic_block *bbs, *copied_bbs;
unsigned n_bbs;
+ unsigned bbs_size;
+ gcov_type entry_count, body_count, total_count;
loops = loop_optimizer_init (dump_file);
if (!loops)
#endif
bbs = xmalloc (sizeof (basic_block) * n_basic_blocks);
+ copied_bbs = xmalloc (sizeof (basic_block) * n_basic_blocks);
+ bbs_size = n_basic_blocks;
for (i = 1; i < loops->num; i++)
{
else
exit = EDGE_SUCC (header, 1);
bbs[n_bbs++] = header;
+ gcc_assert (bbs_size > n_bbs);
header = exit->dest;
}
if (!single_pred_p (exit->dest))
exit = single_succ_edge (loop_split_edge_with (exit, NULL));
- if (!tree_duplicate_sese_region (loop_preheader_edge (loop), exit,
- bbs, n_bbs, NULL))
+ entry = loop_preheader_edge (loop);
+ entry_count = entry->src->count;
+ body_count = exit->dest->count;
+
+ if (!tree_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs))
{
fprintf (dump_file, "Duplication failed.\n");
continue;
}
+ /* Fix profiling info. Scaling is done in gcov_type arithmetic to
+ avoid losing information; this is slow, but is done at most
+ once per loop. We special case 0 to avoid division by 0;
+ probably other special cases exist. */
+ total_count = body_count + entry_count;
+ if (total_count == 0LL)
+ {
+ scale_bbs_frequencies_int (bbs, n_bbs, 0, 1);
+ scale_bbs_frequencies_int (copied_bbs, n_bbs, 0, 1);
+ }
+ else
+ {
+ scale_bbs_frequencies_gcov_type (bbs, n_bbs, body_count, total_count);
+ scale_bbs_frequencies_gcov_type (copied_bbs, n_bbs, entry_count,
+ total_count);
+ }
+
/* Ensure that the latch and the preheader is simple (we know that they
are not now, since there was the loop exit condition. */
loop_split_edge_with (loop_preheader_edge (loop), NULL);
}
free (bbs);
+ free (copied_bbs);
#ifdef ENABLE_CHECKING
verify_loop_closed_ssa ();