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 <rguenther@suse.de> 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.
This commit is contained in:
parent
880682e7b2
commit
1193d05465
|
@ -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;
|
||||
}
|
|
@ -3432,34 +3432,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)
|
||||
{
|
||||
|
@ -3489,6 +3461,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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue