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