On 10/22/26 5:48 PM, Jeff Law wrote:
> Is this still relevant or is it subsumed by the if-combine fix?

It is still needed.  The ifcombine fix (r17-4921, "Preserve comparison
operand order when if-combining") makes ifcombine pass the comparisons
in evaluation order, which covers the short-circuited case.  This patch
is about the callers that combine two comparisons that are both
evaluated: reassoc, for the operands of a BIT_AND_EXPR or BIT_IOR_EXPR,
and if-conversion's fold_or_predicates.  They still pass
TRUTH_ANDIF_EXPR/TRUTH_ORIF_EXPR, so combine_comparisons may drop the
exception of the second comparison.  On current trunk at -O2 on
x86_64, all three examples in the patch still return without raising
FE_INVALID for a quiet NaN operand; with the patch they raise it.

It does not depend on patch 1/2, so I will repost it on its own as v2,
rebased onto current trunk, with its execution test in a file of its own
(in this version it adds to the test that patch 1/2 creates).

Igor



________________________________
From: Jeff Law <[email protected]>
Sent: Thursday, October 22, 2026 5:48:18 PM
To: Igor Shevlyakov; [email protected]
Cc: [email protected]; [email protected]
Subject: Re: [PATCH 2/2] gimple-fold: Combine two comparisons as both evaluated 
[PR127786]

[EXTERNAL] Caution: This email originated from outside of the organization. Do 
not click links or open attachments unless you recognize the sender and know 
the content is safe.



On 10/9/26 10:55 AM, Igor Shevlyakov wrote:
> and_comparisons_1 and or_comparisons_1 pass TRUTH_ANDIF_EXPR and
> TRUTH_ORIF_EXPR to combine_comparisons.  Under -ftrapping-math those
> codes tell it that the second comparison is only evaluated when the
> first does not decide the result, so it may drop the exception the
> second one raises.  That is wrong for reassoc, which combines the
> operands of a BIT_AND_EXPR or BIT_IOR_EXPR, both of them evaluated:
>
> - !__builtin_isgreaterequal (a, b) | (a > b) became a quiet a != b,
>    dropping the FE_INVALID that a > b raises for a NaN;
> - (a <= b) & (a == b) became a quiet a == b;
> - a < b || __builtin_isunordered (a, b), once phiopt has made both
>    comparisons unconditional, became a quiet a u< b.
>
> if-conversion's fold_or_predicates likewise combines block predicates
> that the if-converted code computes unconditionally.
>
> Pass TRUTH_AND_EXPR and TRUTH_OR_EXPR instead, as
> fold_truth_andor_for_ifcombine already does.  combine_comparisons then
> requires the combined comparison to trap exactly when one of the two
> does.  ifcombine, the one caller whose conditions are short-circuited,
> loses nothing: since r17-4921 it passes them in evaluation order, it
> combines an inner condition that can trap itself, with TRUTH_ANDIF_EXPR,
> and it only calls maybe_fold_and_comparisons for one that cannot.  For a
> second comparison that cannot trap the short-circuit rules of
> combine_comparisons make no difference.  fp-trapping-cmp-8.c checks that
> ifcombine still merges if (a == b) if (a <= b) into a == b.
>
> A combination that folds to a constant, e.g. (a < b) & (a > b) -> 0,
> can still lose the exception, as x < x -> 0 does.
>
>        PR middle-end/127786
>
> gcc/ChangeLog:
>
>        * gimple-fold.cc (and_comparisons_1): Pass TRUTH_AND_EXPR to
>        combine_comparisons.
>        (or_comparisons_1): Pass TRUTH_OR_EXPR to combine_comparisons.
>
> gcc/testsuite/ChangeLog:
>
>        * gcc.dg/torture/cmp-of-cmp-fenv.c (unlt_or_gt, le_and_eq)
>        (le_then_eq, lt_orif_uno): New functions.
>        (tests): Add them.
>        * gcc.dg/tree-ssa/fp-trapping-cmp-8.c: New test.
>
> Signed-off-by: Igor Shevlyakov <[email protected]>
Is this still relevant or is it subsumed by the if-combine fix?

Jeff


Reply via email to