aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2013-05-31 19:12:05 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2013-05-31 19:12:05 +0000
commit4172215d0af78c458ba0e287e1fcf2ac80d5eb71 (patch)
tree8839e3f25e5f8ccb1211432eea5838353cb12a4b /gcc/config/rs6000
parenta8c50132e9e2c02c1692088b0f8aaad7a8716f4d (diff)
downloadgcc-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.md9
-rw-r--r--gcc/config/rs6000/rs6000.c58
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