123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- Index: gcc/tree-ssa-tail-merge.c
- ===================================================================
- --- a/gcc/tree-ssa-tail-merge.c (revision 185028)
- +++ b/gcc/tree-ssa-tail-merge.c (working copy)
- @@ -1123,18 +1123,31 @@ gimple_equal_p (same_succ same_succ, gim
- }
- }
-
- -/* Let GSI skip backwards over local defs. */
- +/* Let GSI skip backwards over local defs. Return the earliest vuse in VUSE.
- + Return true in VUSE_ESCAPED if the vuse influenced a SSA_OP_DEF of one of the
- + processed statements. */
-
- static void
- -gsi_advance_bw_nondebug_nonlocal (gimple_stmt_iterator *gsi)
- +gsi_advance_bw_nondebug_nonlocal (gimple_stmt_iterator *gsi, tree *vuse,
- + bool *vuse_escaped)
- {
- gimple stmt;
- + tree lvuse;
-
- while (true)
- {
- if (gsi_end_p (*gsi))
- return;
- stmt = gsi_stmt (*gsi);
- +
- + lvuse = gimple_vuse (stmt);
- + if (lvuse != NULL_TREE)
- + {
- + *vuse = lvuse;
- + if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_DEF))
- + *vuse_escaped = true;
- + }
- +
- if (!(is_gimple_assign (stmt) && local_def (gimple_get_lhs (stmt))
- && !gimple_has_side_effects (stmt)))
- return;
- @@ -1150,9 +1163,11 @@ find_duplicate (same_succ same_succ, bas
- {
- gimple_stmt_iterator gsi1 = gsi_last_nondebug_bb (bb1);
- gimple_stmt_iterator gsi2 = gsi_last_nondebug_bb (bb2);
- + tree vuse1 = NULL_TREE, vuse2 = NULL_TREE;
- + bool vuse_escaped = false;
-
- - gsi_advance_bw_nondebug_nonlocal (&gsi1);
- - gsi_advance_bw_nondebug_nonlocal (&gsi2);
- + gsi_advance_bw_nondebug_nonlocal (&gsi1, &vuse1, &vuse_escaped);
- + gsi_advance_bw_nondebug_nonlocal (&gsi2, &vuse2, &vuse_escaped);
-
- while (!gsi_end_p (gsi1) && !gsi_end_p (gsi2))
- {
- @@ -1161,13 +1176,20 @@ find_duplicate (same_succ same_succ, bas
-
- gsi_prev_nondebug (&gsi1);
- gsi_prev_nondebug (&gsi2);
- - gsi_advance_bw_nondebug_nonlocal (&gsi1);
- - gsi_advance_bw_nondebug_nonlocal (&gsi2);
- + gsi_advance_bw_nondebug_nonlocal (&gsi1, &vuse1, &vuse_escaped);
- + gsi_advance_bw_nondebug_nonlocal (&gsi2, &vuse2, &vuse_escaped);
- }
-
- if (!(gsi_end_p (gsi1) && gsi_end_p (gsi2)))
- return;
-
- + /* If the incoming vuses are not the same, and the vuse escaped into an
- + SSA_OP_DEF, then merging the 2 blocks will change the value of the def,
- + which potentially means the semantics of one of the blocks will be changed.
- + TODO: make this check more precise. */
- + if (vuse_escaped && vuse1 != vuse2)
- + return;
- +
- if (dump_file)
- fprintf (dump_file, "find_duplicates: <bb %d> duplicate of <bb %d>\n",
- bb1->index, bb2->index);
- Index: gcc/testsuite/gcc.dg/pr52734.c
- ===================================================================
- --- a/dev/null (new file)
- +++ b/gcc/testsuite/gcc.dg/pr52734.c (revision 0)
- @@ -0,0 +1,35 @@
- +/* { dg-do run } */
- +/* { dg-options "-O2" } */
- +
- +int bbb = 0;
- +
- +int __attribute__((noinline,noclone)) aaa(void)
- +{
- + ++bbb;
- + return 0;
- +}
- +
- +int __attribute__((noinline,noclone)) ccc(void)
- +{
- + int ddd;
- + /* bbb == 0 */
- + if (aaa())
- + return bbb;
- +
- + /* bbb == 1 */
- + ddd = bbb;
- + /* bbb == ddd == 1 */
- + if (aaa ())
- + return 0;
- + /* bbb == 2, ddd == 1 */
- +
- + return ddd;
- +}
- +
- +int main(void)
- +{
- + if (ccc() != 1)
- + __builtin_abort();
- + return 0;
- +}
- +
|