https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127786
Bug ID: 127786
Summary: Combining two evaluated FP comparisons drops
FE_INVALID under -ftrapping-math
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: igor at tachyum dot com
Target Milestone: ---
Host: x86_64-pc-linux-gnu
Target: x86_64-pc-linux-gnu
Build: x86_64-pc-linux-gnu
Created attachment 65788
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65788&action=edit
combine-cmp.c
When two comparisons of the same operands are both evaluated, combining
them must keep the FE_INVALID that either one raises for a quiet NaN. The
attached testcase aborts at -O1 and -O2 on x86_64 trunk (r17-4942) and on
GCC 16.2 (it passes at -O0):
$ gcc -O2 combined-cmp.c -lm && ./a.out
Aborted
All three functions lose FE_INVALID for (NaN, 1.0):
/* a < b (signaling) | a > b: becomes a quiet a != b. */
int unlt_or_gt (double a, double b)
{ return !__builtin_isgreaterequal (a, b) | (a > b); }
/* a <= b (signaling) & a == b: becomes a quiet a == b. */
int le_and_eq (double a, double b) { return (a <= b) & (a == b); }
/* a < b is always evaluated, then isunordered: becomes a quiet UNLT. */
int lt_orif_uno (double a, double b)
{ return a < b || __builtin_isunordered (a, b); }
and_comparisons_1 / or_comparisons_1 (gimple-fold.cc) pass TRUTH_ANDIF_EXPR
and TRUTH_ORIF_EXPR to combine_comparisons. Under trapping math those codes
tell it that the second comparison is only evaluated when the first does
not decide the result, so the exception of the second may be dropped. That
does not hold for their callers: reassoc and if-conversion combine
comparisons that are both evaluated, and maybe_fold_and_comparisons /
maybe_fold_or_comparisons try both operand orders (ifcombine passes the
inner condition first), so the short-circuit reasoning is applied in the
wrong order. The RTL side (simplify-rtx's combining of comparisons) has
the same issue for targets where it is reached.
Related: PR126295 (a missed optimization in the same code), PR127649
(vectorized LTGT losing FE_INVALID). Patches to follow.