https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114322
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Target Milestone|--- |14.0
Last reconfirmed| |2024-03-13
Status|UNCONFIRMED |NEW
Ever confirmed|0 |1
--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
Confirmed. The issue is we have
{ x_12(D), +, 1 } * stride_11(D)
which doesn't behave the same with respect to overflow as
{ x_12(D) * stride_11(D), +, stride_11(D) }
and because of that we analyze it as
(int) {(unsigned) x_12(D) * (unsigned) stride_11(D), +, (unsigned)
stride_11(D) }
as it might wrap. But then then sign-extension to long unsigned int is
no longer affine.
_1 = x_12(D) + i_20;
_2 = _1 * stride_11(D);
_3 = (long unsigned int) _2;
_4 = _3 * 2;
_5 = A_13(D) + _4;
_6 = *_5;
The problematical case is x == N < 0 where the last - N might now
overflow with the new SCEV.
The correctness means that we'll now more often run into these issues
for IVs smaller than pointer width. With -m32 we can analyze the DR to
Creating dr for *_5
offset from base address: 0
constant offset from base address: 0
step: (ssizetype) ((unsigned int) stride_11(D) * 2)
base alignment: 2
base misalignment: 0
offset alignment: 256
step alignment: 2
base_object: *A_13(D) + (sizetype) ((unsigned int) stride_11(D) *
(unsigned int) x_12(D)) * 2
Access function 0: {0B, +, (unsigned int) stride_11(D) * 2}_1
If you had written
sum += A[i*stride + x*stride];
it might have worked but unfortunately EVRP transforms this back to
(i+x)*stride because it knows stride isn't zero.
In the end this means it's our failure that we fail to handle
2 * (unsigned long)({ x_12(D), +, 1 } * stride_11(D))
as valid evolution for further analysis - of course the multiplication
by two in an unsigned type might overflow as well.