This implements ordered comparisons for most floating point variants.
It does not yet implement it for XL-compatible FP comparisons.
I do not yet know if it works correctly for emulated 128-bit IEEE FP.
There should not be performance impact, but I haven't tested it
thoroughly yet.
Segher
* config/rs6000/rs6000.c (rs6000_generate_compare): Add an UNSPEC_CMPO
to those floating-point comparisons that are not quiet.
* config/rs6000/rs6000.md (define_c_enum enspec): Add UNSPEC_CMPO.
(*cmp<mode>_fpr): Rename to ...
(*cmp<mode>_cmpu): ... this. (SFDF)
(*cmp<mode>_cmpo): New.
(*cmp<mode>_internal1): Rename to ...
(*cmp<mode>_cmpu): ... this. (IBM128)
(*cmp<mode>_cmpo): New.
(*cmp<mode>_hw): Rename to ...
(*cmp<mode>_cmpu): ... this. (IEEE128)
(*cmp<mode>_cmpo): New.
* config/rs6000/dfp.md (*cmpdd_internal1): Rename to ...
(*cmpdd_cmpu): ... this.
(*cmpdd_cmpo): New.
(*cmptd_internal1): Rename to ...
(*cmptd_cmpu): ... this.
(*cmptd_cmpo): New.
gcc/testsuite/
* gcc.dg/torture/inf-compare-1.c: Remove powerpc xfail.
* gcc.dg/torture/inf-compare-2.c: Remove powerpc xfail.
* gcc.dg/torture/inf-compare-3.c: Remove powerpc xfail.
* gcc.dg/torture/inf-compare-4.c: Remove powerpc xfail.
* gcc.target/powerpc/dfp-dd.c: Expect dcmpo to be generated for the
ordered compares.
* gcc.target/powerpc/dfp-td.c: Expect dcmpoq to be generated for the
ordered compares.
---
gcc/config/rs6000/dfp.md | 22 ++++++++++++-
gcc/config/rs6000/rs6000.c | 15 ++++++++-
gcc/config/rs6000/rs6000.md | 41 +++++++++++++++++++++++--
gcc/testsuite/gcc.dg/torture/inf-compare-1.c | 3 +-
gcc/testsuite/gcc.dg/torture/inf-compare-2.c | 3 +-
gcc/testsuite/gcc.dg/torture/inf-compare-3.c | 3 +-
gcc/testsuite/gcc.dg/torture/inf-compare-4.c | 3 +-
gcc/testsuite/gcc.target/powerpc/dfp-dd.c | 3 +-
gcc/testsuite/gcc.target/powerpc/dfp-td.c | 3 +-
9 files changed, 78 insertions(+), 18 deletions(-)
diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md
index cd15aa8..8eb5dcc 100644
--- a/gcc/config/rs6000/dfp.md
+++ b/gcc/config/rs6000/dfp.md
@@ -216,7 +216,7 @@
"ddivq %0,%1,%2"
[(set_attr "type" "dfp")])
-(define_insn "*cmpdd_internal1"
+(define_insn "*cmpdd_cmpu"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
(match_operand:DD 2 "gpc_reg_operand" "d")))]
@@ -224,7 +224,16 @@
"dcmpu %0,%1,%2"
[(set_attr "type" "dfp")])
-(define_insn "*cmptd_internal1"
+(define_insn "*cmpdd_cmpo"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d")
+ (match_operand:DD 2 "gpc_reg_operand" "d")))
+ (unspec [(match_dup 1) (match_dup 2)] UNSPEC_CMPO)]
+ "TARGET_DFP"
+ "dcmpo %0,%1,%2"
+ [(set_attr "type" "dfp")])
+
+(define_insn "*cmptd_cmpu"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
(match_operand:TD 2 "gpc_reg_operand" "d")))]
@@ -232,6 +241,15 @@
"dcmpuq %0,%1,%2"
[(set_attr "type" "dfp")])
+(define_insn "*cmptd_cmpo"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d")
+ (match_operand:TD 2 "gpc_reg_operand" "d")))
+ (unspec [(match_dup 1) (match_dup 2)] UNSPEC_CMPO)]
+ "TARGET_DFP"
+ "dcmpoq %0,%1,%2"
+ [(set_attr "type" "dfp")])
+
(define_insn "floatdidd2"
[(set (match_operand:DD 0 "gpc_reg_operand" "=d")
(float:DD (match_operand:DI 1 "gpc_reg_operand" "d")))]
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 1fe8b9a..401be74 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -22127,8 +22127,19 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
emit_insn (gen_stack_protect_testsi (compare_result, op0, op1b));
}
else
- emit_insn (gen_rtx_SET (compare_result,
- gen_rtx_COMPARE (comp_mode, op0, op1)));
+ {
+ rtx compare = gen_rtx_SET (compare_result,
+ gen_rtx_COMPARE (comp_mode, op0, op1));
+ if (SCALAR_FLOAT_MODE_P (mode) && HONOR_NANS (mode)
+ && (code == LT || code == GT || code == LE || code == GE))
+ {
+ rtx unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (2, op0, op1),
+ UNSPEC_CMPO);
+ compare = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2, compare, unspec));
+ }
+ emit_insn (compare);
+ }
}
/* Some kinds of FP comparisons need an OR operation;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 7b285ef..cd6956f 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -150,6 +150,7 @@
UNSPEC_SIGNBIT
UNSPEC_SF_FROM_SI
UNSPEC_SI_FROM_SF
+ UNSPEC_CMPO
])
;;
@@ -4691,7 +4692,7 @@
[(set_attr "type" "fp")])
;; Floating point comparisons
-(define_insn "*cmp<mode>_fpr"
+(define_insn "*cmp<mode>_cmpu"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y")
(compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")
(match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
@@ -4701,6 +4702,17 @@
xscmpudp %0,%x1,%x2"
[(set_attr "type" "fpcompare")])
+(define_insn "*cmp<mode>_cmpo"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y")
+ (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))
+ (unspec [(match_dup 1) (match_dup 2)] UNSPEC_CMPO)]
+ "TARGET_<MODE>_FPR"
+ "@
+ fcmpo %0,%1,%2
+ xscmpodp %0,%x1,%x2"
+ [(set_attr "type" "fpcompare")])
+
;; Floating point conversions
(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "gpc_reg_operand")
@@ -11582,7 +11594,7 @@
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))])
;; Only need to compare second words if first words equal
-(define_insn "*cmp<mode>_internal1"
+(define_insn "*cmp<mode>_cmpu"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(compare:CCFP (match_operand:IBM128 1 "gpc_reg_operand" "d")
(match_operand:IBM128 2 "gpc_reg_operand" "d")))]
@@ -11592,6 +11604,17 @@
[(set_attr "type" "fpcompare")
(set_attr "length" "12")])
+(define_insn "*cmp<mode>_cmpo"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (compare:CCFP (match_operand:IBM128 1 "gpc_reg_operand" "d")
+ (match_operand:IBM128 2 "gpc_reg_operand" "d")))
+ (unspec [(match_dup 1) (match_dup 2)] UNSPEC_CMPO)]
+ "!TARGET_XL_COMPAT && FLOAT128_IBM_P (<MODE>mode)
+ && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
+ "fcmpo %0,%1,%2\;bne %0,$+8\;fcmpu %0,%L1,%L2"
+ [(set_attr "type" "fpcompare")
+ (set_attr "length" "12")])
+
(define_insn_and_split "*cmp<mode>_internal2"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(compare:CCFP (match_operand:IBM128 1 "gpc_reg_operand" "d")
@@ -14573,12 +14596,22 @@
(set_attr "size" "128")])
;; IEEE 128-bit comparisons
-(define_insn "*cmp<mode>_hw"
+(define_insn "*cmp<mode>_cmpu"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(compare:CCFP (match_operand:IEEE128 1 "altivec_register_operand" "v")
(match_operand:IEEE128 2 "altivec_register_operand"
"v")))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
- "xscmpuqp %0,%1,%2"
+ "xscmpuqp %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "size" "128")])
+
+(define_insn "*cmp<mode>_cmpo"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (compare:CCFP (match_operand:IEEE128 1 "altivec_register_operand" "v")
+ (match_operand:IEEE128 2 "altivec_register_operand" "v")))
+ (unspec [(match_dup 1) (match_dup 2)] UNSPEC_CMPO)]
+ "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+ "xscmpoqp %0,%1,%2"
[(set_attr "type" "veccmp")
(set_attr "size" "128")])
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-1.c
b/gcc/testsuite/gcc.dg/torture/inf-compare-1.c
index a4b44d6..0f45108 100644
--- a/gcc/testsuite/gcc.dg/torture/inf-compare-1.c
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-1.c
@@ -1,5 +1,4 @@
-/* { dg-do run { xfail { powerpc*-*-* } } } */
-/* remove the xfail for powerpc when pr58684 is fixed */
+/* { dg-do run } */
/* { dg-add-options ieee } */
/* { dg-require-effective-target fenv_exceptions } */
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-2.c
b/gcc/testsuite/gcc.dg/torture/inf-compare-2.c
index 8ee932c..ba73395 100644
--- a/gcc/testsuite/gcc.dg/torture/inf-compare-2.c
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-2.c
@@ -1,5 +1,4 @@
-/* { dg-do run { xfail { powerpc*-*-* } } } */
-/* remove the xfail for powerpc when pr58684 is fixed */
+/* { dg-do run } */
/* { dg-add-options ieee } */
/* { dg-require-effective-target fenv_exceptions } */
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-3.c
b/gcc/testsuite/gcc.dg/torture/inf-compare-3.c
index c8605ad..e545d3b 100644
--- a/gcc/testsuite/gcc.dg/torture/inf-compare-3.c
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-3.c
@@ -1,5 +1,4 @@
-/* { dg-do run { xfail { powerpc*-*-* } } } */
-/* remove the xfail for powerpc when pr58684 is fixed */
+/* { dg-do run } */
/* { dg-add-options ieee } */
/* { dg-require-effective-target fenv_exceptions } */
diff --git a/gcc/testsuite/gcc.dg/torture/inf-compare-4.c
b/gcc/testsuite/gcc.dg/torture/inf-compare-4.c
index 55a0dfc..fca6cbf 100644
--- a/gcc/testsuite/gcc.dg/torture/inf-compare-4.c
+++ b/gcc/testsuite/gcc.dg/torture/inf-compare-4.c
@@ -1,5 +1,4 @@
-/* { dg-do run { xfail { powerpc*-*-* } } } */
-/* remove the xfail for powerpc when pr58684 is fixed */
+/* { dg-do run } */
/* { dg-add-options ieee } */
/* { dg-require-effective-target fenv_exceptions } */
diff --git a/gcc/testsuite/gcc.target/powerpc/dfp-dd.c
b/gcc/testsuite/gcc.target/powerpc/dfp-dd.c
index f18cd44..87ef011 100644
--- a/gcc/testsuite/gcc.target/powerpc/dfp-dd.c
+++ b/gcc/testsuite/gcc.target/powerpc/dfp-dd.c
@@ -8,7 +8,8 @@
/* { dg-final { scan-assembler "ddiv" } } */
/* { dg-final { scan-assembler "dmul" } } */
/* { dg-final { scan-assembler "dsub" } } */
-/* { dg-final { scan-assembler-times "dcmpu" 6 } } */
+/* { dg-final { scan-assembler-times "dcmpu" 2 } } */
+/* { dg-final { scan-assembler-times "dcmpo" 4 } } */
/* { dg-final { scan-assembler-times "dctfix" 2 } } */
/* { dg-final { scan-assembler-times "drintn" 2 } } */
/* { dg-final { scan-assembler-times "dcffixq" 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/dfp-td.c
b/gcc/testsuite/gcc.target/powerpc/dfp-td.c
index 2aff868..a159eb6 100644
--- a/gcc/testsuite/gcc.target/powerpc/dfp-td.c
+++ b/gcc/testsuite/gcc.target/powerpc/dfp-td.c
@@ -8,7 +8,8 @@
/* { dg-final { scan-assembler "ddivq" } } */
/* { dg-final { scan-assembler "dmulq" } } */
/* { dg-final { scan-assembler "dsubq" } } */
-/* { dg-final { scan-assembler-times "dcmpuq" 6 } } */
+/* { dg-final { scan-assembler-times "dcmpuq" 2 } } */
+/* { dg-final { scan-assembler-times "dcmpoq" 4 } } */
/* { dg-final { scan-assembler-times "dctfixq" 2 } } */
/* { dg-final { scan-assembler-times "drintnq" 2 } } */
/* { dg-final { scan-assembler-times "dcffixq" 2 } } */
--
1.7.1