re PR target/66217 (PowerPC rotate/shift/mask instructions not optimal)
authorSegher Boessenkool <segher@kernel.crashing.org>
Thu, 23 Jul 2015 14:37:57 +0000 (16:37 +0200)
committerSegher Boessenkool <segher@gcc.gnu.org>
Thu, 23 Jul 2015 14:37:57 +0000 (16:37 +0200)
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.

From-SVN: r226112

gcc/ChangeLog
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index cc07d768c1293a647e6d4ea9cdb96d8d83c5c470..40977504c8bb1c2245a5b830ab78d33108e3159a 100644 (file)
@@ -1,3 +1,14 @@
+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.
+
 2015-07-23  Richard Biener  <rguenther@suse.de>
 
        * generic-match-head.c: Include cgraph.h.
index 30a7128ca56a66d99d172abbfb7f928481db8540..f5d34766990f32746fbb802317dff430c5d5ad64 100644 (file)
@@ -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);
index 3f0fe4ffeda16fc0b756aff01b7b0c9ac44f5ced..2eecde6ed43b188956f382799696582b504c2416 100644 (file)
@@ -16735,20 +16735,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
@@ -16773,7 +16807,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;
     }
@@ -16799,7 +16834,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;
     }
 
@@ -16816,7 +16851,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;
     }
 
@@ -16845,7 +16880,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);
     }
 }
 \f
index 4e64a365131d530afeb07a607b38d09e1684e703..f7fa3996b98ebe20f9095e8754fe4b39db0dbb39 100644 (file)
 
   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;
     }
 
    (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")
   "&& 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"