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.

Reply via email to