diff mbox

[1/2] rs6000: Implement cstore for signed Pmode register compares

Message ID ffa276b006562a0a3f54ce786b21d0e69dcfc258.1449238455.git.segher@kernel.crashing.org
State New
Headers show

Commit Message

Segher Boessenkool Dec. 4, 2015, 2:34 p.m. UTC
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.  Those case
now generate a branch sequence, which is better than what we had
before.

Tested on powerpc64-linux; okay for mainline?


Segher


2015-12-04  Segher Boessenkool  <segher&kernel.crashing.org>

	* (cstore<mode>4_signed): New expander.
	(cstore<mode>4): Call it.  FAIL instead of calling rs6000_emit_sCOND.

---
 gcc/config/rs6000/rs6000.md | 50 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 2 deletions(-)

Comments

David Edelsohn Dec. 4, 2015, 2:55 p.m. UTC | #1
On Fri, Dec 4, 2015 at 9:34 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> 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.  Those case
> now generate a branch sequence, which is better than what we had
> before.
>
> Tested on powerpc64-linux; okay for mainline?
>
>
> Segher
>
>
> 2015-12-04  Segher Boessenkool  <segher&kernel.crashing.org>
>
>         * (cstore<mode>4_signed): New expander.
>         (cstore<mode>4): Call it.  FAIL instead of calling rs6000_emit_sCOND.

The new expander is okay as well as calling it.

Please do not remove the fallback to sCOND without performance testing.

Thanks, David
diff mbox

Patch

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 26b0962..98abdb2 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10525,6 +10525,47 @@  (define_expand "cbranch<mode>4"
   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,9 +10792,14 @@  (define_expand "cstore<mode>4"
     emit_insn (gen_cstore<mode>4_unsigned_imm (operands[0], operands[1],
 					       operands[2], operands[3]));
 
-  /* Everything else, use the mfcr brute force.  */
+  /* 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]));
+
   else
-    rs6000_emit_sCOND (<MODE>mode, operands);
+    FAIL;
 
   DONE;
 })