From: Richard Biener Date: Thu, 25 Feb 2021 08:36:33 +0000 (+0100) Subject: tree-optimization/99253 - fix reduction path check X-Git-Tag: releases/gcc-10.3.0~217 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=65767abfdc07547b5435083a5af6ab085e013a4d;p=thirdparty%2Fgcc.git tree-optimization/99253 - fix reduction path check This fixes an ordering problem with verifying that no intermediate computations in a reduction path are used outside of the chain. The check was disabled for value-preserving conversions at the tail but whether a stmt was a conversion or not was only computed after the first use. The following fixes this by re-ordering things accordingly. 2021-02-25 Richard Biener PR tree-optimization/99253 * tree-vect-loop.c (check_reduction_path): First compute code, then verify out-of-loop uses. * gcc.dg/vect/pr99253.c: New testcase. (cherry picked from commit 1193d05465acd39b6e3c7095274d8351a1e2cd44) --- diff --git a/gcc/testsuite/gcc.dg/vect/pr99253.c b/gcc/testsuite/gcc.dg/vect/pr99253.c new file mode 100644 index 000000000000..9e3345025bab --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr99253.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ + +#include "tree-vect.h" + +int a = 0; +static int b = 0; +long c = 0; + +int +main() +{ + check_vect (); + for (int d = 0; d < 8; d++) + { + a ^= c; + b = a; + a ^= 1; + } + if (a != 0 || b != 1) + __builtin_abort(); + return 0; +} diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index cfeeac5f84e2..899b56087451 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -3030,34 +3030,6 @@ pop: fail = true; break; } - /* Check there's only a single stmt the op is used on. For the - not value-changing tail and the last stmt allow out-of-loop uses. - ??? We could relax this and handle arbitrary live stmts by - forcing a scalar epilogue for example. */ - imm_use_iterator imm_iter; - gimple *op_use_stmt; - unsigned cnt = 0; - FOR_EACH_IMM_USE_STMT (op_use_stmt, imm_iter, op) - if (!is_gimple_debug (op_use_stmt) - && (*code != ERROR_MARK - || flow_bb_inside_loop_p (loop, gimple_bb (op_use_stmt)))) - { - /* We want to allow x + x but not x < 1 ? x : 2. */ - if (is_gimple_assign (op_use_stmt) - && gimple_assign_rhs_code (op_use_stmt) == COND_EXPR) - { - use_operand_p use_p; - FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) - cnt++; - } - else - cnt++; - } - if (cnt != 1) - { - fail = true; - break; - } tree_code use_code = gimple_assign_rhs_code (use_stmt); if (use_code == MINUS_EXPR) { @@ -3087,6 +3059,34 @@ pop: fail = true; break; } + /* Check there's only a single stmt the op is used on. For the + not value-changing tail and the last stmt allow out-of-loop uses. + ??? We could relax this and handle arbitrary live stmts by + forcing a scalar epilogue for example. */ + imm_use_iterator imm_iter; + gimple *op_use_stmt; + unsigned cnt = 0; + FOR_EACH_IMM_USE_STMT (op_use_stmt, imm_iter, op) + if (!is_gimple_debug (op_use_stmt) + && (*code != ERROR_MARK + || flow_bb_inside_loop_p (loop, gimple_bb (op_use_stmt)))) + { + /* We want to allow x + x but not x < 1 ? x : 2. */ + if (is_gimple_assign (op_use_stmt) + && gimple_assign_rhs_code (op_use_stmt) == COND_EXPR) + { + use_operand_p use_p; + FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) + cnt++; + } + else + cnt++; + } + if (cnt != 1) + { + fail = true; + break; + } } return ! fail && ! neg && *code != ERROR_MARK; }