struct loop *in_loop = NULL);
static bool can_predict_insn_p (const rtx_insn *);
static HOST_WIDE_INT get_predictor_value (br_predictor, HOST_WIDE_INT);
+static void determine_unlikely_bbs ();
/* Information we hold about each branch predictor.
Filled using information from predict.def. */
preheaders. */
create_preheaders (CP_SIMPLE_PREHEADERS);
calculate_dominance_info (CDI_POST_DOMINATORS);
+ /* Decide which edges are known to be unlikely. This improves later
+ branch prediction. */
+ determine_unlikely_bbs ();
bb_predictions = new hash_map<const_basic_block, edge_prediction *>;
tree_bb_level_predictions ();
}
/* Finally all edges from non-0 regions to 0 are unlikely. */
FOR_ALL_BB_FN (bb, cfun)
- if (!(bb->count == profile_count::zero ()))
+ {
+ if (!(bb->count == profile_count::zero ()))
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (!(e->probability == profile_probability::never ())
+ && e->dest->count == profile_count::zero ())
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Edge %i->%i is unlikely because "
+ "it enters unlikely block\n",
+ bb->index, e->dest->index);
+ e->probability = profile_probability::never ();
+ }
+
+ edge other = NULL;
+
FOR_EACH_EDGE (e, ei, bb->succs)
- if (!(e->probability == profile_probability::never ())
- && e->dest->count == profile_count::zero ())
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Edge %i->%i is unlikely because "
- "it enters unlikely block\n",
- bb->index, e->dest->index);
- e->probability = profile_probability::never ();
- }
+ if (e->probability == profile_probability::never ())
+ ;
+ else if (other)
+ {
+ other = NULL;
+ break;
+ }
+ else
+ other = e;
+ if (other
+ && !(other->probability == profile_probability::always ()))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Edge %i->%i is locally likely\n",
+ bb->index, other->dest->index);
+ other->probability = profile_probability::always ();
+ }
+ }
if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count == profile_count::zero ())
cgraph_node::get (current_function_decl)->count = profile_count::zero ();
}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized-details-blocks -fdump-rtl-bbpart-details-blocks -freorder-blocks-and-partition" } */
+volatile int v;
+void bar (void) __attribute__((leaf, cold));
+void baz (int *);
+
+void
+foo (int x, int y, int z)
+{
+ static int f __attribute__((section ("mysection")));
+ f = 1;
+ if (__builtin_expect (x, 0))
+ if (__builtin_expect (y, 0))
+ if (__builtin_expect (z, 0))
+ {
+ f = 2;
+ bar ();
+ v += 1;
+ v *= 2;
+ v /= 2;
+ v -= 1;
+ v += 1;
+ v *= 2;
+ v /= 2;
+ v -= 1;
+ v += 1;
+ v *= 2;
+ v /= 2;
+ v -= 1;
+ v += 1;
+ v *= 2;
+ v /= 2;
+ v -= 1;
+ v += 1;
+ v *= 2;
+ v /= 2;
+ v -= 1;
+ v += 1;
+ v *= 2;
+ v /= 2;
+ v -= 1;
+ v += 1;
+ v *= 2;
+ v /= 2;
+ v -= 1;
+ v += 1;
+ v *= 2;
+ v /= 2;
+ v -= 1;
+ f = 3;
+ __builtin_abort ();
+ }
+ f = 4;
+ f = 5;
+ baz (&f);
+}
+/* { dg-final { scan-tree-dump-times "Invalid sum" 0 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "count 0," 1 "optimized"} } */
+/* { dg-final { scan-rtl-dump-times "COLD_PARTITION" 1 "bbpart"} } */