https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128599
Bug ID: 128599
Summary: [16/17 Regression] Page overread with early break
vectorisation (lucas from SPEC2000)
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: ktkachov at gcc dot gnu.org
Target Milestone: ---
We got a report about the lucas benchmark from SPEC2000 aborting when compiled
with -O3 -msse4.2 on x86_64. I have reproduced this and on aarch64 as well and
with the help of an LLM have a generic testcase:
#include <signal.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#define N 1000000
/* Scans down to the nonzero sentinel a[0]. The vectorizer peels for
alignment, but for a negative step the extra vector loads of an iteration
lie below the aligned address, so the last iteration reads below a[0]. */
__attribute__((noipa)) int
scan (double *a, int n)
{
int j = n - 1;
while (a[j] == 0)
j--;
return j;
}
static void
handler (int s)
{
__builtin_abort ();
}
int
main (void)
{
size_t pg = sysconf (_SC_PAGESIZE), bytes = N * sizeof (double);
signal (SIGSEGV, handler);
signal (SIGBUS, handler);
for (size_t off = 0; off < 64; off += sizeof (double))
{
char *m = mmap (0, bytes + 2 * pg, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (m == MAP_FAILED)
return 0;
/* Guard page directly below a[0]. */
mprotect (m, pg, PROT_NONE);
double *a = (double *) (m + pg + off);
memset (a, 0, bytes);
a[0] = 1;
if (scan (a, N) != 0)
__builtin_abort ();
munmap (m, bytes + 2 * pg);
}
return 0;
}
This aborts on aarch64 at -O3 and passes at lower vectorisation levels