[Bug tree-optimization/126491] New: [13/14/15/16/17 Regression] Wrong code with address_compare

"ktkachov at gcc dot gnu.org via Gcc-bugs" <[email protected]>
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.