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

            Bug ID: 126564
           Summary: [16/17 Regression] Wrong code with
                    spaceship_replacement
           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:2431-2441, spaceship_replacement.

   ROOT CAUSE.  In the 4-predecessor !HONOR_NANS direction-consistency check
   the cond1 term folds in e1's TRUE/FALSE polarity:

       (e1->flags & ((cmp1 == LT_EXPR || cmp1 == LE_EXPR)
                     ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) != 0

   but lines 2400-2410 have already pinned the +-1 value to the cmp1-TRUE path
   in BOTH polarities, so this term must not consult the edge flags at all.
   The HONOR_NANS arm of the very same guard (2433-2434) uses the raw
   comparison codes and ignores the flags, which is the correct formulation.

   When e1 is the FALSE edge the test is therefore inverted: correct
   spaceships are rejected, and only the degenerate ones, where cond1 repeats
   cond2's direction and so can never be true, are accepted.  one_cmp is then
   derived from an arm that is unreachable, and the rewritten comparison has
   nothing to do with the original value.

   -O1.  At -O2 and above ranger folds the redundant "x <= y" before phiopt
   runs, so add -fno-tree-vrp there.  Clean with -fno-ssa-phiopt.  */

__attribute__((noipa)) int
f (int x, int y)
{
  int c = -128;
  if (x == y)
    c = 0;
  else if (x < y)
    c = -1;
  else if (x <= y)              /* unreachable: x > y holds here */
    c = 1;
  return c > 0;
}

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

  /* c only ever takes the values 0, -1 and -128, so "c > 0" is false for
     every input.  phiopt rewrites the whole function to "x < y".  */
  for (i = -3; i <= 3; i++)
    for (j = -3; j <= 3; j++)
      if (f (i, j) != 0)
        __builtin_abort ();
  return 0;
}

Aborts on aarch64 at -O1 (but not at -O2, as per the comment)

Reply via email to