simplify-rtx: Fix up simplify_logical_relational_operation [PR119002]
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap |
fail
|
Build failed
|
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
fail
|
Build failed
|
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
Commit Message
Hi!
The following testcase is miscompiled on powerpc64le-linux starting with
r15-6777.
That change has the if (HONOR_NANS (GET_MODE (XEXP (op0, 0)))) all = 15;
lines which work fine if the comparisons use MODE_FLOAT or MODE_INT operands
(or say MODE_VECTOR* etc.). But on this testcase on ppc64le during combine
we see
(set (reg:SI 134)
(ior:SI (ge:SI (reg:CCFP 128)
(const_int 0 [0]))
(lt:SI (reg:CCFP 128)
(const_int 0 [0]))))
HONOR_NANS is obviously false on CCFPmode, because MODE_HAS_NANS is false,
it isn't FLOAT_MODE_P. But still it is a MODE_CC mode used for floating
point comparisons and so we need to consider the possibility of unordered
operands.
I'm not sure how we could look at the setter of those MODE_CC regs
from the simplifiers, after all they can happen in the middle of combiner
trying to combine multiple instructions.
So, instead the following patch attempts to be conservative for MODE_CC
with some exceptions. One is flag_finite_math_only, regardless of
MODE_HAS_NANS in that case HONOR_NANS will be always false.
Another one is for targets which provide REVERSE_CONDITION condition
and reverse one way the floating point MODE_CC modes and another the
integral ones. If REVERSE_CONDITION for GT gives LE, then unordered
is not an option. And finally it searches if there are any scalar floating
point modes with MODE_HAS_NANS at all, if not, it is also safe to
assume there are no NaNs.
Bootstrapped/regtested on x86_64-linux, i686-linux, powerpc64le-linux,
aarch64-linux and bootstrapped on s390x-linux (regtest there still pending).
Ok for trunk?
Or any other ideas how to handle this?
2025-02-24 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/119002
* simplify-rtx.cc: Include tm_p.h.
(simplify_context::simplify_logical_relational_operation): Set
all = 15 also if op0's first operand has MODE_CC mode and it
is or could be floating point comparison which honors NaNs.
* gcc.c-torture/execute/ieee/pr119002.c: New test.
Jakub
Comments
Jakub Jelinek <jakub@redhat.com> writes:
> Hi!
>
> The following testcase is miscompiled on powerpc64le-linux starting with
> r15-6777.
> That change has the if (HONOR_NANS (GET_MODE (XEXP (op0, 0)))) all = 15;
> lines which work fine if the comparisons use MODE_FLOAT or MODE_INT operands
> (or say MODE_VECTOR* etc.). But on this testcase on ppc64le during combine
> we see
> (set (reg:SI 134)
> (ior:SI (ge:SI (reg:CCFP 128)
> (const_int 0 [0]))
> (lt:SI (reg:CCFP 128)
> (const_int 0 [0]))))
> HONOR_NANS is obviously false on CCFPmode, because MODE_HAS_NANS is false,
> it isn't FLOAT_MODE_P. But still it is a MODE_CC mode used for floating
> point comparisons and so we need to consider the possibility of unordered
> operands.
> I'm not sure how we could look at the setter of those MODE_CC regs
> from the simplifiers, after all they can happen in the middle of combiner
> trying to combine multiple instructions.
> So, instead the following patch attempts to be conservative for MODE_CC
> with some exceptions. One is flag_finite_math_only, regardless of
> MODE_HAS_NANS in that case HONOR_NANS will be always false.
> Another one is for targets which provide REVERSE_CONDITION condition
> and reverse one way the floating point MODE_CC modes and another the
> integral ones. If REVERSE_CONDITION for GT gives LE, then unordered
> is not an option. And finally it searches if there are any scalar floating
> point modes with MODE_HAS_NANS at all, if not, it is also safe to
> assume there are no NaNs.
>
> Bootstrapped/regtested on x86_64-linux, i686-linux, powerpc64le-linux,
> aarch64-linux and bootstrapped on s390x-linux (regtest there still pending).
>
> Ok for trunk?
>
> Or any other ideas how to handle this?
I think we should instead go back to punting on comparisons whose inputs
are CC modes, as we did (indirectly, via comparison_code_valid_for_mode)
before r15-6777. Sorry, I'd forgotten/hadn't thought to exclude CC modes
explicitly when removing that function.
Richard
>
> 2025-02-24 Jakub Jelinek <jakub@redhat.com>
>
> PR rtl-optimization/119002
> * simplify-rtx.cc: Include tm_p.h.
> (simplify_context::simplify_logical_relational_operation): Set
> all = 15 also if op0's first operand has MODE_CC mode and it
> is or could be floating point comparison which honors NaNs.
>
> * gcc.c-torture/execute/ieee/pr119002.c: New test.
>
> --- gcc/simplify-rtx.cc.jj 2025-01-15 08:43:39.611918569 +0100
> +++ gcc/simplify-rtx.cc 2025-02-24 21:16:09.980758481 +0100
> @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.
> #include "selftest-rtl.h"
> #include "rtx-vector-builder.h"
> #include "rtlanal.h"
> +#include "tm_p.h"
>
> /* Simplification and canonicalization of RTL. */
>
> @@ -2675,6 +2676,24 @@ simplify_context::simplify_logical_relat
> /* See whether the operands might be unordered. */
> if (HONOR_NANS (GET_MODE (XEXP (op0, 0))))
> all = 15;
> + else if (GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC
> + && !flag_finite_math_only)
> + {
> + /* HONOR_NANS will be false for MODE_CC comparisons, eventhough
> + they could actually be floating point. If the mode is
> + reversible, ask the backend if it could be unordered, otherwise
> + err on the side of caution and assume it could be unordered
> + if any supported floating mode honors NaNs. */
> + machine_mode mode = GET_MODE (XEXP (op0, 0));
> + if (!REVERSIBLE_CC_MODE (mode)
> + || REVERSE_CONDITION (GT, mode) != LE)
> + FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
> + if (HONOR_NANS (mode))
> + {
> + all = 15;
> + break;
> + }
> + }
> mask0 = comparison_to_mask (code0) & all;
> mask1 = comparison_to_mask (code1) & all;
> }
>
> --- gcc/testsuite/gcc.c-torture/execute/ieee/pr119002.c.jj 2025-02-24 21:18:45.880622627 +0100
> +++ gcc/testsuite/gcc.c-torture/execute/ieee/pr119002.c 2025-02-24 21:19:02.418396051 +0100
> @@ -0,0 +1,23 @@
> +/* PR rtl-optimization/119002 */
> +
> +__attribute__((noipa)) unsigned int
> +foo (void *x, float y, float z)
> +{
> + unsigned int a, b;
> + float c, d, e;
> + c = y;
> + d = z;
> + a = c < d;
> + d = y;
> + e = z;
> + b = d >= e;
> + a |= b;
> + return a;
> +}
> +
> +int
> +main ()
> +{
> + if (foo ((void *) 0, 0.f, __builtin_nanf ("")))
> + __builtin_abort ();
> +}
>
> Jakub
On Mon, Mar 03, 2025 at 12:20:00PM +0000, Richard Sandiford wrote:
> I think we should instead go back to punting on comparisons whose inputs
> are CC modes, as we did (indirectly, via comparison_code_valid_for_mode)
> before r15-6777. Sorry, I'd forgotten/hadn't thought to exclude CC modes
> explicitly when removing that function.
I believe that is not what was the case before r15-6777.
We punted simply because comparison_to_mask returned for GE 6, for LT it
returned 8, 6 | 8 is not 15, no optimization.
There wasn't this all = 14 vs. 15 thing.
comparison_code_valid_for_mode is actually checking mode which is the mode
in which IOR is performed, e.g. SImode in the testcase.
So, do you want a simpler
if (GET_MODE (XEXP (op0, 0)) == MODE_CC
|| HONOR_NANS (GET_MODE (XEXP (op0, 0))))
all = 15;
or
if ((!INTEGRAL_MODE_P (GET_MODE (XEXP (op0, 0)))
&& !FLOAT_MODE_P (GET_MODE (XEXP (op0, 0)))
&& !VECTOR_MODE_P (GET_MODE (XEXP (op0, 0))))
|| HONOR_NANS (GET_MODE (XEXP (op0, 0))))
all = 15;
or something else?
Jakub
Jakub Jelinek <jakub@redhat.com> writes:
> On Mon, Mar 03, 2025 at 12:20:00PM +0000, Richard Sandiford wrote:
>> I think we should instead go back to punting on comparisons whose inputs
>> are CC modes, as we did (indirectly, via comparison_code_valid_for_mode)
>> before r15-6777. Sorry, I'd forgotten/hadn't thought to exclude CC modes
>> explicitly when removing that function.
>
> I believe that is not what was the case before r15-6777.
> We punted simply because comparison_to_mask returned for GE 6, for LT it
> returned 8, 6 | 8 is not 15, no optimization.
> There wasn't this all = 14 vs. 15 thing.
> comparison_code_valid_for_mode is actually checking mode which is the mode
> in which IOR is performed, e.g. SImode in the testcase.
Ah, right. But like I said in the covering note, that choice of mode
seemed to be unintentional (since it should never be a floating-point
mode, and even if it were, the mode of the IOR wouldn't affect whether
something like ORDERED is valid).
So I still think that punting (returning 0) on CC modes would be safer.
We just don't have enough information to tell what a CCmode value represents.
If that seems too conservative, and in particular if we want to preserve
the old "all true" optimisation, then...
> So, do you want a simpler
> if (GET_MODE (XEXP (op0, 0)) == MODE_CC
> || HONOR_NANS (GET_MODE (XEXP (op0, 0))))
> all = 15;
> or
> if ((!INTEGRAL_MODE_P (GET_MODE (XEXP (op0, 0)))
> && !FLOAT_MODE_P (GET_MODE (XEXP (op0, 0)))
> && !VECTOR_MODE_P (GET_MODE (XEXP (op0, 0))))
> || HONOR_NANS (GET_MODE (XEXP (op0, 0))))
> all = 15;
> or something else?
...how about something like this? Completely untested, and I haven't
thought about it much. Just didn't want to hold up the discussion.
Thanks,
Richard
diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index c478bd060fc..d20aa518a64 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -2655,6 +2655,7 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
enum rtx_code code0 = GET_CODE (op0);
enum rtx_code code1 = GET_CODE (op1);
+ machine_mode cmp_mode = GET_MODE (XEXP (op0, 0));
/* Assume at first that the comparisons are on integers, and that the
operands are therefore ordered. */
@@ -2672,8 +2673,10 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
}
else
{
- /* See whether the operands might be unordered. */
- if (HONOR_NANS (GET_MODE (XEXP (op0, 0))))
+ /* See whether the operands might be unordered. Assume that all
+ results are possible for CC modes, and punt later if don't get
+ an all-true or all-false answer. */
+ if (GET_MODE_CLASS (cmp_mode) == MODE_CC || HONOR_NANS (cmp_mode))
all = 15;
mask0 = comparison_to_mask (code0) & all;
mask1 = comparison_to_mask (code1) & all;
@@ -2702,6 +2705,9 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
code = mask_to_unsigned_comparison (mask);
else
{
+ if (GET_MODE_CLASS (cmp_mode) == MODE_CC)
+ return 0;
+
code = mask_to_comparison (mask);
/* LTGT and NE are arithmetically equivalent for ordered operands,
with NE being the canonical choice. */
On Mon, Mar 03, 2025 at 01:02:07PM +0000, Richard Sandiford wrote:
> ...how about something like this? Completely untested, and I haven't
> thought about it much. Just didn't want to hold up the discussion.
Works for me.
Just wonder if there is anything that will actually verify that XEXP (op0, 0)
and XEXP (op1, 0) modes are at least from the same class, rather than say
have one of the comparisons in MODE_CC and another in MODE_INT or vice versa
or whatever other modes.
> --- a/gcc/simplify-rtx.cc
> +++ b/gcc/simplify-rtx.cc
> @@ -2655,6 +2655,7 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
>
> enum rtx_code code0 = GET_CODE (op0);
> enum rtx_code code1 = GET_CODE (op1);
> + machine_mode cmp_mode = GET_MODE (XEXP (op0, 0));
>
> /* Assume at first that the comparisons are on integers, and that the
> operands are therefore ordered. */
> @@ -2672,8 +2673,10 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
> }
> else
> {
> - /* See whether the operands might be unordered. */
> - if (HONOR_NANS (GET_MODE (XEXP (op0, 0))))
> + /* See whether the operands might be unordered. Assume that all
> + results are possible for CC modes, and punt later if don't get
> + an all-true or all-false answer. */
> + if (GET_MODE_CLASS (cmp_mode) == MODE_CC || HONOR_NANS (cmp_mode))
> all = 15;
> mask0 = comparison_to_mask (code0) & all;
> mask1 = comparison_to_mask (code1) & all;
> @@ -2702,6 +2705,9 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
> code = mask_to_unsigned_comparison (mask);
> else
> {
> + if (GET_MODE_CLASS (cmp_mode) == MODE_CC)
> + return 0;
> +
> code = mask_to_comparison (mask);
> /* LTGT and NE are arithmetically equivalent for ordered operands,
> with NE being the canonical choice. */
Jakub
Jakub Jelinek <jakub@redhat.com> writes:
> On Mon, Mar 03, 2025 at 01:02:07PM +0000, Richard Sandiford wrote:
>> ...how about something like this? Completely untested, and I haven't
>> thought about it much. Just didn't want to hold up the discussion.
>
> Works for me.
>
> Just wonder if there is anything that will actually verify that XEXP (op0, 0)
> and XEXP (op1, 0) modes are at least from the same class, rather than say
> have one of the comparisons in MODE_CC and another in MODE_INT or vice versa
> or whatever other modes.
There's:
if (!(rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
&& rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1))))
return 0;
But I suppose there's the (separate) question of whether (const_int 0)
can be the first operand and the CC value the second. AIUI that ought
to be canonicalised to the opposite order, but if we're relying on the
order for correctness, perhaps we should check.
Thanks,
Richard
>
>> --- a/gcc/simplify-rtx.cc
>> +++ b/gcc/simplify-rtx.cc
>> @@ -2655,6 +2655,7 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
>>
>> enum rtx_code code0 = GET_CODE (op0);
>> enum rtx_code code1 = GET_CODE (op1);
>> + machine_mode cmp_mode = GET_MODE (XEXP (op0, 0));
>>
>> /* Assume at first that the comparisons are on integers, and that the
>> operands are therefore ordered. */
>> @@ -2672,8 +2673,10 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
>> }
>> else
>> {
>> - /* See whether the operands might be unordered. */
>> - if (HONOR_NANS (GET_MODE (XEXP (op0, 0))))
>> + /* See whether the operands might be unordered. Assume that all
>> + results are possible for CC modes, and punt later if don't get
>> + an all-true or all-false answer. */
>> + if (GET_MODE_CLASS (cmp_mode) == MODE_CC || HONOR_NANS (cmp_mode))
>> all = 15;
>> mask0 = comparison_to_mask (code0) & all;
>> mask1 = comparison_to_mask (code1) & all;
>> @@ -2702,6 +2705,9 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
>> code = mask_to_unsigned_comparison (mask);
>> else
>> {
>> + if (GET_MODE_CLASS (cmp_mode) == MODE_CC)
>> + return 0;
>> +
>> code = mask_to_comparison (mask);
>> /* LTGT and NE are arithmetically equivalent for ordered operands,
>> with NE being the canonical choice. */
>
> Jakub
On Mon, Mar 03, 2025 at 01:46:20PM +0000, Richard Sandiford wrote:
> Jakub Jelinek <jakub@redhat.com> writes:
> > On Mon, Mar 03, 2025 at 01:02:07PM +0000, Richard Sandiford wrote:
> >> ...how about something like this? Completely untested, and I haven't
> >> thought about it much. Just didn't want to hold up the discussion.
> >
> > Works for me.
> >
> > Just wonder if there is anything that will actually verify that XEXP (op0, 0)
> > and XEXP (op1, 0) modes are at least from the same class, rather than say
> > have one of the comparisons in MODE_CC and another in MODE_INT or vice versa
> > or whatever other modes.
>
> There's:
>
> if (!(rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
> && rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1))))
> return 0;
You're right, and rtx_equal_p returns false for GET_MODE differences.
Will you test your patch (with the testcase from my patch) or should I?
Jakub
Jakub Jelinek <jakub@redhat.com> writes:
> On Mon, Mar 03, 2025 at 01:46:20PM +0000, Richard Sandiford wrote:
>> Jakub Jelinek <jakub@redhat.com> writes:
>> > On Mon, Mar 03, 2025 at 01:02:07PM +0000, Richard Sandiford wrote:
>> >> ...how about something like this? Completely untested, and I haven't
>> >> thought about it much. Just didn't want to hold up the discussion.
>> >
>> > Works for me.
>> >
>> > Just wonder if there is anything that will actually verify that XEXP (op0, 0)
>> > and XEXP (op1, 0) modes are at least from the same class, rather than say
>> > have one of the comparisons in MODE_CC and another in MODE_INT or vice versa
>> > or whatever other modes.
>>
>> There's:
>>
>> if (!(rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
>> && rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1))))
>> return 0;
>
> You're right, and rtx_equal_p returns false for GET_MODE differences.
>
> Will you test your patch (with the testcase from my patch) or should I?
I'm just about to test it with a tweak to the mode check. Should be
done in a couple of hours.
Thanks,
Richard
Richard Sandiford <richard.sandiford@arm.com> writes:
> Jakub Jelinek <jakub@redhat.com> writes:
>> On Mon, Mar 03, 2025 at 01:46:20PM +0000, Richard Sandiford wrote:
>>> Jakub Jelinek <jakub@redhat.com> writes:
>>> > On Mon, Mar 03, 2025 at 01:02:07PM +0000, Richard Sandiford wrote:
>>> >> ...how about something like this? Completely untested, and I haven't
>>> >> thought about it much. Just didn't want to hold up the discussion.
>>> >
>>> > Works for me.
>>> >
>>> > Just wonder if there is anything that will actually verify that XEXP (op0, 0)
>>> > and XEXP (op1, 0) modes are at least from the same class, rather than say
>>> > have one of the comparisons in MODE_CC and another in MODE_INT or vice versa
>>> > or whatever other modes.
>>>
>>> There's:
>>>
>>> if (!(rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
>>> && rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1))))
>>> return 0;
>>
>> You're right, and rtx_equal_p returns false for GET_MODE differences.
>>
>> Will you test your patch (with the testcase from my patch) or should I?
>
> I'm just about to test it with a tweak to the mode check. Should be
> done in a couple of hours.
Heh. Forgot when I said that that I would need to test on powerpc64le
as well, which isn't something I do regularly, and so took a couple of
gos to get right. I've now bootstrapped & regression-tested on both
powerpc64le-linux-gnu and aarch64-linux-gnu. OK to install?
Richard
The following testcase is miscompiled on powerpc64le-linux starting with
r15-6777. During combine we see:
(set (reg:SI 134)
(ior:SI (ge:SI (reg:CCFP 128)
(const_int 0 [0]))
(lt:SI (reg:CCFP 128)
(const_int 0 [0]))))
The simplify_logical_relational_operation code (in its current form)
was written with arithmetic rather than CC modes in mind. Since CCFP
is a CC mode, it fails the HONOR_NANS check, and so the function assumes
that ge | lt => true.
If one comparison is unsigned then it should be safe to assume that
the other comparison is also unsigned, even for CC modes, since the
optimisation checks that the comparisons are between the same operands.
For the other cases, we can only safely fold comparisons of CC mode
values if the result is always-true (15) or always-false (0).
It turns out that the original testcase for PR117186, which ran at -O,
was relying on the old behaviour for some of the functions. It needs
4-instruction combinations, and so -fexpensive-optimizations, to pass
in its intended form.
gcc/
PR rtl-optimization/119002
* simplify-rtx.cc
(simplify_context::simplify_logical_relational_operation): Handle
comparisons between CC values. If there is no evidence that the
CC values are unsigned, restrict the fold to always-true or
always-false results.
gcc/testsuite/
* gcc.c-torture/execute/ieee/pr119002.c: New test.
* gcc.target/aarch64/pr117186.c: Run at -O2 rather than -O.
Co-authored-by: Jakub Jelinek <jakub@redhat.com>
---
gcc/simplify-rtx.cc | 12 ++++++++--
.../gcc.c-torture/execute/ieee/pr119002.c | 23 +++++++++++++++++++
gcc/testsuite/gcc.target/aarch64/pr117186.c | 2 +-
3 files changed, 34 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.c-torture/execute/ieee/pr119002.c
diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index c478bd060fc..fe007bc7d96 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -2655,6 +2655,9 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
enum rtx_code code0 = GET_CODE (op0);
enum rtx_code code1 = GET_CODE (op1);
+ machine_mode cmp_mode = GET_MODE (XEXP (op0, 0));
+ if (cmp_mode == VOIDmode)
+ cmp_mode = GET_MODE (XEXP (op0, 1));
/* Assume at first that the comparisons are on integers, and that the
operands are therefore ordered. */
@@ -2672,8 +2675,10 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
}
else
{
- /* See whether the operands might be unordered. */
- if (HONOR_NANS (GET_MODE (XEXP (op0, 0))))
+ /* See whether the operands might be unordered. Assume that all
+ results are possible for CC modes, and punt later if we don't get an
+ always-true or always-false answer. */
+ if (GET_MODE_CLASS (cmp_mode) == MODE_CC || HONOR_NANS (cmp_mode))
all = 15;
mask0 = comparison_to_mask (code0) & all;
mask1 = comparison_to_mask (code1) & all;
@@ -2702,6 +2707,9 @@ simplify_context::simplify_logical_relational_operation (rtx_code code,
code = mask_to_unsigned_comparison (mask);
else
{
+ if (GET_MODE_CLASS (cmp_mode) == MODE_CC)
+ return 0;
+
code = mask_to_comparison (mask);
/* LTGT and NE are arithmetically equivalent for ordered operands,
with NE being the canonical choice. */
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/pr119002.c b/gcc/testsuite/gcc.c-torture/execute/ieee/pr119002.c
new file mode 100644
index 00000000000..af1a705f170
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/pr119002.c
@@ -0,0 +1,23 @@
+/* PR rtl-optimization/119002 */
+
+__attribute__((noipa)) unsigned int
+foo (void *x, float y, float z)
+{
+ unsigned int a, b;
+ float c, d, e;
+ c = y;
+ d = z;
+ a = c < d;
+ d = y;
+ e = z;
+ b = d >= e;
+ a |= b;
+ return a;
+}
+
+int
+main ()
+{
+ if (foo ((void *) 0, 0.f, __builtin_nanf ("")))
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr117186.c b/gcc/testsuite/gcc.target/aarch64/pr117186.c
index afe3c25a493..3090f2c11d5 100644
--- a/gcc/testsuite/gcc.target/aarch64/pr117186.c
+++ b/gcc/testsuite/gcc.target/aarch64/pr117186.c
@@ -1,4 +1,4 @@
-/* { dg-options "-O" } */
+/* { dg-options "-O2" } */
/* { dg-final { check-function-bodies "**" "" "" } } */
/*
On Tue, Mar 04, 2025 at 09:26:07AM +0000, Richard Sandiford wrote:
> gcc/
> PR rtl-optimization/119002
> * simplify-rtx.cc
> (simplify_context::simplify_logical_relational_operation): Handle
> comparisons between CC values. If there is no evidence that the
> CC values are unsigned, restrict the fold to always-true or
> always-false results.
>
> gcc/testsuite/
> * gcc.c-torture/execute/ieee/pr119002.c: New test.
> * gcc.target/aarch64/pr117186.c: Run at -O2 rather than -O.
LGTM.
Jakub
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.
#include "selftest-rtl.h"
#include "rtx-vector-builder.h"
#include "rtlanal.h"
+#include "tm_p.h"
/* Simplification and canonicalization of RTL. */
@@ -2675,6 +2676,24 @@ simplify_context::simplify_logical_relat
/* See whether the operands might be unordered. */
if (HONOR_NANS (GET_MODE (XEXP (op0, 0))))
all = 15;
+ else if (GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC
+ && !flag_finite_math_only)
+ {
+ /* HONOR_NANS will be false for MODE_CC comparisons, eventhough
+ they could actually be floating point. If the mode is
+ reversible, ask the backend if it could be unordered, otherwise
+ err on the side of caution and assume it could be unordered
+ if any supported floating mode honors NaNs. */
+ machine_mode mode = GET_MODE (XEXP (op0, 0));
+ if (!REVERSIBLE_CC_MODE (mode)
+ || REVERSE_CONDITION (GT, mode) != LE)
+ FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
+ if (HONOR_NANS (mode))
+ {
+ all = 15;
+ break;
+ }
+ }
mask0 = comparison_to_mask (code0) & all;
mask1 = comparison_to_mask (code1) & all;
}
@@ -0,0 +1,23 @@
+/* PR rtl-optimization/119002 */
+
+__attribute__((noipa)) unsigned int
+foo (void *x, float y, float z)
+{
+ unsigned int a, b;
+ float c, d, e;
+ c = y;
+ d = z;
+ a = c < d;
+ d = y;
+ e = z;
+ b = d >= e;
+ a |= b;
+ return a;
+}
+
+int
+main ()
+{
+ if (foo ((void *) 0, 0.f, __builtin_nanf ("")))
+ __builtin_abort ();
+}