diff options
| author | Richard Biener <rguenther@suse.de> | 2025-12-08 10:14:19 +0100 |
|---|---|---|
| committer | Richard Biener <rguenther@suse.de> | 2025-12-09 08:53:16 +0100 |
| commit | e3a60357520bc3d14a098ca748c49c44f97b03f5 (patch) | |
| tree | ad8ff71ba1b1072615298ff937dbbb0837bd0d0b | |
| parent | cf22e30f0cfae65dd012966cab657583e2be667e (diff) | |
| download | gcc-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.cc | 9 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr123027.c | 20 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.target/i386/pr123027.c | 15 |
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 } } */ |
