ranger: Fix up REALPART_EXPR/IMAGPART_EXPR handling [PR104604]

The following testcase is miscompiled since r12-3328.
That change assumed that if rhs1 of a GIMPLE_ASSIGN is COMPLEX_CST, then
that is the value of the lhs of the stmt, but that is not the case always,
only if it is a GIMPLE_SINGLE_RHS stmt.  If it is e.g.
GIMPLE_UNARY_RHS or GIMPLE_BINARY_RHS (the latter happens in the testcase),
then it can be e.g.
__complex__ (3, 0) / var
and the REALPART_EXPR of that isn't 3, but the realpart of the division.
I assume once the ranger can do complex numbers adjust_*part_expr will just
fetch one or the other range from a underlying complex range, but until
then, we should limit this to what r12-3328 meant to do.

2022-02-22  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/104604
	* gimple-range-fold.cc (adjust_imagpart_expr, adjust_realpart_expr):
	Only check if gimple_assign_rhs1 is COMPLEX_CST if
	gimple_assign_rhs_code is COMPLEX_CST.

	* gcc.c-torture/execute/pr104604.c: New test.
This commit is contained in:
Jakub Jelinek 2022-02-22 10:43:13 +01:00
parent 7e691189ca
commit d44dc131f4
2 changed files with 38 additions and 2 deletions

View file

@ -397,7 +397,8 @@ adjust_imagpart_expr (irange &res, const gimple *stmt)
}
return;
}
if (is_gimple_assign (def_stmt))
if (is_gimple_assign (def_stmt)
&& gimple_assign_rhs_code (def_stmt) == COMPLEX_CST)
{
tree cst = gimple_assign_rhs1 (def_stmt);
if (TREE_CODE (cst) == COMPLEX_CST)
@ -422,7 +423,8 @@ adjust_realpart_expr (irange &res, const gimple *stmt)
if (!SSA_NAME_DEF_STMT (name))
return;
if (is_gimple_assign (def_stmt))
if (is_gimple_assign (def_stmt)
&& gimple_assign_rhs_code (def_stmt) == COMPLEX_CST)
{
tree cst = gimple_assign_rhs1 (def_stmt);
if (TREE_CODE (cst) == COMPLEX_CST)

View file

@ -0,0 +1,34 @@
/* PR tree-optimization/104604 */
unsigned char g;
__attribute__((noipa))
unsigned char
foo (_Complex unsigned c)
{
unsigned char v = g;
_Complex unsigned t = 3;
t /= c;
return v + t;
}
__attribute__((noipa))
unsigned char
bar (_Complex unsigned c)
{
unsigned char v = g;
_Complex unsigned t = 42;
t /= c;
return v + t;
}
int
main ()
{
unsigned char x = foo (7);
if (x)
__builtin_abort ();
if (bar (7) != 6)
__builtin_abort ();
return 0;
}