Fix insn length for pdp11 shift patterns.
authorPaul Koning <ni1d@arrl.net>
Thu, 28 Jun 2018 18:50:12 +0000 (14:50 -0400)
committerPaul Koning <pkoning@gcc.gnu.org>
Thu, 28 Jun 2018 18:50:12 +0000 (14:50 -0400)
* config/pdp11/pdp11-protos.h (pdp11_shift_length): New function.
* config/pdp11/pdp11.c (pdp11_shift_length): New function.
* config/pdp11/pdp11.h (ADJUST_INSN_LENGTH): Remove.
* config/pdp11/pdp11.md: Correct "length" attribute calculation
for shift insn patterns.

From-SVN: r262227

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

index 92e31fcd6eef1caecd40d26f6d22b2e574ada0b9..1edab9e2be65ddd45af6caf7e83a22b171103d7f 100644 (file)
@@ -1,3 +1,11 @@
+2018-06-28  Paul Koning  <ni1d@arrl.net>
+
+       * config/pdp11/pdp11-protos.h (pdp11_shift_length): New function.
+       * config/pdp11/pdp11.c (pdp11_shift_length): New function.
+       * config/pdp11/pdp11.h (ADJUST_INSN_LENGTH): Remove.
+       * config/pdp11/pdp11.md: Correct "length" attribute calculation
+       for shift insn patterns.
+
 2018-06-28  David Malcolm  <dmalcolm@redhat.com>
 
        * cgraph.c (cgraph_node::get_body): Replace assignments to
index 453632314d7fd699983b49f4c46fedee0acd2170..754a29df40b728468bd7780308e3b2dee97b06c9 100644 (file)
@@ -41,6 +41,7 @@ extern machine_mode pdp11_cc_mode (enum rtx_code, rtx, rtx);
 extern bool pdp11_expand_shift (rtx *, rtx (*) (rtx, rtx, rtx),
                                rtx (*) (rtx, rtx, rtx));
 extern const char * pdp11_assemble_shift (rtx *, machine_mode, int);
+extern int pdp11_shift_length (rtx *, machine_mode, int, bool);
 extern bool pdp11_small_shift (int);
 
 #endif /* RTX_CODE */
index ab73693d1da4236172b8607d8d24e31e48599a7b..142a5655114ee886637a9b7606ddd57057d84c59 100644 (file)
@@ -2020,6 +2020,35 @@ pdp11_assemble_shift (rtx *operands, machine_mode m, int code)
   return "";
 }
 
+/* Figure out the length of the instructions that will be produced for
+   the given operands by pdp11_assemble_shift above.  */
+int
+pdp11_shift_length (rtx *operands, machine_mode m, int code, bool simple_operand_p)
+{
+  int shift_size;
+
+  /* Shift by 1 is 2 bytes if simple operand, 4 bytes if 2-word addressing mode.  */
+  shift_size = simple_operand_p ? 2 : 4;
+
+  /* In SImode, two shifts are needed per data item.  */
+  if (m == E_SImode)
+    shift_size *= 2;
+
+  /* If shifting by a small constant, the loop is unrolled by the
+     shift count.  Otherwise, account for the size of the decrement
+     and branch.  */
+  if (CONSTANT_P (operands[2]) && pdp11_small_shift (INTVAL (operands[2])))
+    shift_size *= INTVAL (operands[2]);
+  else
+    shift_size += 4;
+
+  /* Logical right shift takes one more instruction (CLC).  */
+  if (code == LSHIFTRT)
+    shift_size += 2;
+
+  return shift_size;
+}
+
 /* Worker function for TARGET_TRAMPOLINE_INIT.
 
    trampoline - how should i do it in separate i+d ? 
index f995bc8672b37d979935726ebc93da861142014d..67386cab724c97295313e65a29f8b0c211358616 100644 (file)
@@ -123,22 +123,6 @@ extern const struct real_format pdp11_d_format;
 /* Define this if move instructions will actually fail to work
    when given unaligned data.  */
 #define STRICT_ALIGNMENT 1
-
-/* Adjust the length of shifts by small constant amounts.  The base
-   value (in "length" on input) is the length of a shift by one, not
-   including the CLC in logical shifts.  */
-#define ADJUST_INSN_LENGTH(insn, length) \
-  if ((GET_CODE (insn) == ASHIFT ||     \
-       GET_CODE (insn) == ASHIFTRT || \
-       GET_CODE (insn) == LSHIFTRT) && \
-      GET_CODE (XEXP (insn, 2)) == CONST_INT && \
-      pdp11_small_shift (XINT (insn, 2))) \
-    {                                    \
-      if (GET_CODE (insn) == LSHIFTRT)   \
-       length = (length * XINT (insn, 2)) + 2; \
-      else \
-       length *= XINT (insn, 2); \
-    }
 \f
 /* Standard register usage.  */
 
index 1dd069ff101b7cec1faaadf2fb12b85e80590229..6592a2cb806a0f8bc96a16d29ca9ee049e8c8562 100644 (file)
 ;; used to reduce the amount of very similar code.
 ;;
 ;; First the insns used for small constant shifts.
-;
-;; The "length" attribute values are modified by the ADJUST_INSN_LENGTH
-;; macro for the small constant shift case (first two alternatives).
-;; For those, the value coded in the length attribute is the cost of just
-;; the shift for a single shift.
 (define_insn "<code><mode>_sc"
   [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
        (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
                    (match_operand:HI 2 "expand_shift_operand" "O,O")))]
   ""
   "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
-  [(set_attr "length" "2,4")])
+  [(set (attr "length")
+       (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 
+                                         <CODE>, which_alternative == 0)"))])
 
 ;; Next, shifts that are done as a loop on base (11/10 class) machines.
 ;; This applies to shift counts too large to unroll, or variable shift
    (clobber (match_dup 2))]
   ""
   "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
-  [(set_attr "length" "2,4")])
+  [(set (attr "length")
+       (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 
+                                         <CODE>, which_alternative == 0)"))])
 
 ;; Next the insns that use the extended instructions ash and ashc.
 ;; Note that these are just left shifts, and HI/SI only.  (Right shifts