https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126491

            Bug ID: 126491
           Summary: [13/14/15/16/17 Regression] Wrong code with
                    address_compare
           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: ---

/* Wrong code: address_compare () (gcc/fold-const.cc:16483) computes
   equal == 2 ("cannot decide") for these pairs at fold-const.cc:16614-16631,
   then throws that verdict away at fold-const.cc:16672-16676

     if (!INTEGRAL_TYPE_P (type))
       return 0;

   and reports "known unequal" for every pointer-typed comparison.
   match.pd:8393-8396 folds the == to constant false, yet the very same two
   addresses compare equal at run time in the same program.

   Free of undefined behaviour: forming and comparing a one-past-the-end
   pointer is allowed, == between pointers to distinct objects is a defined
   comparison, and no object is dereferenced.  */

char e0[0];
char e1[0];
struct E { };
struct E es1, es2;
char g1[16];
char g2[16];

/* Run-time reference: a single comparison the optimiser cannot fold.  */
__attribute__((noipa)) int rt (void *a, void *b) { return a == b; }

__attribute__((noipa)) void chk (int folded, int runtime)
{
  if (folded != runtime)
    __builtin_abort ();
}

int main (void)
{
  /* Zero-sized objects are placed at one and the same address, so both of
     these compare equal at run time.  The fold says "unequal".  */
  chk (&e0[0] == &e1[0], rt (&e0[0], &e1[0]));
  chk ((char *) &es1 == (char *) &es2, rt ((char *) &es1, (char *) &es2));

  /* C11 6.5.9p6: a one-past-the-end pointer compares equal to a pointer to
     the start of an object that immediately follows it in the address space.
     Whichever of g1/g2 the compiler lays out first, one of the two lines
     below is such a pair at run time.  Both fold to constant false.  */
  chk (&g1[16] == &g2[0], rt (&g1[16], &g2[0]));
  chk (&g2[16] == &g1[0], rt (&g2[16], &g1[0]));

  return 0;
}

aborts at -O2 since GCC 10 on aarch64

Reply via email to