Commit 5775d58c by Jiong Wang Committed by Jiong Wang

[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
parent a0d66002
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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment