diff mbox

rs6000: Add dot forms of and<mode>3_2insn

Message ID 0724924fc516504da751ab414285146d96bc6a94.1437660385.git.segher@kernel.crashing.org
State New
Headers show

Commit Message

Segher Boessenkool July 23, 2015, 2:21 p.m. UTC
This does one of the TODOs I added: it adds dot forms of the ANDs done
with two machine insns.  It uses a new helper function (rs6000_emit_dot_insn)
that probably can be used more often; it is quite general in any case.

Bootstrapped and tested on powerpc64-linux, using {-m32,-m32/-mpowerpc64,
-m64,-m64/-mlra}; no regressions.  Code size on both 32-bit and 64-bit
improves.

Is this okay for trunk?


Segher


2015-07-23  Segher Boessenkool  <segher@kernel.crashing.org>

	PR target/66217
	* config/rs6000/rs6000-protos.h (rs6000_emit_2insn_and): Change
	prototype.
	* config/rs6000/rs6000.c (rs6000_emit_dot_insn): New function.
	(rs6000_emit_2insn_and): Handle dot forms.
	* config/rs6000/rs6000.md (and<mode>3): Adjust.
	(*and<mode>3_2insn): Remove TODO.  Adjust.  Add "type" attr.
	(*and<mode>3_2insn_dot, *and<mode>3_2insn_dot2): New.

---
 gcc/config/rs6000/rs6000-protos.h |  2 +-
 gcc/config/rs6000/rs6000.c        | 55 +++++++++++++++++++++++++++++++-------
 gcc/config/rs6000/rs6000.md       | 56 ++++++++++++++++++++++++++++++++++++---
 3 files changed, 98 insertions(+), 15 deletions(-)

Comments

David Edelsohn July 23, 2015, 2:25 p.m. UTC | #1
On Thu, Jul 23, 2015 at 10:21 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> This does one of the TODOs I added: it adds dot forms of the ANDs done
> with two machine insns.  It uses a new helper function (rs6000_emit_dot_insn)
> that probably can be used more often; it is quite general in any case.
>
> Bootstrapped and tested on powerpc64-linux, using {-m32,-m32/-mpowerpc64,
> -m64,-m64/-mlra}; no regressions.  Code size on both 32-bit and 64-bit
> improves.
>
> Is this okay for trunk?
>
>
> Segher
>
>
> 2015-07-23  Segher Boessenkool  <segher@kernel.crashing.org>
>
>         PR target/66217
>         * config/rs6000/rs6000-protos.h (rs6000_emit_2insn_and): Change
>         prototype.
>         * config/rs6000/rs6000.c (rs6000_emit_dot_insn): New function.
>         (rs6000_emit_2insn_and): Handle dot forms.
>         * config/rs6000/rs6000.md (and<mode>3): Adjust.
>         (*and<mode>3_2insn): Remove TODO.  Adjust.  Add "type" attr.
>         (*and<mode>3_2insn_dot, *and<mode>3_2insn_dot2): New.

Okay.

Thanks, David
diff mbox

Patch

diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 30a7128..f5d3476 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -77,7 +77,7 @@  extern const char *rs6000_insn_for_and_mask (machine_mode, rtx *, bool);
 extern const char *rs6000_insn_for_shift_mask (machine_mode, rtx *, bool);
 extern const char *rs6000_insn_for_insert_mask (machine_mode, rtx *, bool);
 extern bool rs6000_is_valid_2insn_and (rtx, machine_mode);
-extern void rs6000_emit_2insn_and (machine_mode, rtx *, bool, bool);
+extern void rs6000_emit_2insn_and (machine_mode, rtx *, bool, int);
 extern int registers_ok_for_quad_peep (rtx, rtx);
 extern int mems_ok_for_quad_peep (rtx, rtx);
 extern bool gpr_or_gpr_p (rtx, rtx);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 1fb1f32..fe8ce71 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -16736,20 +16736,54 @@  rs6000_is_valid_2insn_and (rtx c, machine_mode mode)
   return rs6000_is_valid_and_mask (GEN_INT (val + bit3 - bit2), mode);
 }
 
+/* Emit a potentially record-form instruction, setting DST from SRC.
+   If DOT is 0, that is all; otherwise, set CCREG to the result of the
+   signed comparison of DST with zero.  If DOT is 1, the generated RTL
+   doesn't care about the DST result; if DOT is 2, it does.  If CCREG
+   is CR0 do a single dot insn (as a PARALLEL); otherwise, do a SET and
+   a separate COMPARE.  */
+
+static void
+rs6000_emit_dot_insn (rtx dst, rtx src, int dot, rtx ccreg)
+{
+  if (dot == 0)
+    {
+      emit_move_insn (dst, src);
+      return;
+    }
+
+  if (cc_reg_not_cr0_operand (ccreg, CCmode))
+    {
+      emit_move_insn (dst, src);
+      emit_move_insn (ccreg, gen_rtx_COMPARE (CCmode, dst, const0_rtx));
+      return;
+    }
+
+  rtx ccset = gen_rtx_SET (ccreg, gen_rtx_COMPARE (CCmode, src, const0_rtx));
+  if (dot == 1)
+    {
+      rtx clobber = gen_rtx_CLOBBER (VOIDmode, dst);
+      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, ccset, clobber)));
+    }
+  else
+    {
+      rtx set = gen_rtx_SET (dst, src);
+      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, ccset, set)));
+    }
+}
+
 /* Emit the two insns to do an AND in mode MODE, with operands OPERANDS.
    If EXPAND is true, split rotate-and-mask instructions we generate to
    their constituent parts as well (this is used during expand); if DOT
-   is true, make the last insn a record-form instruction.  */
+   is 1, make the last insn a record-form instruction clobbering the
+   destination GPR and setting the CC reg (from operands[3]); if 2, set
+   that GPR as well as the CC reg.  */
 
 void
-rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, bool dot)
+rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, int dot)
 {
   gcc_assert (!(expand && dot));
 
-  /* We do not actually handle record form yet.  */
-  if (dot)
-    gcc_unreachable ();
-
   unsigned HOST_WIDE_INT val = INTVAL (operands[2]);
 
   /* If it is one stretch of ones, it is DImode; shift left, mask, then
@@ -16774,7 +16808,8 @@  rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, bool dot)
 	  rtx tmp = gen_rtx_ASHIFT (mode, operands[1], GEN_INT (shift));
 	  tmp = gen_rtx_AND (mode, tmp, GEN_INT (val << shift));
 	  emit_move_insn (operands[0], tmp);
-	  emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (shift)));
+	  tmp = gen_rtx_LSHIFTRT (mode, operands[0], GEN_INT (shift));
+	  rs6000_emit_dot_insn (operands[0], tmp, dot, dot ? operands[3] : 0);
 	}
       return;
     }
@@ -16800,7 +16835,7 @@  rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, bool dot)
       rtx tmp = gen_rtx_AND (mode, operands[1], GEN_INT (mask1));
       emit_move_insn (reg, tmp);
       tmp = gen_rtx_AND (mode, reg, GEN_INT (mask2));
-      emit_move_insn (operands[0], tmp);
+      rs6000_emit_dot_insn (operands[0], tmp, dot, dot ? operands[3] : 0);
       return;
     }
 
@@ -16817,7 +16852,7 @@  rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, bool dot)
       rtx reg_low = gen_lowpart (SImode, reg);
       emit_move_insn (reg_low, tmp);
       tmp = gen_rtx_AND (mode, reg, GEN_INT (mask2));
-      emit_move_insn (operands[0], tmp);
+      rs6000_emit_dot_insn (operands[0], tmp, dot, dot ? operands[3] : 0);
       return;
     }
 
@@ -16846,7 +16881,7 @@  rs6000_emit_2insn_and (machine_mode mode, rtx *operands, bool expand, bool dot)
       emit_move_insn (operands[0], tmp);
       tmp = gen_rtx_ROTATE (mode, operands[0], GEN_INT (right));
       tmp = gen_rtx_AND (mode, tmp, GEN_INT (mask2));
-      emit_move_insn (operands[0], tmp);
+      rs6000_emit_dot_insn (operands[0], tmp, dot, dot ? operands[3] : 0);
     }
 }
 
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index d37a4b5..997675a 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -2913,7 +2913,7 @@  (define_expand "and<mode>3"
 
   if (rs6000_is_valid_2insn_and (operands[2], <MODE>mode))
     {
-      rs6000_emit_2insn_and (<MODE>mode, operands, true, false);
+      rs6000_emit_2insn_and (<MODE>mode, operands, true, 0);
       DONE;
     }
 
@@ -3139,7 +3139,6 @@  (define_insn_and_split "*and<mode>3_mask_dot2"
    (set_attr "length" "4,8")])
 
 
-; TODO: dots of this
 (define_insn_and_split "*and<mode>3_2insn"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
 	(and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r")
@@ -3152,10 +3151,59 @@  (define_insn_and_split "*and<mode>3_2insn"
   "&& 1"
   [(pc)]
 {
-  rs6000_emit_2insn_and (<MODE>mode, operands, false, false);
+  rs6000_emit_2insn_and (<MODE>mode, operands, false, 0);
   DONE;
 }
-  [(set_attr "length" "8")])
+  [(set_attr "type" "shift")
+   (set_attr "length" "8")])
+
+(define_insn_and_split "*and<mode>3_2insn_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+	(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
+			     (match_operand:GPR 2 "const_int_operand" "n,n"))
+		    (const_int 0)))
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
+   && rs6000_gen_cell_microcode
+   && rs6000_is_valid_2insn_and (operands[2], <MODE>mode)
+   && !(rs6000_is_valid_and_mask (operands[2], <MODE>mode)
+	|| (logical_const_operand (operands[2], <MODE>mode)
+	    && rs6000_gen_cell_microcode))"
+  "#"
+  "&& reload_completed"
+  [(pc)]
+{
+  rs6000_emit_2insn_and (<MODE>mode, operands, false, 1);
+  DONE;
+}
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
+   (set_attr "length" "8,12")])
+
+(define_insn_and_split "*and<mode>3_2insn_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+	(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
+			     (match_operand:GPR 2 "const_int_operand" "n,n"))
+		    (const_int 0)))
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+	(and:GPR (match_dup 1)
+		 (match_dup 2)))]
+  "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
+   && rs6000_gen_cell_microcode
+   && rs6000_is_valid_2insn_and (operands[2], <MODE>mode)
+   && !(rs6000_is_valid_and_mask (operands[2], <MODE>mode)
+	|| (logical_const_operand (operands[2], <MODE>mode)
+	    && rs6000_gen_cell_microcode))"
+  "#"
+  "&& reload_completed"
+  [(pc)]
+{
+  rs6000_emit_2insn_and (<MODE>mode, operands, false, 2);
+  DONE;
+}
+  [(set_attr "type" "shift")
+   (set_attr "dot" "yes")
+   (set_attr "length" "8,12")])
 
 
 (define_expand "<code><mode>3"