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