https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96783
--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
OK, so it seems the runtime alias check is hosed.
merged alias checks:
reference: MEM[(const struct _Vector_impl_data &)_254]._M_start vs.
MEM[(struct _Vector_impl_data *)_256]._M_start
segment length: 18446744073709551592(OVF)
access size: 24
alignment: 8
flags: WAR WAW ARBITRARY
that's a segment length of -24. The loop in question looks like
<bb 20> [local count: 347248109]:
# __i_373 = PHI <0(89), __i_263(98)>
# __p$_M_current_374 = PHI <_251(89), _254(98)>
# __q$_M_current_5 = PHI <_247(89), _256(98)>
_254 = __p$_M_current_374 + 18446744073709551592;
_256 = __q$_M_current_5 + 18446744073709551592;
_257 = MEM[(const struct _Vector_impl_data &)_254]._M_start;
_258 = MEM[(const struct _Vector_impl_data &)_254]._M_finish;
_259 = MEM[(const struct _Vector_impl_data &)_254]._M_end_of_storage;
_260 = MEM[(const struct _Vector_impl_data &)_256]._M_start;
MEM[(struct _Vector_impl_data *)_254]._M_start = _260;
_261 = MEM[(const struct _Vector_impl_data &)_256]._M_finish;
MEM[(struct _Vector_impl_data *)_254]._M_finish = _261;
_262 = MEM[(const struct _Vector_impl_data &)_256]._M_end_of_storage;
MEM[(struct _Vector_impl_data *)_254]._M_end_of_storage = _262;
MEM[(struct _Vector_impl_data *)_256]._M_start = _257;
MEM[(struct _Vector_impl_data *)_256]._M_finish = _258;
MEM[(struct _Vector_impl_data *)_256]._M_end_of_storage = _259;
__i_263 = __i_373 + 1;
if (__k_225 <= __i_263)
goto <bb 102>; [11.00%]
else
goto <bb 98>; [89.00%]
which looks like backwards walking swap of two arrays.
C testcase:
void __attribute__((noipa))
foo (long *a, int off, int n)
{
for (int i = 0; i < n; ++i)
{
long tem1 = a[0];
long tem2 = a[1];
long tem3 = a[2];
long tem4 = a[off + 1];
a[0] = tem4;
long tem5 = a[off + 2];
a[1] = tem5;
long tem6 = a[off + 3];
a[2] = tem6;
a[off + 1] = tem1;
a[off + 2] = tem2;
a[off + 3] = tem3;
a -= 3;
}
}
int main ()
{
long a[3 * 8];
for (int i = 0; i < 3 * 8; ++i)
a[i] = i;
foo (a + 3 * 5, 6-1, 5);
const long b[3 * 8] = { 0, 1, 2, 21, 22, 23, 18, 19, 20, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17 };
for (int i = 0; i < 3 * 8; ++i)
if (a[i] != b[i])
__builtin_abort ();
}