diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/rs6000/predicates.md | 6 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 10 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 32 |
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" "") |