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:
parent
0998d2fd59
commit
ca06b86c2f
@ -1,5 +1,28 @@
|
|||||||
2019-10-23 Michael Meissner <meissner@linux.ibm.com>
|
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.
|
* config/rs6000/rs6000.md (mov<mode>_64bit_dm): Reformat.
|
||||||
(movtd_64bit_nodm): Reformat.
|
(movtd_64bit_nodm): Reformat.
|
||||||
(mov<mode>_32bit): Reformat.
|
(mov<mode>_32bit): Reformat.
|
||||||
|
@ -194,6 +194,7 @@ extern bool prefixed_store_p (rtx_insn *);
|
|||||||
extern bool prefixed_paddi_p (rtx_insn *);
|
extern bool prefixed_paddi_p (rtx_insn *);
|
||||||
extern void rs6000_asm_output_opcode (FILE *);
|
extern void rs6000_asm_output_opcode (FILE *);
|
||||||
extern void rs6000_final_prescan_insn (rtx_insn *, rtx [], int);
|
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
|
/* 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.
|
immediate instructions that cannot be used with a non-prefixed instruction.
|
||||||
|
@ -21076,14 +21076,32 @@ rs6000_insn_cost (rtx_insn *insn, bool speed)
|
|||||||
if (recog_memoized (insn) < 0)
|
if (recog_memoized (insn) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* If we are optimizing for size, just use the length. */
|
||||||
if (!speed)
|
if (!speed)
|
||||||
return get_attr_length (insn);
|
return get_attr_length (insn);
|
||||||
|
|
||||||
|
/* Use the cost if provided. */
|
||||||
int cost = get_attr_cost (insn);
|
int cost = get_attr_cost (insn);
|
||||||
if (cost > 0)
|
if (cost > 0)
|
||||||
return cost;
|
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);
|
enum attr_type type = get_attr_type (insn);
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
@ -25087,6 +25105,37 @@ rs6000_asm_output_opcode (FILE *stream)
|
|||||||
return;
|
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
|
#ifdef HAVE_GAS_HIDDEN
|
||||||
# define USE_HIDDEN_LINKONCE 1
|
# define USE_HIDDEN_LINKONCE 1
|
||||||
|
@ -1847,9 +1847,19 @@ extern scalar_int_mode rs6000_pmode;
|
|||||||
/* Adjust the length of an INSN. LENGTH is the currently-computed length and
|
/* 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
|
should be adjusted to reflect any required changes. This macro is used when
|
||||||
there is some systematic length adjustment required that would be difficult
|
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
|
/* Given a comparison code (EQ, NE, etc.) and the first operand of a
|
||||||
COMPARE, return the mode to be used for the comparison. For
|
COMPARE, return the mode to be used for the comparison. For
|
||||||
|
@ -285,20 +285,24 @@
|
|||||||
|
|
||||||
(const_string "no")))
|
(const_string "no")))
|
||||||
|
|
||||||
;; Length in bytes of instructions that use prefixed addressing and length in
|
;; Return the number of real hardware instructions in a combined insn. If it
|
||||||
;; bytes of instructions that does not use prefixed addressing. This allows
|
;; is 0, just use the length / 4.
|
||||||
;; both lengths to be defined as constants, and the length attribute can pick
|
(define_attr "num_insns" "" (const_int 0))
|
||||||
;; 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
|
;; If an insn is prefixed, return the maximum number of prefixed instructions
|
||||||
;; assembler might issue need to issue a NOP so that the prefixed instruction
|
;; in the insn. The macro ADJUST_INSN_LENGTH uses this number to adjust the
|
||||||
;; does not cross a cache boundary, which makes them possibly 12 bytes.
|
;; insn length.
|
||||||
(define_attr "length" ""
|
(define_attr "max_prefixed_insns" "" (const_int 1))
|
||||||
(if_then_else (eq_attr "prefixed" "yes")
|
|
||||||
(attr "prefixed_length")
|
;; Length of the instruction (in bytes). This length does not consider the
|
||||||
(attr "non_prefixed_length")))
|
;; 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
|
;; Processor type -- this attribute must exactly match the processor_type
|
||||||
;; enumeration in rs6000-opts.h.
|
;; enumeration in rs6000-opts.h.
|
||||||
@ -7766,7 +7770,9 @@
|
|||||||
DONE;
|
DONE;
|
||||||
}
|
}
|
||||||
[(set_attr "length" "8")
|
[(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"
|
(define_insn_and_split "*movtd_64bit_nodm"
|
||||||
[(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
|
[(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]);
|
rs6000_split_multireg_move (operands[0], operands[1]);
|
||||||
DONE;
|
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"
|
(define_insn_and_split "*mov<mode>_32bit"
|
||||||
[(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,d,Y,r,r")
|
[(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);
|
return rs6000_output_move_128bit (operands);
|
||||||
}
|
}
|
||||||
[(set_attr "type" "store,store,load,load,*,*")
|
[(set_attr "type" "store,store,load,load,*,*")
|
||||||
(set_attr "length" "8")])
|
(set_attr "length" "8")
|
||||||
|
(set_attr "max_prefixed_insns" "2")])
|
||||||
|
|
||||||
(define_split
|
(define_split
|
||||||
[(set (match_operand:TI2 0 "int_reg_operand")
|
[(set (match_operand:TI2 0 "int_reg_operand")
|
||||||
|
@ -1149,6 +1149,14 @@
|
|||||||
"vecstore, vecload, vecsimple, mffgpr, mftgpr, load,
|
"vecstore, vecload, vecsimple, mffgpr, mftgpr, load,
|
||||||
store, load, store, *, vecsimple, vecsimple,
|
store, load, store, *, vecsimple, vecsimple,
|
||||||
vecsimple, *, *, vecstore, vecload")
|
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"
|
(set_attr "length"
|
||||||
"*, *, *, 8, *, 8,
|
"*, *, *, 8, *, 8,
|
||||||
8, 8, 8, 8, *, *,
|
8, 8, 8, 8, *, *,
|
||||||
|
Loading…
Reference in New Issue
Block a user