Minor H8 shift code generation change in preparation for cc0 removal
authorJeff Law <law@redhat.com>
Thu, 19 Nov 2020 04:01:06 +0000 (21:01 -0700)
committerJeff Law <law@redhat.com>
Thu, 19 Nov 2020 04:01:06 +0000 (21:01 -0700)
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.

gcc/config/h8300/constraints.md
gcc/config/h8300/h8300-protos.h
gcc/config/h8300/h8300.c
gcc/config/h8300/shiftrotate.md

index d24518225f8a720465863e52e0b0191261ddef82..1d80152ce412fdfd745dc9e3eedab1d72b49a43d 100644 (file)
 (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"
 (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."
index 2416741e76a4c4c4b77575f793b84b6f6243534c..8a8ebf6f490fe648bdfb446ca9b3e24fe323579a 100644 (file)
@@ -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);
index 6875cd9b81ad3d6d65afb7be2249005659c909d4..767ecda79799e6759b8368ffb0acd51ccda65d41 100644 (file)
@@ -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.  */
index 75606d7c50b7190602f3547768770350da64b1bc..5a85e1673fe889cde9167c3522c63a796d2237b1 100644 (file)
    (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"
    (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"
    (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.