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

Reply via email to