https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122104
Bug ID: 122104
Summary: Incorrect range after widening_mul
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: kristerw at gcc dot gnu.org
Target Milestone: ---
The widening_mul pass makes the following function more UB when compiled for
x86_64 with -O2 or higher:
int
f21 (int x)
{
int r = (unsigned) x * 35;
return x && ((unsigned) r / x) != 35U;
}
The IR before the widening_mul pass looks like
int f21 (int x)
{
unsigned int x.0_1;
unsigned int _2;
unsigned int _3;
int iftmp.1_4;
_Bool _7;
int _8;
<bb 2> :
if (x_5(D) != 0)
goto <bb 3>;
else
goto <bb 4>;
<bb 3> :
x.0_1 = (unsigned int) x_5(D);
_2 = x.0_1 * 35;
_3 = _2 / x.0_1;
_7 = _3 != 35;
_8 = (int) _7;
<bb 4> :
# iftmp.1_4 = PHI <_8(3), 0(2)>
return iftmp.1_4;
}
where x.0_1 has a range:
x.0_1 = [irange] unsigned int [1, +INF]
The widening_mul pass changes the code to
int f21 (int x)
{
unsigned int x.0_1;
unsigned int _2;
_Bool _7;
int _8;
__complex__ unsigned int _9;
unsigned int _10;
<bb 2> :
x.0_1 = (unsigned int) x_5(D);
_9 = .MUL_OVERFLOW (x.0_1, 35);
_2 = REALPART_EXPR <_9>;
_10 = IMAGPART_EXPR <_9>;
_7 = _10 != 0;
_8 = (int) _7;
return _8;
}
where x.0_1 keeps the range:
x.0_1 = [irange] unsigned int [1, +INF]
which is incorrect now when the if-statement has been removed.