The following enhances copy propagation of constants to also see through simple operations like conversions but also operations with otherwise constant operands. That's required to fulfill the promise
/* Copy propagation also copy-propagates constants, this is necessary to forward object-size and builtin folding results properly. */ NEXT_PASS (pass_copy_prop); and avoid false diagnostics as shown in the testcase. We're using gimple_fold_stmt_to_constant_1 with not following SSA edges and accordingly adjust what stmts we simulate during SSA propagation. Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/107618 * tree-sssa-copy.cc (stmt_may_generate_copy): Simulate all assignments with a single SSA use. (copy_prop_visit_assignment): Use gimple_fold_stmt_to_constant_1 to perform simple constant folding. (copy_prop::visit_stmt): Visit all assignments. * gcc.dg/pr107618.c: New testcase. --- gcc/testsuite/gcc.dg/pr107618.c | 10 +++++++ gcc/tree-ssa-copy.cc | 49 +++++++++++++++++---------------- 2 files changed, 35 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr107618.c diff --git a/gcc/testsuite/gcc.dg/pr107618.c b/gcc/testsuite/gcc.dg/pr107618.c new file mode 100644 index 00000000000..9e73cc1f1a1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr107618.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-Og" } */ + +void a(void) __attribute__((__warning__(""))); +int main(void) +{ + unsigned long b = __builtin_object_size(0, 0); + if (__builtin_expect(b < 1, 0)) + a(); /* { dg-bogus "warning" } */ +} diff --git a/gcc/tree-ssa-copy.cc b/gcc/tree-ssa-copy.cc index 782ceb500cc..811161c223e 100644 --- a/gcc/tree-ssa-copy.cc +++ b/gcc/tree-ssa-copy.cc @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "tree-scalar-evolution.h" #include "tree-ssa-loop-niter.h" +#include "gimple-fold.h" /* This file implements the copy propagation pass and provides a @@ -99,12 +100,16 @@ stmt_may_generate_copy (gimple *stmt) if (gimple_vuse (stmt)) return false; + /* If the assignment is from a constant it generates a useful copy. */ + if (gimple_assign_single_p (stmt) + && is_gimple_min_invariant (gimple_assign_rhs1 (stmt))) + return true; + /* Otherwise, the only statements that generate useful copies are - assignments whose RHS is just an SSA name that doesn't flow - through abnormal edges. */ - return ((gimple_assign_rhs_code (stmt) == SSA_NAME - && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt))) - || is_gimple_min_invariant (gimple_assign_rhs1 (stmt))); + assignments whose single SSA use doesn't flow through abnormal + edges. */ + tree rhs = single_ssa_tree_operand (stmt, SSA_OP_USE); + return (rhs && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs)); } @@ -197,26 +202,24 @@ dump_copy_of (FILE *file, tree var) static enum ssa_prop_result copy_prop_visit_assignment (gimple *stmt, tree *result_p) { - tree lhs, rhs; - - lhs = gimple_assign_lhs (stmt); - rhs = valueize_val (gimple_assign_rhs1 (stmt)); - - if (TREE_CODE (lhs) == SSA_NAME) + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_fold_stmt_to_constant_1 (stmt, valueize_val); + if (rhs + && (TREE_CODE (rhs) == SSA_NAME + || is_gimple_min_invariant (rhs))) { - /* Straight copy between two SSA names. First, make sure that + /* Straight copy between two SSA names or a constant. Make sure that we can propagate the RHS into uses of LHS. */ if (!may_propagate_copy (lhs, rhs)) - return SSA_PROP_VARYING; - - *result_p = lhs; - if (set_copy_of_val (*result_p, rhs)) - return SSA_PROP_INTERESTING; - else - return SSA_PROP_NOT_INTERESTING; + rhs = lhs; } + else + rhs = lhs; - return SSA_PROP_VARYING; + *result_p = lhs; + if (set_copy_of_val (*result_p, rhs)) + return SSA_PROP_INTERESTING; + return rhs != lhs ? SSA_PROP_NOT_INTERESTING : SSA_PROP_VARYING; } @@ -282,10 +285,8 @@ copy_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *result_p) fprintf (dump_file, "\n"); } - if (gimple_assign_single_p (stmt) - && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME - && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME - || is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))) + if (is_gimple_assign (stmt) + && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME) { /* If the statement is a copy assignment, evaluate its RHS to see if the lattice value of its output has changed. */ -- 2.35.3