diff options
Diffstat (limited to 'toolchain/gcc/4.7.0/200-gcc-pr52734.patch')
-rw-r--r-- | toolchain/gcc/4.7.0/200-gcc-pr52734.patch | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/toolchain/gcc/4.7.0/200-gcc-pr52734.patch b/toolchain/gcc/4.7.0/200-gcc-pr52734.patch new file mode 100644 index 000000000..a1ac6017d --- /dev/null +++ b/toolchain/gcc/4.7.0/200-gcc-pr52734.patch @@ -0,0 +1,115 @@ +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; ++} ++ |