aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSegher Boessenkool <segher@kernel.crashing.org>2015-12-04 18:21:49 +0100
committerSegher Boessenkool <segher@gcc.gnu.org>2015-12-04 18:21:49 +0100
commit2f74c72b13f9c212dabca5c801e1da37ce8d60b2 (patch)
treef880ea6cb21ff01c9f5ff51840129c3bc3eb99f6
parent5c24689633f109abfc2b9b6c62f327c805c49fa4 (diff)
downloadgcc-2f74c72b13f9c212dabca5c801e1da37ce8d60b2.zip
gcc-2f74c72b13f9c212dabca5c801e1da37ce8d60b2.tar.gz
gcc-2f74c72b13f9c212dabca5c801e1da37ce8d60b2.tar.bz2
rs6000: Implement cstore for signed Pmode register compares
This implements cstore for the last case we do not yet handle, using the superopt algo from the venerable CWG. The only integer cases we do still not handle after this are for -m32 -mpowerpc64. * (cstore<mode>4_signed): New expander. (cstore<mode>4): Call it. From-SVN: r231284
-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 d9a0bf8..1f108e7 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 26b0962..f346cba 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);