summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorsegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-04 17:21:49 +0000
committersegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-04 17:21:49 +0000
commit09767a25f61c044e689d6d190d57c66b7a2515af (patch)
treef880ea6cb21ff01c9f5ff51840129c3bc3eb99f6 /gcc/config
parente7f8c9f3d63fb349f076e3710bae3b6f3415b191 (diff)
downloadgcc-09767a25f61c044e689d6d190d57c66b7a2515af.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231284 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/rs6000/rs6000.md47
1 files changed, 47 insertions, 0 deletions
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);