mirror of git://gcc.gnu.org/git/gcc.git
[ARM] length pop* pattern in epilogue correctly
PR target/71061 * config/arm/arm-protos.h (arm_attr_length_pop_multi): New declaration. * config/arm/arm.c (arm_attr_length_pop_multi): New function to return length for pop patterns. (arm_attr_length_push_multi): Update comments. * config/arm/arm.md (*load_multiple_with_writeback): Set "length" attribute. (*pop_multiple_with_writeback_and_return): Likewise. (*pop_multiple_with_return): Likewise. From-SVN: r237331
This commit is contained in:
parent
a0d6600253
commit
5775d58c06
|
|
@ -1,3 +1,15 @@
|
||||||
|
2016-06-11 Jiong Wang <jiong.wang@arm.com>
|
||||||
|
|
||||||
|
PR target/71061
|
||||||
|
* config/arm/arm-protos.h (arm_attr_length_pop_multi): New declaration.
|
||||||
|
* config/arm/arm.c (arm_attr_length_pop_multi): New function to return
|
||||||
|
length for pop patterns.
|
||||||
|
(arm_attr_length_push_multi): Update comments.
|
||||||
|
* config/arm/arm.md (*load_multiple_with_writeback): Set "length"
|
||||||
|
attribute.
|
||||||
|
(*pop_multiple_with_writeback_and_return): Likewise.
|
||||||
|
(*pop_multiple_with_return): Likewise.
|
||||||
|
|
||||||
2016-06-11 Segher Boessenkool <segher@kernel.crashing.org>
|
2016-06-11 Segher Boessenkool <segher@kernel.crashing.org>
|
||||||
|
|
||||||
PR middle-end/71310
|
PR middle-end/71310
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,7 @@ extern const char *arm_output_iwmmxt_shift_immediate (const char *, rtx *, bool)
|
||||||
extern const char *arm_output_iwmmxt_tinsr (rtx *);
|
extern const char *arm_output_iwmmxt_tinsr (rtx *);
|
||||||
extern unsigned int arm_sync_loop_insns (rtx , rtx *);
|
extern unsigned int arm_sync_loop_insns (rtx , rtx *);
|
||||||
extern int arm_attr_length_push_multi(rtx, rtx);
|
extern int arm_attr_length_push_multi(rtx, rtx);
|
||||||
|
extern int arm_attr_length_pop_multi(rtx *, bool, bool);
|
||||||
extern void arm_expand_compare_and_swap (rtx op[]);
|
extern void arm_expand_compare_and_swap (rtx op[]);
|
||||||
extern void arm_split_compare_and_swap (rtx op[]);
|
extern void arm_split_compare_and_swap (rtx op[]);
|
||||||
extern void arm_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx, rtx);
|
extern void arm_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx, rtx);
|
||||||
|
|
|
||||||
|
|
@ -27793,7 +27793,7 @@ arm_preferred_rename_class (reg_class_t rclass)
|
||||||
return NO_REGS;
|
return NO_REGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the atrribute "length" of insn "*push_multi".
|
/* Compute the attribute "length" of insn "*push_multi".
|
||||||
So this function MUST be kept in sync with that insn pattern. */
|
So this function MUST be kept in sync with that insn pattern. */
|
||||||
int
|
int
|
||||||
arm_attr_length_push_multi(rtx parallel_op, rtx first_op)
|
arm_attr_length_push_multi(rtx parallel_op, rtx first_op)
|
||||||
|
|
@ -27810,6 +27810,11 @@ arm_attr_length_push_multi(rtx parallel_op, rtx first_op)
|
||||||
|
|
||||||
/* Thumb2 mode. */
|
/* Thumb2 mode. */
|
||||||
regno = REGNO (first_op);
|
regno = REGNO (first_op);
|
||||||
|
/* For PUSH/STM under Thumb2 mode, we can use 16-bit encodings if the register
|
||||||
|
list is 8-bit. Normally this means all registers in the list must be
|
||||||
|
LO_REGS, that is (R0 -R7). If any HI_REGS used, then we must use 32-bit
|
||||||
|
encodings. There is one exception for PUSH that LR in HI_REGS can be used
|
||||||
|
with 16-bit encoding. */
|
||||||
hi_reg = (REGNO_REG_CLASS (regno) == HI_REGS) && (regno != LR_REGNUM);
|
hi_reg = (REGNO_REG_CLASS (regno) == HI_REGS) && (regno != LR_REGNUM);
|
||||||
for (i = 1; i < num_saves && !hi_reg; i++)
|
for (i = 1; i < num_saves && !hi_reg; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -27822,6 +27827,56 @@ arm_attr_length_push_multi(rtx parallel_op, rtx first_op)
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compute the attribute "length" of insn. Currently, this function is used
|
||||||
|
for "*load_multiple_with_writeback", "*pop_multiple_with_return" and
|
||||||
|
"*pop_multiple_with_writeback_and_return". OPERANDS is the toplevel PARALLEL
|
||||||
|
rtx, RETURN_PC is true if OPERANDS contains return insn. WRITE_BACK_P is
|
||||||
|
true if OPERANDS contains insn which explicit updates base register. */
|
||||||
|
|
||||||
|
int
|
||||||
|
arm_attr_length_pop_multi (rtx *operands, bool return_pc, bool write_back_p)
|
||||||
|
{
|
||||||
|
/* ARM mode. */
|
||||||
|
if (TARGET_ARM)
|
||||||
|
return 4;
|
||||||
|
/* Thumb1 mode. */
|
||||||
|
if (TARGET_THUMB1)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
rtx parallel_op = operands[0];
|
||||||
|
/* Initialize to elements number of PARALLEL. */
|
||||||
|
unsigned indx = XVECLEN (parallel_op, 0) - 1;
|
||||||
|
/* Initialize the value to base register. */
|
||||||
|
unsigned regno = REGNO (operands[1]);
|
||||||
|
/* Skip return and write back pattern.
|
||||||
|
We only need register pop pattern for later analysis. */
|
||||||
|
unsigned first_indx = 0;
|
||||||
|
first_indx += return_pc ? 1 : 0;
|
||||||
|
first_indx += write_back_p ? 1 : 0;
|
||||||
|
|
||||||
|
/* A pop operation can be done through LDM or POP. If the base register is SP
|
||||||
|
and if it's with write back, then a LDM will be alias of POP. */
|
||||||
|
bool pop_p = (regno == SP_REGNUM && write_back_p);
|
||||||
|
bool ldm_p = !pop_p;
|
||||||
|
|
||||||
|
/* Check base register for LDM. */
|
||||||
|
if (ldm_p && REGNO_REG_CLASS (regno) == HI_REGS)
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
/* Check each register in the list. */
|
||||||
|
for (; indx >= first_indx; indx--)
|
||||||
|
{
|
||||||
|
regno = REGNO (XEXP (XVECEXP (parallel_op, 0, indx), 0));
|
||||||
|
/* For POP, PC in HI_REGS can be used with 16-bit encoding. See similar
|
||||||
|
comment in arm_attr_length_push_multi. */
|
||||||
|
if (REGNO_REG_CLASS (regno) == HI_REGS
|
||||||
|
&& (regno != PC_REGNUM || ldm_p))
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute the number of instructions emitted by output_move_double. */
|
/* Compute the number of instructions emitted by output_move_double. */
|
||||||
int
|
int
|
||||||
arm_count_output_move_double_insns (rtx *operands)
|
arm_count_output_move_double_insns (rtx *operands)
|
||||||
|
|
|
||||||
|
|
@ -10562,7 +10562,11 @@
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
[(set_attr "type" "load4")
|
[(set_attr "type" "load4")
|
||||||
(set_attr "predicable" "yes")]
|
(set_attr "predicable" "yes")
|
||||||
|
(set (attr "length")
|
||||||
|
(symbol_ref "arm_attr_length_pop_multi (operands,
|
||||||
|
/*return_pc=*/false,
|
||||||
|
/*write_back_p=*/true)"))]
|
||||||
)
|
)
|
||||||
|
|
||||||
;; Pop with return (as used in epilogue RTL)
|
;; Pop with return (as used in epilogue RTL)
|
||||||
|
|
@ -10591,7 +10595,10 @@
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
[(set_attr "type" "load4")
|
[(set_attr "type" "load4")
|
||||||
(set_attr "predicable" "yes")]
|
(set_attr "predicable" "yes")
|
||||||
|
(set (attr "length")
|
||||||
|
(symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
|
||||||
|
/*write_back_p=*/true)"))]
|
||||||
)
|
)
|
||||||
|
|
||||||
(define_insn "*pop_multiple_with_return"
|
(define_insn "*pop_multiple_with_return"
|
||||||
|
|
@ -10611,7 +10618,10 @@
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
[(set_attr "type" "load4")
|
[(set_attr "type" "load4")
|
||||||
(set_attr "predicable" "yes")]
|
(set_attr "predicable" "yes")
|
||||||
|
(set (attr "length")
|
||||||
|
(symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
|
||||||
|
/*write_back_p=*/false)"))]
|
||||||
)
|
)
|
||||||
|
|
||||||
;; Load into PC and return
|
;; Load into PC and return
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue