Rework how prefixed instruction length is calculated.
authorMichael Meissner <meissner@linux.ibm.com>
Wed, 23 Oct 2019 20:53:08 +0000 (20:53 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Wed, 23 Oct 2019 20:53:08 +0000 (20:53 +0000)
2019-10-23  Michael Meissner  <meissner@linux.ibm.com>

* config/rs6000/rs6000-protos.h (rs6000_adjust_insn_length): New
declaration.
* config/rs6000/rs6000.c (rs6000_insn_cost): Use num_insns insn
attribute if it exists, rather than the insn size.  If we use the
insn size, adjust the size to remove the extra size that prefixed
instructions take.
(rs6000_adjust_insn_length): New function.
* config/rs6000/rs6000.h (ADJUST_INSN_LENGTH): New target hook to
update the instruction sized if prefixed instructions are used.
* config/rs6000/rs6000.md (prefixed_length attribute): Delete.
(non_prefixed_length attribute): Delete.
(num_insns attribute): New insn attribute to return the number of
instructions.
(max_prefixed_insns attribute): New insn attribute to return the
maximum number of prefixed instructions in an insn.
(length attribute): Do not adjust for prefix instructions here,
punt to ADJUST_INSN_LENGTH.
(mov<mode>_64bit): Set max_prefixed_insns and num_insns.
(movtd_64bit_nodm): Set max_prefixed_insns and num_insns.
(mov<mode>_ppc64): Set max_prefixed_insns and num_insns.
* config/rs6000/vsx.md: (vsx_mov<mode>_64bit): Set
max_prefixed_insns and num_insns.

From-SVN: r277352

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

index b3f874ba9cab5eaf19a6ebcabe087a99037831ab..0c81a1077afe8f78494961fa67d094eda06c24eb 100644 (file)
@@ -1,5 +1,28 @@
 2019-10-23  Michael Meissner  <meissner@linux.ibm.com>
 
+       * config/rs6000/rs6000-protos.h (rs6000_adjust_insn_length): New
+       declaration.
+       * config/rs6000/rs6000.c (rs6000_insn_cost): Use num_insns insn
+       attribute if it exists, rather than the insn size.  If we use the
+       insn size, adjust the size to remove the extra size that prefixed
+       instructions take.
+       (rs6000_adjust_insn_length): New function.
+       * config/rs6000/rs6000.h (ADJUST_INSN_LENGTH): New target hook to
+       update the instruction sized if prefixed instructions are used.
+       * config/rs6000/rs6000.md (prefixed_length attribute): Delete.
+       (non_prefixed_length attribute): Delete.
+       (num_insns attribute): New insn attribute to return the number of
+       instructions.
+       (max_prefixed_insns attribute): New insn attribute to return the
+       maximum number of prefixed instructions in an insn.
+       (length attribute): Do not adjust for prefix instructions here,
+       punt to ADJUST_INSN_LENGTH.
+       (mov<mode>_64bit): Set max_prefixed_insns and num_insns.
+       (movtd_64bit_nodm): Set max_prefixed_insns and num_insns.
+       (mov<mode>_ppc64): Set max_prefixed_insns and num_insns.
+       * config/rs6000/vsx.md: (vsx_mov<mode>_64bit): Set
+       max_prefixed_insns and num_insns.
+
        * config/rs6000/rs6000.md (mov<mode>_64bit_dm): Reformat.
        (movtd_64bit_nodm): Reformat.
        (mov<mode>_32bit): Reformat.
index 08dd88c3e4d6ca40a33d82cc15bc97a07dd8d9dd..6b27d73023af833a40b73cbeac192e83bf6e75fe 100644 (file)
@@ -194,6 +194,7 @@ extern bool prefixed_store_p (rtx_insn *);
 extern bool prefixed_paddi_p (rtx_insn *);
 extern void rs6000_asm_output_opcode (FILE *);
 extern void rs6000_final_prescan_insn (rtx_insn *, rtx [], int);
+extern int rs6000_adjust_insn_length (rtx_insn *, int);
 
 /* Return true if the address can be used for a prefixed load, store, or add
    immediate instructions that cannot be used with a non-prefixed instruction.
index 5876714d5626696f200c4be5f8d94ab03cb75120..13992217fd686dda2e57b36c13af9cdb238f1dc6 100644 (file)
@@ -21076,14 +21076,32 @@ rs6000_insn_cost (rtx_insn *insn, bool speed)
   if (recog_memoized (insn) < 0)
     return 0;
 
+  /* If we are optimizing for size, just use the length.  */
   if (!speed)
     return get_attr_length (insn);
 
+  /* Use the cost if provided.  */
   int cost = get_attr_cost (insn);
   if (cost > 0)
     return cost;
 
-  int n = get_attr_length (insn) / 4;
+  /* If the insn tells us how many insns there are, use that.  Otherwise use
+     the length/4.  Adjust the insn length to remove the extra size that
+     prefixed instructions take.  */
+  int n = get_attr_num_insns (insn);
+  if (n == 0)
+    {
+      int length = get_attr_length (insn);
+      if (get_attr_prefixed (insn) == PREFIXED_YES)
+       {
+         int adjust = 0;
+         ADJUST_INSN_LENGTH (insn, adjust);
+         length -= adjust;
+       }
+
+      n = length / 4;
+    }
+
   enum attr_type type = get_attr_type (insn);
 
   switch (type)
@@ -25087,6 +25105,37 @@ rs6000_asm_output_opcode (FILE *stream)
   return;
 }
 
