summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/rs6000/rs6000.md47
2 files changed, 52 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d9a0bf89569..1f108e7339a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2015-12-04 Segher Boessenkool <segher&kernel.crashing.org>
+
+ * (cstore<mode>4_signed): New expander.
+ (cstore<mode>4): Call it.
+
2015-12-04 Jakub Jelinek <jakub@redhat.com>
* tree-tailcall.c (find_tail_calls): Ignore GIMPLE_NOPs.
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 26b0962ae7d..f346cba8e08 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10525,6 +10525,47 @@
DONE;
}")
+(define_expand "cstore<mode>4_signed"
+ [(use (match_operator 1 "signed_comparison_operator"
+ [(match_operand:P 2 "gpc_reg_operand")
+ (match_operand:P 3 "gpc_reg_operand")]))
+ (clobber (match_operand:P 0 "gpc_reg_operand"))]
+ ""
+{
+ enum rtx_code cond_code = GET_CODE (operands[1]);
+
+ rtx op0 = operands[0];
+ rtx op1 = operands[2];
+ rtx op2 = operands[3];
+
+ if (cond_code == GE || cond_code == LT)
+ {
+ cond_code = swap_condition (cond_code);
+ std::swap (op1, op2);
+ }
+
+ rtx tmp1 = gen_reg_rtx (<MODE>mode);
+ rtx tmp2 = gen_reg_rtx (<MODE>mode);
+ rtx tmp3 = gen_reg_rtx (<MODE>mode);
+
+ int sh = GET_MODE_BITSIZE (<MODE>mode) - 1;
+ emit_insn (gen_lshr<mode>3 (tmp1, op1, GEN_INT (sh)));
+ emit_insn (gen_ashr<mode>3 (tmp2, op2, GEN_INT (sh)));
+
+ emit_insn (gen_subf<mode>3_carry (tmp3, op1, op2));
+
+ if (cond_code == LE)
+ emit_insn (gen_add<mode>3_carry_in (op0, tmp1, tmp2));
+ else
+ {
+ rtx tmp4 = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_add<mode>3_carry_in (tmp4, tmp1, tmp2));
+ emit_insn (gen_xor<mode>3 (op0, tmp4, const1_rtx));
+ }
+
+ DONE;
+})
+
(define_expand "cstore<mode>4_unsigned"
[(use (match_operator 1 "unsigned_comparison_operator"
[(match_operand:P 2 "gpc_reg_operand" "")
@@ -10751,6 +10792,12 @@
emit_insn (gen_cstore<mode>4_unsigned_imm (operands[0], operands[1],
operands[2], operands[3]));
+ /* We also do not want to use mfcr for signed comparisons. */
+ else if (<MODE>mode == Pmode
+ && signed_comparison_operator (operands[1], VOIDmode))
+ emit_insn (gen_cstore<mode>4_signed (operands[0], operands[1],
+ operands[2], operands[3]));
+
/* Everything else, use the mfcr brute force. */
else
rs6000_emit_sCOND (<MODE>mode, operands);