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

            Bug ID: 126565
           Summary: [16/17 Regression] Wrong code with optimising
                    std::partial_ordering::_M_reverse -styler patterns in
                    phiopt
           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 in phiopt, tree-ssa-phiopt.cc:2214, spaceship_replacement.

   ROOT CAUSE.  The std::partial_ordering::_M_reverse recogniser tests

       if (TYPE_PRECISION (ty2) != 8 || TYPE_PRECISION (ty1) < 8)

   where ty1 is the type of phires.  It has to be != 8, not < 8.  The chain

       _1 = (unsigned char) phires;   _2 = -_1;   _3 = (ty1) _2;

   only reverses the order when ty1 is itself 8 bits wide, because then the
   final cast is a reinterpretation.  With ty1 == int it is a zero extension
   and the real mapping is -1 -> 1, 0 -> 0, 1 -> 255, so "_3 > 0" means
   "phires != 0", i.e. "x != y".  spaceship_replacement applies
   swap_tree_comparison at line 2563 as though the chain were a reversal and
   emits "x < y" instead.

   -O1 -fno-tree-forwprop.  The flag is needed only to stop match.pd narrowing
   (int)uchar CMP cst back to an 8 bit compare, which destroys the chain before
   phiopt sees it; -O2 and above additionally need -fno-tree-vrp.  Clean with
   -fno-ssa-phiopt.  */

__attribute__((noipa)) int
f (int x, int y)
{
  int c;
  unsigned char d, e;
  int g;

  if (x == y)
    c = 0;
  else if (x < y)
    c = -1;
  else
    c = 1;

  d = c;                        /* 0 -> 0,  -1 -> 255,  1 -> 1 */
  e = -d;                       /* 0 -> 0,  255 -> 1,   1 -> 255 */
  g = e;                        /* zero extension, NOT a reversal */
  return g > 0;
}

int
main (void)
{
  volatile int i, j;

  /* g is 0 exactly when c is 0, so "g > 0" is "x != y".  */
  for (i = -3; i <= 3; i++)
    for (j = -3; j <= 3; j++)
      if (f (i, j) != (i != j))
        __builtin_abort ();
  return 0;
}

This aborts on aarch64 at -O1 -fno-tree-forwprop

Reply via email to