rs6000.md (cstore<mode>4_signed_imm): New expander.
authorSegher Boessenkool <segher@kernel.crashing.org>
Wed, 6 May 2015 15:55:10 +0000 (17:55 +0200)
committerSegher Boessenkool <segher@gcc.gnu.org>
Wed, 6 May 2015 15:55:10 +0000 (17:55 +0200)
* config/rs6000/rs6000.md (cstore<mode>4_signed_imm): New expander.
(cstore<mode>4_unsigned_imm): New expander.
(cstore<mode>4): Remove empty constraint strings.  Use the new
expanders.

From-SVN: r222855

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

index f7188b2..3b267c8 100644 (file)
@@ -1,3 +1,10 @@
+2015-05-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * config/rs6000/rs6000.md (cstore<mode>4_signed_imm): New expander.
+       (cstore<mode>4_unsigned_imm): New expander.
+       (cstore<mode>4): Remove empty constraint strings.  Use the new
+       expanders.
+
 2015-05-06  Yvan Roux  <yvan.roux@linaro.org>
 
        PR target/64208
index 2d15d71..7fc2bb1 100644 (file)
   DONE;
 })
 
+(define_expand "cstore<mode>4_signed_imm"
+  [(use (match_operator 1 "signed_comparison_operator"
+         [(match_operand:GPR 2 "gpc_reg_operand")
+          (match_operand:GPR 3 "immediate_operand")]))
+   (clobber (match_operand:GPR 0 "register_operand"))]
+  ""
+{
+  bool invert = false;
+
+  enum rtx_code cond_code = GET_CODE (operands[1]);
+
+  rtx op0 = operands[0];
+  rtx op1 = operands[2];
+  HOST_WIDE_INT val = INTVAL (operands[3]);
+
+  if (cond_code == GE || cond_code == GT)
+    {
+      cond_code = reverse_condition (cond_code);
+      invert = true;
+    }
+
+  if (cond_code == LE)
+    val++;
+
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  emit_insn (gen_add<mode>3 (tmp, op1, GEN_INT (-val)));
+  rtx x = gen_reg_rtx (<MODE>mode);
+  if (val < 0)
+    emit_insn (gen_and<mode>3 (x, op1, tmp));
+  else
+    emit_insn (gen_ior<mode>3 (x, op1, tmp));
+
+  if (invert)
+    {
+      rtx tmp = gen_reg_rtx (<MODE>mode);
+      emit_insn (gen_one_cmpl<mode>2 (tmp, x));
+      x = tmp;
+    }
+
+  int sh = GET_MODE_BITSIZE (<MODE>mode) - 1;
+  emit_insn (gen_lshr<mode>3 (op0, x, GEN_INT (sh)));
+
+  DONE;
+})
+
+(define_expand "cstore<mode>4_unsigned_imm"
+  [(use (match_operator 1 "unsigned_comparison_operator"
+         [(match_operand:GPR 2 "gpc_reg_operand")
+          (match_operand:GPR 3 "immediate_operand")]))
+   (clobber (match_operand:GPR 0 "register_operand"))]
+  ""
+{
+  bool invert = false;
+
+  enum rtx_code cond_code = GET_CODE (operands[1]);
+
+  rtx op0 = operands[0];
+  rtx op1 = operands[2];
+  HOST_WIDE_INT val = INTVAL (operands[3]);
+
+  if (cond_code == GEU || cond_code == GTU)
+    {
+      cond_code = reverse_condition (cond_code);
+      invert = true;
+    }
+
+  if (cond_code == LEU)
+    val++;
+
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  rtx tmp2 = gen_reg_rtx (<MODE>mode);
+  emit_insn (gen_add<mode>3 (tmp, op1, GEN_INT (-val)));
+  emit_insn (gen_one_cmpl<mode>2 (tmp2, op1));
+  rtx x = gen_reg_rtx (<MODE>mode);
+  if (val < 0)
+    emit_insn (gen_ior<mode>3 (x, tmp, tmp2));
+  else
+    emit_insn (gen_and<mode>3 (x, tmp, tmp2));
+
+  if (invert)
+    {
+      rtx tmp = gen_reg_rtx (<MODE>mode);
+      emit_insn (gen_one_cmpl<mode>2 (tmp, x));
+      x = tmp;
+    }
+
+  int sh = GET_MODE_BITSIZE (<MODE>mode) - 1;
+  emit_insn (gen_lshr<mode>3 (op0, x, GEN_INT (sh)));
+
+  DONE;
+})
+
 (define_expand "cstore<mode>4"
   [(use (match_operator 1 "rs6000_cbranch_operator"
-         [(match_operand:GPR 2 "gpc_reg_operand" "")
-          (match_operand:GPR 3 "reg_or_short_operand" "")]))
+         [(match_operand:GPR 2 "gpc_reg_operand")
+          (match_operand:GPR 3 "reg_or_short_operand")]))
    (clobber (match_operand:GPR 0 "register_operand"))]
   ""
 {
     emit_insn (gen_cstore<mode>4_unsigned (operands[0], operands[1],
                                           operands[2], operands[3]));
 
-  /* The generic code knows tricks to compute signed comparisons against
-     zero.  Let it do its thing.  */
-  else if (operands[3] == const0_rtx
-          && signed_comparison_operator (operands[1], VOIDmode))
-    FAIL;
+  /* For signed comparisons against a constant, we can do some simple
+     bit-twiddling.  */
+  else if (signed_comparison_operator (operands[1], VOIDmode)
+          && CONST_INT_P (operands[3]))
+    emit_insn (gen_cstore<mode>4_signed_imm (operands[0], operands[1],
+                                            operands[2], operands[3]));
+
+  /* And similarly for unsigned comparisons.  */
+  else if (unsigned_comparison_operator (operands[1], VOIDmode)
+          && CONST_INT_P (operands[3]))
+    emit_insn (gen_cstore<mode>4_unsigned_imm (operands[0], operands[1],
+                                              operands[2], operands[3]));
 
   /* Everything else, use the mfcr brute force.  */
   else