From: Richard Biener Date: Mon, 14 Aug 2023 07:31:18 +0000 (+0200) Subject: tree-optimization/110991 - unroll size estimate after vectorization X-Git-Tag: basepoints/gcc-15~6923 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bcdbedb3e6083ad01d844ed97cf19645c1ef6568;p=thirdparty%2Fgcc.git tree-optimization/110991 - unroll size estimate after vectorization The following testcase shows that we are bad at identifying inductions that will be optimized away after vectorizing them because SCEV doesn't handle vectorized defs. The following rolls a simpler identification of SSA cycles covering a PHI and an assignment with a binary operator with a constant second operand. PR tree-optimization/110991 * tree-ssa-loop-ivcanon.cc (constant_after_peeling): Handle VIEW_CONVERT_EXPR , handle more simple IV-like SSA cycles that will end up constant. * gcc.dg/tree-ssa/cunroll-16.c: New testcase. --- diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-16.c b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-16.c new file mode 100644 index 000000000000..9bb66ff82995 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-16.c @@ -0,0 +1,17 @@ +/* PR/110991 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cunroll-details -fdump-tree-optimized" } */ + +static unsigned char a; +static signed char b; +void foo(void); +int main() { + a = 25; + for (; a > 13; --a) + b = a > 127 ?: a << 3; + if (!b) + foo(); +} + +/* { dg-final { scan-tree-dump "optimized: loop with \[0-9\]\+ iterations completely unrolled" "cunroll" } } */ +/* { dg-final { scan-tree-dump-not "foo" "optimized" } } */ diff --git a/gcc/tree-ssa-loop-ivcanon.cc b/gcc/tree-ssa-loop-ivcanon.cc index a895e8e65be0..99e50ee2efe4 100644 --- a/gcc/tree-ssa-loop-ivcanon.cc +++ b/gcc/tree-ssa-loop-ivcanon.cc @@ -166,6 +166,11 @@ constant_after_peeling (tree op, gimple *stmt, class loop *loop) if (CONSTANT_CLASS_P (op)) return true; + /* Get at the actual SSA operand. */ + if (handled_component_p (op) + && TREE_CODE (TREE_OPERAND (op, 0)) == SSA_NAME) + op = TREE_OPERAND (op, 0); + /* We can still fold accesses to constant arrays when index is known. */ if (TREE_CODE (op) != SSA_NAME) { @@ -198,7 +203,46 @@ constant_after_peeling (tree op, gimple *stmt, class loop *loop) tree ev = analyze_scalar_evolution (loop, op); if (chrec_contains_undetermined (ev) || chrec_contains_symbols (ev)) - return false; + { + if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (op))) + { + gassign *ass = nullptr; + gphi *phi = nullptr; + if (is_a (SSA_NAME_DEF_STMT (op))) + { + ass = as_a (SSA_NAME_DEF_STMT (op)); + if (TREE_CODE (gimple_assign_rhs1 (ass)) == SSA_NAME) + phi = dyn_cast + (SSA_NAME_DEF_STMT (gimple_assign_rhs1 (ass))); + } + else if (is_a (SSA_NAME_DEF_STMT (op))) + { + phi = as_a (SSA_NAME_DEF_STMT (op)); + if (gimple_bb (phi) == loop->header) + { + tree def = gimple_phi_arg_def_from_edge + (phi, loop_latch_edge (loop)); + if (TREE_CODE (def) == SSA_NAME + && is_a (SSA_NAME_DEF_STMT (def))) + ass = as_a (SSA_NAME_DEF_STMT (def)); + } + } + if (ass && phi) + { + tree rhs1 = gimple_assign_rhs1 (ass); + if (gimple_assign_rhs_class (ass) == GIMPLE_BINARY_RHS + && CONSTANT_CLASS_P (gimple_assign_rhs2 (ass)) + && rhs1 == gimple_phi_result (phi) + && gimple_bb (phi) == loop->header + && (gimple_phi_arg_def_from_edge (phi, loop_latch_edge (loop)) + == gimple_assign_lhs (ass)) + && (CONSTANT_CLASS_P (gimple_phi_arg_def_from_edge + (phi, loop_preheader_edge (loop))))) + return true; + } + } + return false; + } return true; }