rs6000: Implement cstore for signed Pmode register compares
authorSegher Boessenkool <segher@kernel.crashing.org>
Fri, 4 Dec 2015 17:21:49 +0000 (18:21 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Fri, 4 Dec 2015 17:21:49 +0000 (18:21 +0100)
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

gcc/ChangeLog
gcc/config/rs6000/rs6000.md

index d9a0bf8956962da09b1711e171128a0aca9646bb..1f108e7339a4068be4bc56421161560963d869d5 100644 (file)
@@ -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.
index 26b0962ae7d4c62a85121f17538497f3faa8cd1b..f346cba8e08de13f9ef6151044d1e4a31f142731 100644 (file)
   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" "")
     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);