aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2025-12-08 10:14:19 +0100
committerRichard Biener <rguenther@suse.de>2025-12-09 08:53:16 +0100
commite3a60357520bc3d14a098ca748c49c44f97b03f5 (patch)
treead8ff71ba1b1072615298ff937dbbb0837bd0d0b
parentcf22e30f0cfae65dd012966cab657583e2be667e (diff)
downloadgcc-e3a60357520bc3d14a098ca748c49c44f97b03f5.zip
gcc-e3a60357520bc3d14a098ca748c49c44f97b03f5.tar.gz
gcc-e3a60357520bc3d14a098ca748c49c44f97b03f5.tar.bz2
target/123027 - handle min/max expansion when -ffinite-math-only
When we get a <= b ? b : a into ix86_expand_sse_fp_minmax we can swap and invert this with -ffinite-math-only to get a < b ? a : b. PR target/123027 * config/i386/i386-expand.cc (ix86_expand_sse_fp_minmax): With !HONOR_NANS we can handle LE by swapping and inverting. * gcc.target/i386/pr123027.c: New testcase. * gcc.dg/torture/pr123027.c: Likewise.
-rw-r--r--gcc/config/i386/i386-expand.cc9
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr123027.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/pr123027.c15
3 files changed, 42 insertions, 2 deletions
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index fd9bcaa..438fa4e 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -4159,12 +4159,18 @@ static bool
ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
rtx cmp_op1, rtx if_true, rtx if_false)
{
- machine_mode mode;
+ machine_mode mode = GET_MODE (dest);
bool is_min;
rtx tmp;
if (code == LT)
;
+ else if (code == LE && !HONOR_NANS (mode))
+ {
+ /* We can swap LE to GE and then invert to LT. */
+ std::swap (cmp_op0, cmp_op1);
+ std::swap (if_true, if_false);
+ }
else if (code == UNGE)
std::swap (if_true, if_false);
else
@@ -4177,7 +4183,6 @@ ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
else
return false;
- mode = GET_MODE (dest);
if (immediate_operand (if_false, mode))
if_false = force_reg (mode, if_false);
if (immediate_operand (if_true, mode))
diff --git a/gcc/testsuite/gcc.dg/torture/pr123027.c b/gcc/testsuite/gcc.dg/torture/pr123027.c
new file mode 100644
index 0000000..cba4cc9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr123027.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-ffinite-math-only" } */
+/* { dg-add-options ieee } */
+
+double a = 0.0;
+double b = -0.0;
+
+int main()
+{
+ double min1 = a < b ? a : b;
+ double max1 = a > b ? a : b;
+ double min2 = b < a ? b : a;
+ double max2 = b > a ? b : a;
+ if (__builtin_copysign (1., min1) != -1.
+ || __builtin_copysign (1., max1) != -1.
+ || __builtin_copysign (1., min2) != 1.
+ || __builtin_copysign (1., max2) != 1.)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr123027.c b/gcc/testsuite/gcc.target/i386/pr123027.c
new file mode 100644
index 0000000..b7effac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr123027.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mfpmath=sse -ffinite-math-only" } */
+
+float foo (float a, float b)
+{
+ return a < b ? a : b;
+}
+
+float bar (float a, float b)
+{
+ return a > b ? a : b;
+}
+
+/* { dg-final { scan-assembler-times "minss" 1 } } */
+/* { dg-final { scan-assembler-times "maxss" 1 } } */