When we remove __builtin_pow statements as part of reassociation, we have to unlink the associated VDEF. We've always done this when we directly remove the statement. However, in reassociation the statements are sometimes modified in place instead of removed, potentially leaving one or more dangling VUSEs. This patch solves the problem by unlinking the VDEF when the statement's operands are added to the ops list.
Bootstrapped and regression tested on powerpc64-unknown-linux-gnu with no new regressions. The new test case is the code that exposed the problem in PR56321. Ok for trunk? Thanks, Bill Index: gcc/testsuite/gcc.dg/tree-ssa/pr56321.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/pr56321.c (revision 0) +++ gcc/testsuite/gcc.dg/tree-ssa/pr56321.c (revision 0) @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -ffast-math -fdump-tree-optimized" } */ + +float foo(int n) +{ + return ((2.0*n*n)/3.0+2.0*n); +} + +/* { dg-final { scan-tree-dump-times "__builtin_pow" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " \\* " 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " \\+ " 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Index: gcc/tree-ssa-reassoc.c =================================================================== --- gcc/tree-ssa-reassoc.c (revision 196053) +++ gcc/tree-ssa-reassoc.c (working copy) @@ -3386,6 +3386,10 @@ linearize_expr_tree (vec<operand_entry_t> *ops, gi { add_repeat_to_ops_vec (ops, base, exponent); gimple_set_visited (binrhsdef, true); + // We may not physically remove the call later because + // stmts are preferably modified in place. But we have + // to remove any VDEF associated with the call regardless. + unlink_stmt_vdef (binrhsdef); } else add_to_ops_vec (ops, binrhs); @@ -3396,6 +3400,10 @@ linearize_expr_tree (vec<operand_entry_t> *ops, gi { add_repeat_to_ops_vec (ops, base, exponent); gimple_set_visited (binlhsdef, true); + // We may not physically remove the call later because + // stmts are preferably modified in place. But we have + // to remove any VDEF associated with the call regardless. + unlink_stmt_vdef (binlhsdef); } else add_to_ops_vec (ops, binlhs); @@ -3445,6 +3453,10 @@ linearize_expr_tree (vec<operand_entry_t> *ops, gi { add_repeat_to_ops_vec (ops, base, exponent); gimple_set_visited (SSA_NAME_DEF_STMT (binrhs), true); + // We may not physically remove the call later because + // stmts are preferably modified in place. But we have + // to remove any VDEF associated with the call regardless. + unlink_stmt_vdef (SSA_NAME_DEF_STMT (binrhs)); } else add_to_ops_vec (ops, binrhs);