Rework how prefixed instruction length is calculated.

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
This commit is contained in:
Michael Meissner 2019-10-23 20:53:08 +00:00 committed by Michael Meissner
parent 0998d2fd59
commit ca06b86c2f
6 changed files with 119 additions and 19 deletions

View 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.

View 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.

View 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;
}
#ifdef HAVE_GAS_HIDDEN
# define USE_HIDDEN_LINKONCE 1

View 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. */
to express in the length attribute.
/* #define ADJUST_INSN_LENGTH(X,LENGTH) */
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

View File

@ -285,20 +285,24 @@
(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))
;; 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))
;; 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")))
;; 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.
@ -7766,7 +7770,9 @@
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")
@ -7781,7 +7787,9 @@
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")
@ -8990,7 +8998,8 @@
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")

View File

@ -1149,6 +1149,14 @@
"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, *, *,