diff -r 000000000000 -r a8cb9039fade patches/gcc/4.7.0/100-PR52734-tree-ssa-tail-merge.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/gcc/4.7.0/100-PR52734-tree-ssa-tail-merge.patch Tue Feb 11 21:34:48 2014 +0100 @@ -0,0 +1,91 @@ +------------------------------------------------------------------------ +r186424 | vries | 2012-04-13 18:44:18 +0200 (Fri, 13 Apr 2012) | 12 lines + +2012-04-13 Tom de Vries + + Backport from mainline r186418. + + 2012-04-13 Tom de Vries + + * tree-ssa-tail-merge.c (gsi_advance_bw_nondebug_nonlocal): Add + parameters vuse and vuse_escaped. + (find_duplicate): Init vuse1, vuse2 and vuse_escaped. Pass to + gsi_advance_bw_nondebug_nonlocal. Return if vuse_escaped and + vuse1 != vuse2. + +------------------------------------------------------------------------ +Index: gcc/tree-ssa-tail-merge.c +=================================================================== +--- gcc-4.7.0/gcc/tree-ssa-tail-merge.c (revision 186423) ++++ gcc-4.7.0/gcc/tree-ssa-tail-merge.c (revision 186424) +@@ -1123,18 +1123,31 @@ + } + } + +-/* 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 @@ + { + 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 @@ + + 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: duplicate of \n", + bb1->index, bb2->index);