+/* Adjust the length of an INSN.  LENGTH is the currently-computed length and
+   should be adjusted to reflect any required changes.  This macro is used when
+   there is some systematic length adjustment required that would be difficult
+   to express in the length attribute.
+
+   In the PowerPC, we use this to adjust the length of an instruction if one or
+   more prefixed instructions are generated, using the attribute
+   num_prefixed_insns.  A prefixed instruction is 8 bytes instead of 4, but the
+   hardware requires that a prefied instruciton does not cross a 64-byte
+   boundary.  This means the compiler has to assume the length of the first
+   prefixed instruction is 12 bytes instead of 8 bytes.  Since the length is
+   already set for the non-prefixed instruction, we just need to udpate for the
+   difference.  */
+
+int
+rs6000_adjust_insn_length (rtx_insn *insn, int length)
+{
+  if (TARGET_PREFIXED_ADDR && NONJUMP_INSN_P (insn))
+    {
+      rtx pattern = PATTERN (insn);
+      if (GET_CODE (pattern) != USE && GET_CODE (pattern) != CLOBBER
+         && get_attr_prefixed (insn) == PREFIXED_YES)
+       {
+         int num_prefixed = get_attr_max_prefixed_insns (insn);
+         length += 4 * (num_prefixed + 1);
+       }
+    }
+
+  return length;
+}
+
 \f
 #ifdef HAVE_GAS_HIDDEN
 # define USE_HIDDEN_LINKONCE 1
