aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/rs6000/predicates.md6
-rw-r--r--gcc/config/rs6000/rs6000.c10
-rw-r--r--gcc/config/rs6000/rs6000.md32
4 files changed, 55 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 14e4cde..9b72153 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2010-10-12 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/rs6000/predicates.md (scc_rev_comparison_operator): New.
+ * config/rs6000/rs6000.md (*isel_reversed_signed_<mode>): New.
+ (*isel_reversed_unsigned_<mode>): New.
+ * config/rs6000/rs6000.c (output_isel): Accept GE/GEU/LE/LEU/NE
+ as valid comparisons and adjust operands and output appropriately.
+ (rs6000_rtx_costs) <CONST_INT>: Accept NE as a cost-0 outer_code.
+
2010-10-12 Chung-Lin Tang <cltang@codesourcery.com>
* config/arm/arm.h (ARM_EXPAND_ALIGNMENT): Rename from
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index c94af46..81ac68a 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -903,6 +903,12 @@
(and (match_operand 0 "branch_comparison_operator")
(match_code "eq,lt,gt,ltu,gtu,unordered")))
+;; Return 1 if OP is a comparison operation whose inverse would be valid for
+;; an SCC insn.
+(define_predicate "scc_rev_comparison_operator"
+ (and (match_operand 0 "branch_comparison_operator")
+ (match_code "ne,le,ge,leu,geu,ordered")))
+
;; Return 1 if OP is a comparison operation that is valid for a branch
;; insn, which is true if the corresponding bit in the CC register is set.
(define_predicate "branch_positive_comparison_operator"
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index cd1c8cc..d7377a5 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -17159,7 +17159,13 @@ output_isel (rtx *operands)
code = GET_CODE (operands[1]);
- gcc_assert (!(code == GE || code == GEU || code == LE || code == LEU || code == NE));
+ if (code == GE || code == GEU || code == LE || code == LEU || code == NE)
+ {
+ gcc_assert (GET_CODE (operands[2]) == REG
+ && GET_CODE (operands[3]) == REG);
+ PUT_CODE (operands[1], reverse_condition (code));
+ return "isel %0,%3,%2,%j1";
+ }
return "isel %0,%2,%3,%j1";
}
@@ -25731,7 +25737,7 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int *total,
|| (outer_code == COMPARE
&& (satisfies_constraint_I (x)
|| satisfies_constraint_K (x)))
- || (outer_code == EQ
+ || ((outer_code == EQ || outer_code == NE)
&& (satisfies_constraint_I (x)
|| satisfies_constraint_K (x)
|| (mode == SImode
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 23fde85..9fa2ff1 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -6126,6 +6126,38 @@
[(set_attr "type" "isel")
(set_attr "length" "4")])
+;; These patterns can be useful for combine; they let combine know that
+;; isel can handle reversed comparisons so long as the operands are
+;; registers.
+
+(define_insn "*isel_reversed_signed_<mode>"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (if_then_else:GPR
+ (match_operator 1 "scc_rev_comparison_operator"
+ [(match_operand:CC 4 "cc_reg_operand" "y")
+ (const_int 0)])
+ (match_operand:GPR 2 "gpc_reg_operand" "b")
+ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
+ "TARGET_ISEL<sel>"
+ "*
+{ return output_isel (operands); }"
+ [(set_attr "type" "isel")
+ (set_attr "length" "4")])
+
+(define_insn "*isel_reversed_unsigned_<mode>"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (if_then_else:GPR
+ (match_operator 1 "scc_rev_comparison_operator"
+ [(match_operand:CCUNS 4 "cc_reg_operand" "y")
+ (const_int 0)])
+ (match_operand:GPR 2 "gpc_reg_operand" "b")
+ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
+ "TARGET_ISEL<sel>"
+ "*
+{ return output_isel (operands); }"
+ [(set_attr "type" "isel")
+ (set_attr "length" "4")])
+
(define_expand "movsfcc"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(if_then_else:SF (match_operand 1 "comparison_operator" "")