Minor H8 shift code generation change in preparation for cc0 removal

Jeff Law law@redhat.com
Thu Nov 19 04:07:26 GMT 2020


So I didn't stay up late to work from Pago Pago this year and beat the
stage1 close, but I do want to flush out the removal of cc0 from the H8
port this cycle.  Given these patches only affect the H8 and the H8
would be killed this cycle without the conversion, I think this is
suitable even though we're past stage1 close.

This patch addresses an initial codegen issue that would have resulted
in regressions after removal of cc0.  The compare/test eliminate pass is
unable to handle multiple clobbers.  So patterns that clobber a scratch
and also clobber a condition code are never used to eliminate a
compare/test.

The H8 can shift 1 or 2 bits at a time depending on the precise model. 
Not surprisingly we have multiple strategies to implement shifts, some
of which clobber scratch registers -- but we have a clobber on every
shift insn and as a result they can not participate in compare/test
removal once cc0 is removed from the port.

This patch removes the clobber in the initial code generation in cases
where it's obviously not needed allowing those shifts to participate in
compare/test removal in a future patch.  It has the advantage that is
also generates slightly better code.  By installing this now the removal
of cc0 is a smaller patch, but more importantly, it allows for a more
direct comparison of the generated code before/after cc0 removal.

I've had my tester test before/after this patch with no regressions on
the major H8 multilibs.  I've also spot checked the generated code and
as expected it's ever-so-slightly better after this patch.

I'll be installing this on the trunk momentarily.  More patches will
follow, though probably not in rapid succession as my time to push this
stuff is very limited.

Jeff
-------------- next part --------------
commit 700337494e1b0d5ff608e1a3c77852381e264653
Author: Jeff Law <law@redhat.com>
Date:   Wed Nov 18 21:01:06 2020 -0700

    Minor H8 shift code generation change in preparation for cc0 removal
    
    So I didn't stay up late to work from pago pago this year and beat the stage1
    close, but I do want to flush out the removal of cc0 from the H8 port this
    cycle.  Given these patches only affect the H8 and the H8 would be killed this
    cycle without the conversion, I think this is suitable even though we're past
    stage1 close.
    
    This patch addresses an initial codegen issue that would have resulted in
    regressions after removal of cc0.  The compare/test eliminate pass is unable to
    handle multiple clobbers.  So patterns that clobber a scratch and also clobber
    a condition code are never used to eliminate a compare/test.
    
    The H8 can shift 1 or 2 bits at a time depending on the precise model.  Not
    surprisingly we have multiple strategies to implement shifts, some of which
    clobber scratch registers -- but we have a clobber on every shift insn and as
    a result they can not participate in compare/test removal once cc0 is removed
    from the port.
    
    This patch removes the clobber in the initial code generation in cases where
    it's obviously not needed allowing those shifts to participate in compare/test
    removal in a future patch.  It has the advantage that is also generates
    slightly better code.  By installing this now the removal of cc0 is a smaller
    patch, but more importantly, it allows for a more direct comparison of the
    generated code before/after cc0 removal.
    
    I've had my tester test before/after this patch with no regressions on the
    major H8 multilibs.  I've also spot checked the generated code and as expected
    it's ever-so-slightly better after this patch.
    
    I'll be installing this on the trunk momentarily.  More patches will follow,
    though probably not in rapid succession as my time to push this stuff is very
    limited.
    
    gcc/
    
            * config/h8300/constraints.md (R constraint): Add argument to call
            to h8300_shift_needs_scratch_p.
            (S and T constraints): Similary.
            * config/h8300/h8300-protos.h: Update h8300_shift_needs_scratch_p
            prototype.
            * config/h8300/h8300.c (expand_a_shift): Emit a different pattern
            if the shift does not require a scratch register.
            (h8300_shift_needs_scratch_p): Refine to be more accurate.
            * config/h8300/shiftrotate.md (shiftqi_noscratch): New pattern.
            (shifthi_noscratch, shiftsi_noscratch): Similarly.