index 27373c55ad65225f9a92346fa86e28664fe1a3cb..a4ad3f8fc3eaf63663364f2cb0948cc946ff54d4 100644 (file)
@@ -1847,9 +1847,19 @@ extern scalar_int_mode rs6000_pmode;
 /* Adjust the length of an INSN.  LENGTH is the currently-computed length and
    should be adjusted to reflect any required changes.  This macro is used when
    there is some systematic length adjustment required that would be difficult
-   to express in the length attribute.  */
-
-/* #define ADJUST_INSN_LENGTH(X,LENGTH) */
+   to express in the length attribute.
+
+   In the PowerPC, we use this to adjust the length of an instruction if one or
+   more prefixed instructions are generated, using the attribute
+   num_prefixed_insns.  A prefixed instruction is 8 bytes instead of 4, but the
+   hardware requires that a prefied instruciton does not cross a 64-byte
+   boundary.  This means the compiler has to assume the length of the first
+   prefixed instruction is 12 bytes instead of 8 bytes.  Since the length is
+   already set for the non-prefixed instruction, we just need to udpate for the
+   difference.  */
+
+#define ADJUST_INSN_LENGTH(INSN,LENGTH)                                        \
+  (LENGTH) = rs6000_adjust_insn_length ((INSN), (LENGTH))
 
 /* Given a comparison code (EQ, NE, etc.) and the first operand of a
    COMPARE, return the mode to be used for the comparison.  For
index 60b8b8ce568ee94ecbb13acf0306b41a7149b848..a3c909fabfb545718cc58e7eb4039dc8bb8c321e 100644 (file)
 
        (const_string "no")))
 
-;; Length in bytes of instructions that use prefixed addressing and length in
-;; bytes of instructions that does not use prefixed addressing.  This allows
-;; both lengths to be defined as constants, and the length attribute can pick
-;; the size as appropriate.
-(define_attr "prefixed_length" "" (const_int 12))
-(define_attr "non_prefixed_length" "" (const_int 4))
-
-;; Length of the instruction (in bytes).  Prefixed insns are 8 bytes, but the
-;; assembler might issue need to issue a NOP so that the prefixed instruction
-;; does not cross a cache boundary, which makes them possibly 12 bytes.
-(define_attr "length" ""
-  (if_then_else (eq_attr "prefixed" "yes")
-               (attr "prefixed_length")
-               (attr "non_prefixed_length")))
+;; Return the number of real hardware instructions in a combined insn.  If it
+;; is 0, just use the length / 4.
+(define_attr "num_insns" "" (const_int 0))
+
+;; If an insn is prefixed, return the maximum number of prefixed instructions
+;; in the insn.  The macro ADJUST_INSN_LENGTH uses this number to adjust the
+;; insn length.
+(define_attr "max_prefixed_insns" "" (const_int 1))
+
+;; Length of the instruction (in bytes).  This length does not consider the
+;; length for prefixed instructions.  The macro ADJUST_INSN_LENGTH will adjust
+;; the length if there are prefixed instructions.
+;;
+;; While it might be tempting to use num_insns to calculate the length, it can
+;; be problematical unless all insn lengths are adjusted to use num_insns
+;; (i.e. if num_insns is 0, it will get the length, which in turn will get
+;; num_insns and recurse).
+(define_attr "length" "" (const_int 4))
 
 ;; Processor type -- this attribute must exactly match the processor_type
 ;; enumeration in rs6000-opts.h.
   DONE;
 }
   [(set_attr "length" "8")
-   (set_attr "isa" "*,*,*,*,*,*,*,*,p8v,p8v")])
+   (set_attr "isa" "*,*,*,*,*,*,*,*,p8v,p8v")
+   (set_attr "max_prefixed_insns" "2")
+   (set_attr "num_insns" "2")])
 
 (define_insn_and_split "*movtd_64bit_nodm"
   [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
   rs6000_split_multireg_move (operands[0], operands[1]);
   DONE;
 }
-  [(set_attr "length" "8,8,8,12,12,8")])
+  [(set_attr "length" "8,8,8,12,12,8")
+   (set_attr "max_prefixed_insns" "2")
+   (set_attr "num_insns" "2,2,2,3,3,2")])
 
 (define_insn_and_split "*mov<mode>_32bit"
   [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,d,Y,r,r")
   return rs6000_output_move_128bit (operands);
 }
   [(set_attr "type" "store,store,load,load,*,*")
-   (set_attr "length" "8")])
+   (set_attr "length" "8")
+   (set_attr "max_prefixed_insns" "2")])
 
 (define_split
   [(set (match_operand:TI2 0 "int_reg_operand")
index 3cc1277aaee7525269be6c489489c9e78582cda4..a0b2e7b1fc016a76b365b43308d3ea46e7a26178 100644 (file)
                "vecstore,  vecload,   vecsimple, mffgpr,    mftgpr,    load,
                 store,     load,      store,     *,         vecsimple, vecsimple,
                 vecsimple, *,         *,         vecstore,  vecload")
+   (set_attr "num_insns"
+               "*,         *,         *,         2,         *,         2,
+                2,         2,         2,         2,         *,         *,
+                *,         5,         2,         *,         *")
+   (set_attr "max_prefixed_insns"
+               "*,         *,         *,         *,         *,         2,
+                2,         2,         2,         2,         *,         *,
+                *,         *,         *,         *,         *")
    (set_attr "length"
                "*,         *,         *,         8,         *,         8,
                 8,         8,         8,         8,         *,         *,