summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-02 10:56:15 +0000
committersegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-02 10:56:15 +0000
commit32cbdfc447c3a2cc1aba19a5fbee87ebc8868b22 (patch)
tree91068602631c3d28713bc7e74bbf6d0319a4358c
parentacbb264c8805485d874f3ff89697e030432076b0 (diff)
downloadgcc-32cbdfc447c3a2cc1aba19a5fbee87ebc8868b22.tar.gz
rs6000: Optimise SImode cstore on 64-bit
On 64-bit we can do comparisons of 32-bit values by extending those values to 64-bit, subtracting them, and then getting the high bit of the result. For registers this is always cheaper than using the carry bit sequence; and if the comparison involves a constant, this is cheaper than the sequence we previously generated in half of the cases (and the same cost in the other cases). After this, the only sequence left that is using the mfcr insn is the one doing signed comparison of Pmode registers. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231165 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/rs6000/rs6000.md50
2 files changed, 55 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8eaac80b47d..58c472868ed 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2015-12-02 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (cstore_si_as_di): New expander.
+ (cstore<mode>4): Use it.
+
2015-12-02 Richard Biener <rguenther@suse.de>
PR tree-optimization/68625
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index a500d67efa9..26b0962ae7d 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10564,6 +10564,51 @@
DONE;
})
+(define_expand "cstore_si_as_di"
+ [(use (match_operator 1 "unsigned_comparison_operator"
+ [(match_operand:SI 2 "gpc_reg_operand")
+ (match_operand:SI 3 "reg_or_short_operand")]))
+ (clobber (match_operand:SI 0 "register_operand"))]
+ ""
+{
+ int uns_flag = unsigned_comparison_operator (operands[1], VOIDmode) ? 1 : 0;
+ enum rtx_code cond_code = signed_condition (GET_CODE (operands[1]));
+
+ rtx op1 = gen_reg_rtx (DImode);
+ rtx op2 = gen_reg_rtx (DImode);
+ convert_move (op1, operands[2], uns_flag);
+ convert_move (op2, operands[3], uns_flag);
+
+ if (cond_code == GT || cond_code == LE)
+ {
+ cond_code = swap_condition (cond_code);
+ std::swap (op1, op2);
+ }
+
+ rtx tmp = gen_reg_rtx (DImode);
+ rtx tmp2 = gen_reg_rtx (DImode);
+ emit_insn (gen_subdi3 (tmp, op1, op2));
+ emit_insn (gen_lshrdi3 (tmp2, tmp, GEN_INT (63)));
+
+ rtx tmp3;
+ switch (cond_code)
+ {
+ default:
+ gcc_unreachable ();
+ case LT:
+ tmp3 = tmp2;
+ break;
+ case GE:
+ tmp3 = gen_reg_rtx (DImode);
+ emit_insn (gen_xordi3 (tmp3, tmp2, const1_rtx));
+ break;
+ }
+
+ convert_move (operands[0], tmp3, 1);
+
+ DONE;
+})
+
(define_expand "cstore<mode>4_signed_imm"
[(use (match_operator 1 "signed_comparison_operator"
[(match_operand:GPR 2 "gpc_reg_operand")
@@ -10688,6 +10733,11 @@
emit_insn (gen_cstore<mode>4_unsigned (operands[0], operands[1],
operands[2], operands[3]));
+ /* For comparisons smaller than Pmode we can cheaply do things in Pmode. */
+ else if (<MODE>mode == SImode && Pmode == DImode)
+ emit_insn (gen_cstore_si_as_di (operands[0], operands[1],
+ operands[2], operands[3]));
+
/* For signed comparisons against a constant, we can do some simple
bit-twiddling. */
else if (signed_comparison_operator (operands[1], VOIDmode)