diff --git a/gcc/config/h8300/constraints.md b/gcc/config/h8300/constraints.md
index d24518225f8..1d80152ce41 100644
--- a/gcc/config/h8300/constraints.md
+++ b/gcc/config/h8300/constraints.md
@@ -152,7 +152,7 @@
 (define_constraint "R"
   "@internal"
   (and (match_code "const_int")
-       (match_test "!h8300_shift_needs_scratch_p (ival, QImode)")))
+       (match_test "!h8300_shift_needs_scratch_p (ival, QImode, CLOBBER)")))
 
 (define_constraint "C"
   "@internal"
@@ -161,12 +161,12 @@
 (define_constraint "S"
   "@internal"
   (and (match_code "const_int")
-       (match_test "!h8300_shift_needs_scratch_p (ival, HImode)")))
+       (match_test "!h8300_shift_needs_scratch_p (ival, HImode, CLOBBER)")))
 
 (define_constraint "T"
   "@internal"
   (and (match_code "const_int")
-       (match_test "!h8300_shift_needs_scratch_p (ival, SImode)")))
+       (match_test "!h8300_shift_needs_scratch_p (ival, SImode, CLOBBER)")))
 
 (define_constraint "U"
   "An operand valid for a bset destination."
diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h
index 2416741e76a..8a8ebf6f490 100644
--- a/gcc/config/h8300/h8300-protos.h
+++ b/gcc/config/h8300/h8300-protos.h
@@ -47,7 +47,7 @@ extern enum attr_cc compute_logical_op_cc (machine_mode, rtx *);
 extern void h8300_expand_branch (rtx[]);
 extern void h8300_expand_store (rtx[]);
 extern bool expand_a_shift (machine_mode, enum rtx_code, rtx[]);
-extern int h8300_shift_needs_scratch_p (int, machine_mode);
+extern int h8300_shift_needs_scratch_p (int, machine_mode, rtx_code);
 extern int expand_a_rotate (rtx[]);
 extern int fix_bit_operand (rtx *, enum rtx_code);
 extern int h8300_adjust_insn_length (rtx, int);
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 6875cd9b81a..767ecda7979 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -3381,19 +3381,25 @@ expand_a_shift (machine_mode mode, enum rtx_code code, rtx operands[])
       break;
     }
 
-  emit_move_insn (copy_rtx (operands[0]), operands[1]);
-
   /* Need a loop to get all the bits we want  - we generate the
      code at emit time, but need to allocate a scratch reg now.  */
-
-  emit_insn (gen_rtx_PARALLEL
-	     (VOIDmode,
-	      gen_rtvec (2,
-			 gen_rtx_SET (copy_rtx (operands[0]),
-				      gen_rtx_fmt_ee (code, mode,
-						      copy_rtx (operands[0]), operands[2])),
-			 gen_rtx_CLOBBER (VOIDmode,
-					  gen_rtx_SCRATCH (QImode)))));
+  emit_move_insn (copy_rtx (operands[0]), operands[1]);
+  if (operands[2] == CONST0_RTX (QImode))
+    ;
+  else if (GET_CODE (operands[2]) == CONST_INT
+      && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), mode, code))
+    emit_insn (gen_rtx_SET (copy_rtx (operands[0]),
+			      gen_rtx_fmt_ee (code, mode,
+					      copy_rtx (operands[1]), operands[2])));
+  else
+    emit_insn (gen_rtx_PARALLEL
+	       (VOIDmode,
+		gen_rtvec (2,
+			   gen_rtx_SET (copy_rtx (operands[0]),
+					gen_rtx_fmt_ee (code, mode,
+							copy_rtx (operands[0]), operands[2])),
+			   gen_rtx_CLOBBER (VOIDmode,
+					    gen_rtx_SCRATCH (QImode)))));
   return true;
 }
 
@@ -3920,7 +3926,7 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
    needed for some shift with COUNT and MODE.  Return 0 otherwise.  */
 
 int
-h8300_shift_needs_scratch_p (int count, machine_mode mode)
+h8300_shift_needs_scratch_p (int count, machine_mode mode, enum rtx_code type)
 {
   enum h8_cpu cpu;
   int a, lr, ar;
@@ -3960,8 +3966,18 @@ h8300_shift_needs_scratch_p (int count, machine_mode mode)
     }
 
   /* On H8/300H, count == 8 uses a scratch register.  */
