[committed] Fix insn length in pdp11 shift patterns

Message ID 4E5CA69F-8782-458B-9B35-DB6DE07186E7@comcast.net
State New
Headers show
Series
  • [committed] Fix insn length in pdp11 shift patterns
Related show

Commit Message

Paul Koning June 28, 2018, 6:51 p.m.
This patch corrects the setting of the "length" attributes in the pdp11 target for certain shift cases.

Committed.

	paul

ChangeLog:

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.

Patch

Index: config/pdp11/pdp11-protos.h
===================================================================
--- config/pdp11/pdp11-protos.h	(revision 262198)
+++ config/pdp11/pdp11-protos.h	(working copy)
@@ -41,6 +41,7 @@  extern machine_mode pdp11_cc_mode (enum rtx_code,
 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: config/pdp11/pdp11.c
===================================================================
--- config/pdp11/pdp11.c	(revision 262198)
+++ config/pdp11/pdp11.c	(working copy)
@@ -2020,6 +2020,35 @@  pdp11_assemble_shift (rtx *operands, machine_mode
   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: config/pdp11/pdp11.h
===================================================================
--- config/pdp11/pdp11.h	(revision 262198)
+++ config/pdp11/pdp11.h	(working copy)
@@ -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); \
-    }
 
 /* Standard register usage.  */
 
Index: config/pdp11/pdp11.md
===================================================================
--- config/pdp11/pdp11.md	(revision 262198)
+++ config/pdp11/pdp11.md	(working copy)
@@ -1297,11 +1297,6 @@ 
 ;; 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")
@@ -1308,7 +1303,9 @@ 
 	            (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
@@ -1320,7 +1317,9 @@ 
    (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