diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-05-31 19:12:05 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-05-31 19:12:05 +0000 |
commit | fb80316e470b1700ccaff692aed8e6bc063a1278 (patch) | |
tree | 8839e3f25e5f8ccb1211432eea5838353cb12a4b | |
parent | efb076ad21b8806881320a3ba40c100653fc501d (diff) | |
download | gcc-fb80316e470b1700ccaff692aed8e6bc063a1278.tar.gz |
* config/rs6000/predicates.md (rs6000_cbranch_operator): Accept some
unordered comparison operators when -fno-trapping-math is in effect
on the e500.
* config/rs6000/rs6000.c (rs6000_generate_compare): Remove dead code
and implement unordered comparison operators properly on the e500.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@199557 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/rs6000/predicates.md | 9 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 58 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/e500-ord-1.c | 29 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/e500-ord-2.c | 29 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/e500-unord-1.c | 29 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/e500-unord-2.c | 29 |
8 files changed, 175 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0894c50d81f..2ec1dccf6f8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2013-05-31 Eric Botcazou <ebotcazou@adacore.com> + * config/rs6000/predicates.md (rs6000_cbranch_operator): Accept some + unordered comparison operators when -fno-trapping-math is in effect + on the e500. + * config/rs6000/rs6000.c (rs6000_generate_compare): Remove dead code + and implement unordered comparison operators properly on the e500. + +2013-05-31 Eric Botcazou <ebotcazou@adacore.com> + * simplify-rtx.c (simplify_byte_swapping_operation): Use proper macro for constant scalar integers. (simplify_relational_operation_1): Likewise. diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 078c9387350..7fdf7d1b6cb 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -1121,9 +1121,16 @@ GET_MODE (XEXP (op, 0))), 1")))) +;; Return 1 if OP is a valid comparison operator for "cbranch" instructions. +;; If we're assuming that FP operations cannot generate user-visible traps, +;; then on e500 we can use the ordered-signaling instructions to implement +;; the unordered-quiet FP comparison predicates modulo a reversal. (define_predicate "rs6000_cbranch_operator" (if_then_else (match_test "TARGET_HARD_FLOAT && !TARGET_FPRS") - (match_operand 0 "ordered_comparison_operator") + (if_then_else (match_test "flag_trapping_math") + (match_operand 0 "ordered_comparison_operator") + (ior (match_operand 0 "ordered_comparison_operator") + (match_code ("unlt,unle,ungt,unge")))) (match_operand 0 "comparison_operator"))) ;; Return 1 if OP is a comparison operation that is valid for an SCC insn -- diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index cb6876051d7..9c4b7f04c35 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -16087,16 +16087,41 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode) { rtx cmp, or_result, compare_result2; enum machine_mode op_mode = GET_MODE (op0); + bool reverse_p; if (op_mode == VOIDmode) op_mode = GET_MODE (op1); + /* First reverse the condition codes that aren't directly supported. */ + switch (code) + { + case NE: + case UNLT: + case UNLE: + case UNGT: + case UNGE: + code = reverse_condition_maybe_unordered (code); + reverse_p = true; + break; + + case EQ: + case LT: + case LE: + case GT: + case GE: + reverse_p = false; + break; + + default: + gcc_unreachable (); + } + /* The E500 FP compare instructions toggle the GT bit (CR bit 1) only. This explains the following mess. */ switch (code) { - case EQ: case UNEQ: case NE: case LTGT: + case EQ: switch (op_mode) { case SFmode: @@ -16122,7 +16147,8 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode) } break; - case GT: case GTU: case UNGT: case UNGE: case GE: case GEU: + case GT: + case GE: switch (op_mode) { case SFmode: @@ -16148,7 +16174,8 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode) } break; - case LT: case LTU: case UNLT: case UNLE: case LE: case LEU: + case LT: + case LE: switch (op_mode) { case SFmode: @@ -16173,24 +16200,16 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode) gcc_unreachable (); } break; + default: gcc_unreachable (); } /* Synthesize LE and GE from LT/GT || EQ. */ - if (code == LE || code == GE || code == LEU || code == GEU) + if (code == LE || code == GE) { emit_insn (cmp); - switch (code) - { - case LE: code = LT; break; - case GE: code = GT; break; - case LEU: code = LT; break; - case GEU: code = GT; break; - default: gcc_unreachable (); - } - compare_result2 = gen_reg_rtx (CCFPmode); /* Do the EQ. */ @@ -16217,23 +16236,18 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode) default: gcc_unreachable (); } + emit_insn (cmp); /* OR them together. */ or_result = gen_reg_rtx (CCFPmode); cmp = gen_e500_cr_ior_compare (or_result, compare_result, - compare_result2); + compare_result2); compare_result = or_result; - code = EQ; - } - else - { - if (code == NE || code == LTGT) - code = NE; - else - code = EQ; } + code = reverse_p ? NE : EQ; + emit_insn (cmp); } else diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b46c378d828..fb6c69430cf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2013-05-31 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.target/powerpc/e500-ord-1.c: New test. + * gcc.target/powerpc/e500-ord-2.c: Likewise. + * gcc.target/powerpc/e500-unord-1.c: Likewise. + * gcc.target/powerpc/e500-unord-2.c: Likewise. + 2013-05-31 Marcus Shawcroft <marcus.shawcroft@arm.com> * g++.dg/torture/pr54684.C: Add -fno-short-enums. diff --git a/gcc/testsuite/gcc.target/powerpc/e500-ord-1.c b/gcc/testsuite/gcc.target/powerpc/e500-ord-1.c new file mode 100644 index 00000000000..c4f2769901c --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/e500-ord-1.c @@ -0,0 +1,29 @@ +/* { dg-do compile { target powerpc*-*-eabi* } } */ +/* { dg-options "-O -ftrapping-math -fdump-rtl-final" } */ + +int isgreater (float f1, float f2) +{ + int r = (f1 > f2); + return !r ? -1 : 1; +} + +int isgreaterequal (float f1, float f2) +{ + int r = (f1 >= f2); + return !r ? -1 : 1; +} + +int isless (float f1, float f2) +{ + int r = (f1 < f2); + return !r ? -1 : 1; +} + +int islessequal (float f1, float f2) +{ + int r = (f1 <= f2); + return !r ? -1 : 1; +} + +/* { dg-final { scan-rtl-dump-not "__unordsf2" "final" } } */ +/* { dg-final { cleanup-rtl-dump "final" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/e500-ord-2.c b/gcc/testsuite/gcc.target/powerpc/e500-ord-2.c new file mode 100644 index 00000000000..a6b5c297370 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/e500-ord-2.c @@ -0,0 +1,29 @@ +/* { dg-do compile { target powerpc*-*-eabi* } } */ +/* { dg-options "-O -fno-trapping-math -fdump-rtl-final" } */ + +int isgreater (float f1, float f2) +{ + int r = (f1 > f2); + return !r ? -1 : 1; +} + +int isgreaterequal (float f1, float f2) +{ + int r = (f1 >= f2); + return !r ? -1 : 1; +} + +int isless (float f1, float f2) +{ + int r = (f1 < f2); + return !r ? -1 : 1; +} + +int islessequal (float f1, float f2) +{ + int r = (f1 <= f2); + return !r ? -1 : 1; +} + +/* { dg-final { scan-rtl-dump-not "__unordsf2" "final" } } */ +/* { dg-final { cleanup-rtl-dump "final" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/e500-unord-1.c b/gcc/testsuite/gcc.target/powerpc/e500-unord-1.c new file mode 100644 index 00000000000..0cd75d8d30d --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/e500-unord-1.c @@ -0,0 +1,29 @@ +/* { dg-do compile { target powerpc*-*-eabi* } } */ +/* { dg-options "-O -ftrapping-math -fdump-rtl-final" } */ + +int isgreater (float f1, float f2) +{ + int r = __builtin_isgreater (f1, f2); + return !r ? -1 : 1; +} + +int isgreaterequal (float f1, float f2) +{ + int r = __builtin_isgreaterequal (f1, f2); + return !r ? -1 : 1; +} + +int isless (float f1, float f2) +{ + int r = __builtin_isless (f1, f2); + return !r ? -1 : 1; +} + +int islessequal (float f1, float f2) +{ + int r = __builtin_islessequal (f1, f2); + return !r ? -1 : 1; +} + +/* { dg-final { scan-rtl-dump-times "__unordsf2" 4 "final" } } */ +/* { dg-final { cleanup-rtl-dump "final" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/e500-unord-2.c b/gcc/testsuite/gcc.target/powerpc/e500-unord-2.c new file mode 100644 index 00000000000..51b1316f271 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/e500-unord-2.c @@ -0,0 +1,29 @@ +/* { dg-do compile { target powerpc*-*-eabi* } } */ +/* { dg-options "-O -fno-trapping-math -fdump-rtl-final" } */ + +int isgreater (float f1, float f2) +{ + int r = __builtin_isgreater (f1, f2); + return !r ? -1 : 1; +} + +int isgreaterequal (float f1, float f2) +{ + int r = __builtin_isgreaterequal (f1, f2); + return !r ? -1 : 1; +} + +int isless (float f1, float f2) +{ + int r = __builtin_isless (f1, f2); + return !r ? -1 : 1; +} + +int islessequal (float f1, float f2) +{ + int r = __builtin_islessequal (f1, f2); + return !r ? -1 : 1; +} + +/* { dg-final { scan-rtl-dump-not "__unordsf2" "final" } } */ +/* { dg-final { cleanup-rtl-dump "final" } } */ |