-  return (a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP
-	  || (TARGET_H8300H && mode == SImode && count == 8));
+  if (type == CLOBBER)
+    return (a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP
+	    || (TARGET_H8300H && mode == SImode && count == 8));
+  else if (type == ASHIFT)
+    return (a == SHIFT_LOOP
+	    || (TARGET_H8300H && mode == SImode && count == 8));
+  else if (type == LSHIFTRT)
+    return (lr == SHIFT_LOOP
+	    || (TARGET_H8300H && mode == SImode && count == 8));
+  else if (type == ASHIFTRT)
+    return (ar == SHIFT_LOOP
+	    || (TARGET_H8300H && mode == SImode && count == 8));
 }
 
 /* Output the assembler code for doing shifts.  */
diff --git a/gcc/config/h8300/shiftrotate.md b/gcc/config/h8300/shiftrotate.md
index 75606d7c50b..5a85e1673fe 100644
--- a/gcc/config/h8300/shiftrotate.md
+++ b/gcc/config/h8300/shiftrotate.md
@@ -101,6 +101,22 @@
    (set (attr "cc")
 	(symbol_ref "compute_a_shift_cc (insn, operands)"))])
 
+(define_insn "*shiftqi_noscratch"
+  [(set (match_operand:QI 0 "register_operand" "=r,r")
+	(match_operator:QI 3 "nshift_operator"
+	 [(match_operand:QI 1 "register_operand" "0,0")
+	  (match_operand:QI 2 "nonmemory_operand" "R,rn")]))]
+  "(GET_CODE (operands[2]) == CONST_INT
+    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode,
+				     GET_CODE (operands[3])))"
+{
+  return output_a_shift (operands);
+}
+  [(set (attr "length")
+	(symbol_ref "compute_a_shift_length (insn, operands)"))
+   (set (attr "cc")
+	(symbol_ref "compute_a_shift_cc (insn, operands)"))])
+
 (define_insn "*shifthi"
   [(set (match_operand:HI 0 "register_operand" "=r,r")
 	(match_operator:HI 3 "nshift_operator"
@@ -116,6 +132,22 @@
    (set (attr "cc")
 	(symbol_ref "compute_a_shift_cc (insn, operands)"))])
 
+(define_insn "*shifthi_noscratch"
+  [(set (match_operand:HI 0 "register_operand" "=r,r")
+	(match_operator:HI 3 "nshift_operator"
+	 [(match_operand:HI 1 "register_operand" "0,0")
+	  (match_operand:QI 2 "nonmemory_operand" "S,rn")]))]
+  "(GET_CODE (operands[2]) == CONST_INT
+    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode,
+				     GET_CODE (operands[3])))"
+{
+  return output_a_shift (operands);
+}
+  [(set (attr "length")
+	(symbol_ref "compute_a_shift_length (insn, operands)"))
+   (set (attr "cc")
+	(symbol_ref "compute_a_shift_cc (insn, operands)"))])
+
 (define_insn "*shiftsi"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
 	(match_operator:SI 3 "nshift_operator"
@@ -131,6 +163,22 @@
    (set (attr "cc")
 	(symbol_ref "compute_a_shift_cc (insn, operands)"))])
 
+(define_insn "*shiftsi_noscratch"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(match_operator:SI 3 "nshift_operator"
+	 [(match_operand:SI 1 "register_operand" "0,0")
+	  (match_operand:QI 2 "nonmemory_operand" "T,rn")]))]
+  "(GET_CODE (operands[2]) == CONST_INT
+    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode,
+				     GET_CODE (operands[3])))"
+{
+  return output_a_shift (operands);
+}
+  [(set (attr "length")
+	(symbol_ref "compute_a_shift_length (insn, operands)"))
+   (set (attr "cc")
+	(symbol_ref "compute_a_shift_cc (insn, operands)"))])
+
 
 ;; Split a variable shift into a loop.  If the register containing
 ;; the shift count dies, then we just use that register.


More information about the Gcc-patches mailing list