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)