On Tue, Dec 01, 2015 at 09:39:30PM -0600, Segher Boessenkool wrote:
> On Wed, Dec 02, 2015 at 01:50:46PM +1030, Alan Modra wrote:
> > On Wed, Dec 02, 2015 at 01:55:17AM +0000, Segher Boessenkool wrote:
> > > +  emit_insn (gen_subdi3 (tmp, op1, op2));
> > > +  emit_insn (gen_lshrdi3 (tmp2, tmp, GEN_INT (63)));
> > > +  emit_insn (gen_anddi3 (tmp3, tmp2, const1_rtx));
> > 
> > Why the AND?  The top 63 bits are already clear.
> 
> Ha, yes.  Thanks.  In a previous version I shifted by less, in which
> case GCC is smart enough to make it 63 anyway.  63 is always correct
> as well, and simpler because you don't need the AND.  But I forgot
> to take it out :-)

For completeness, this is what I committed.


Segher

---
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index a500d67..26b0962 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10564,6 +10564,51 @@ (define_expand "cstore<mode>4_unsigned"
   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 @@ (define_expand "cstore<mode>4"
     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)
-- 
1.9.3


Reply via email to