diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2013-05-31 19:12:05 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2013-05-31 19:12:05 +0000 |
commit | 4172215d0af78c458ba0e287e1fcf2ac80d5eb71 (patch) | |
tree | 8839e3f25e5f8ccb1211432eea5838353cb12a4b /gcc/config/rs6000 | |
parent | a8c50132e9e2c02c1692088b0f8aaad7a8716f4d (diff) | |
download | gcc-4172215d0af78c458ba0e287e1fcf2ac80d5eb71.zip gcc-4172215d0af78c458ba0e287e1fcf2ac80d5eb71.tar.gz gcc-4172215d0af78c458ba0e287e1fcf2ac80d5eb71.tar.bz2 |
predicates.md (rs6000_cbranch_operator): Accept some unordered comparison operators when...
* 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.
From-SVN: r199557
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r-- | gcc/config/rs6000/predicates.md | 9 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 58 |
2 files changed, 44 insertions, 23 deletions
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 078c938..7fdf7d1 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 cb68760..9c4b7f0 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 |