[RFC PATCH for 9] rs6000: Ordered comparisons (PR56864)

Segher Boessenkool segher@kernel.crashing.org
Mon Mar 26 19:29:00 GMT 2018


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



More information about the Gcc-patches mailing list