+2014-12-10 Martin Liska <mliska@suse.cz>
+
+ * gimple-iterator.h (gsi_start_bb_nondebug): New function.
+ * ipa-icf-gimple.c (func_checker::compare_bb): Correct iteration
+ replaces loop based on precomputed number of non-debug statements.
+
2014-12-08 Alexander Ivchenko <alexander.ivchenko@intel.com>
* config/linux.c (linux_has_ifunc_p): Remove.
return i.ptr;
}
+/* Return a new iterator pointing to the first non-debug statement
+ in basic block BB. */
+
+static inline gimple_stmt_iterator
+gsi_start_bb_nondebug (basic_block bb)
+{
+ gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ while (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
+ gsi_next (&gsi);
+
+ return gsi;
+}
+
/* Return a block statement iterator that points to the first non-label
statement in block BB. */
bool
func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
{
- unsigned i;
gimple_stmt_iterator gsi1, gsi2;
gimple s1, s2;
- if (bb1->nondbg_stmt_count != bb2->nondbg_stmt_count
- || bb1->edge_count != bb2->edge_count)
- return return_false ();
-
- gsi1 = gsi_start_bb (bb1->bb);
- gsi2 = gsi_start_bb (bb2->bb);
+ gsi1 = gsi_start_bb_nondebug (bb1->bb);
+ gsi2 = gsi_start_bb_nondebug (bb2->bb);
- for (i = 0; i < bb1->nondbg_stmt_count; i++)
+ while (!gsi_end_p (gsi1))
{
- if (is_gimple_debug (gsi_stmt (gsi1)))
- gsi_next_nondebug (&gsi1);
-
- if (is_gimple_debug (gsi_stmt (gsi2)))
- gsi_next_nondebug (&gsi2);
+ if (gsi_end_p (gsi2))
+ return return_false ();
s1 = gsi_stmt (gsi1);
s2 = gsi_stmt (gsi2);
return return_false_with_msg ("Unknown GIMPLE code reached");
}
- gsi_next (&gsi1);
- gsi_next (&gsi2);
+ gsi_next_nondebug (&gsi1);
+ gsi_next_nondebug (&gsi2);
}
+ if (!gsi_end_p (gsi2))
+ return return_false ();
+
return true;
}
--- /dev/null
+/* { dg-options "-O2 -fno-guess-branch-probability" } */
+
+int z;
+
+__attribute__((noinline))
+void g ()
+{
+ if (++z)
+ __builtin_exit (0);
+ g ();
+}
+
+__attribute__((noinline))
+void f ()
+{
+ if (++z)
+ __builtin_exit (0);
+ f ();
+}
+
+int main()
+{
+ f ();
+ g ();
+
+ return 0;
+}