--- a/gcc/tree-ssa-tail-merge.c +++ b/gcc/tree-ssa-tail-merge.c @@ -1033,7 +1033,7 @@ set_cluster (basic_block bb1, basic_bloc gimple_bb (s2) are members of SAME_SUCC. */ static bool -gimple_equal_p (same_succ same_succ, gimple s1, gimple s2) +gimple_equal_p (same_succ same_succ, gimple s1, gimple s2, bool *gvn_used) { unsigned int i; tree lhs1, lhs2; @@ -1069,7 +1069,10 @@ gimple_equal_p (same_succ same_succ, gim if (operand_equal_p (t1, t2, 0)) continue; if (gvn_uses_equal (t1, t2)) - continue; + { + *gvn_used = true; + continue; + } equal = false; break; } @@ -1083,12 +1086,16 @@ gimple_equal_p (same_succ same_succ, gim if (lhs1 == NULL_TREE || lhs2 == NULL_TREE) return false; if (TREE_CODE (lhs1) == SSA_NAME && TREE_CODE (lhs2) == SSA_NAME) - return vn_valueize (lhs1) == vn_valueize (lhs2); + { + *gvn_used = true; + return vn_valueize (lhs1) == vn_valueize (lhs2); + } return operand_equal_p (lhs1, lhs2, 0); case GIMPLE_ASSIGN: lhs1 = gimple_get_lhs (s1); lhs2 = gimple_get_lhs (s2); + *gvn_used = true; return (TREE_CODE (lhs1) == SSA_NAME && TREE_CODE (lhs2) == SSA_NAME && vn_valueize (lhs1) == vn_valueize (lhs2)); @@ -1096,15 +1103,23 @@ gimple_equal_p (same_succ same_succ, gim case GIMPLE_COND: t1 = gimple_cond_lhs (s1); t2 = gimple_cond_lhs (s2); - if (!operand_equal_p (t1, t2, 0) - && !gvn_uses_equal (t1, t2)) - return false; + if (!operand_equal_p (t1, t2, 0)) + { + if (gvn_uses_equal (t1, t2)) + *gvn_used = true; + else + return false; + } t1 = gimple_cond_rhs (s1); t2 = gimple_cond_rhs (s2); - if (!operand_equal_p (t1, t2, 0) - && !gvn_uses_equal (t1, t2)) - return false; + if (!operand_equal_p (t1, t2, 0)) + { + if (gvn_uses_equal (t1, t2)) + *gvn_used = true; + else + return false; + } code1 = gimple_expr_code (s1); code2 = gimple_expr_code (s2); @@ -1126,18 +1141,25 @@ gimple_equal_p (same_succ same_succ, gim /* Let GSI skip backwards over local defs. */ static void -gsi_advance_bw_nondebug_nonlocal (gimple_stmt_iterator *gsi) +gsi_advance_bw_nondebug_nonlocal (gimple_stmt_iterator *gsi, tree *vuse) { 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 (!(is_gimple_assign (stmt) && local_def (gimple_get_lhs (stmt)) && !gimple_has_side_effects (stmt))) return; + gsi_prev_nondebug (gsi); } } @@ -1146,28 +1168,34 @@ gsi_advance_bw_nondebug_nonlocal (gimple clusters them. */ static void -find_duplicate (same_succ same_succ, basic_block bb1, basic_block bb2) +find_duplicate (same_succ same_succ, basic_block bb1, basic_block bb2, + bool gvn_used) { 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; - gsi_advance_bw_nondebug_nonlocal (&gsi1); - gsi_advance_bw_nondebug_nonlocal (&gsi2); + gsi_advance_bw_nondebug_nonlocal (&gsi1, &vuse1); + gsi_advance_bw_nondebug_nonlocal (&gsi2, &vuse2); while (!gsi_end_p (gsi1) && !gsi_end_p (gsi2)) { - if (!gimple_equal_p (same_succ, gsi_stmt (gsi1), gsi_stmt (gsi2))) + if (!gimple_equal_p (same_succ, gsi_stmt (gsi1), gsi_stmt (gsi2), + &gvn_used)) return; 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); + gsi_advance_bw_nondebug_nonlocal (&gsi2, &vuse2); } if (!(gsi_end_p (gsi1) && gsi_end_p (gsi2))) return; + if (gvn_used && vuse1 != vuse2) + return; + if (dump_file) fprintf (dump_file, "find_duplicates: duplicate of \n", bb1->index, bb2->index); @@ -1179,7 +1207,7 @@ find_duplicate (same_succ same_succ, bas E2 are equal. */ static bool -same_phi_alternatives_1 (basic_block dest, edge e1, edge e2) +same_phi_alternatives_1 (basic_block dest, edge e1, edge e2, bool *gvn_used) { int n1 = e1->dest_idx, n2 = e2->dest_idx; gimple_stmt_iterator gsi; @@ -1197,7 +1225,10 @@ same_phi_alternatives_1 (basic_block des if (operand_equal_for_phi_arg_p (val1, val2)) continue; if (gvn_uses_equal (val1, val2)) - continue; + { + *gvn_used = true; + continue; + } return false; } @@ -1209,7 +1240,8 @@ same_phi_alternatives_1 (basic_block des phi alternatives for BB1 and BB2 are equal. */ static bool -same_phi_alternatives (same_succ same_succ, basic_block bb1, basic_block bb2) +same_phi_alternatives (same_succ same_succ, basic_block bb1, basic_block bb2, + bool *gvn_used) { unsigned int s; bitmap_iterator bs; @@ -1227,7 +1259,7 @@ same_phi_alternatives (same_succ same_su /* For all phis in bb, the phi alternatives for e1 and e2 need to have the same value. */ - if (!same_phi_alternatives_1 (succ, e1, e2)) + if (!same_phi_alternatives_1 (succ, e1, e2, gvn_used)) return false; } @@ -1301,6 +1333,7 @@ find_clusters_1 (same_succ same_succ) bitmap_iterator bi, bj; int nr_comparisons; int max_comparisons = PARAM_VALUE (PARAM_MAX_TAIL_MERGE_COMPARISONS); + bool gvn_used; EXECUTE_IF_SET_IN_BITMAP (same_succ->bbs, 0, i, bi) { @@ -1333,10 +1366,11 @@ find_clusters_1 (same_succ same_succ) if (!deps_ok_for_redirect (bb1, bb2)) continue; - if (!(same_phi_alternatives (same_succ, bb1, bb2))) + gvn_used = false; + if (!(same_phi_alternatives (same_succ, bb1, bb2, &gvn_used))) continue; - find_duplicate (same_succ, bb1, bb2); + find_duplicate (same_succ, bb1, bb2, gvn_used); } } } --- /dev/null +++ b/testsuite/gcc.dg/pr52734.c @@ -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; +} +