Generate RTL for return in Thumb2 mode. Used by expand of return insn.
2012-06-18 Ian Bolton <ian.bolton@arm.com> Sameera Deshpande <sameera.deshpande@arm.com> Greta Yorsh <greta.yorsh@arm.com> * config/arm/arm-protos.h (thumb2_expand_return): New declaration. * config/arm/arm.c (thumb2_expand_return): New function. * config/arm/arm.md (return): Update condition and code. Co-Authored-By: Greta Yorsh <greta.yorsh@arm.com> Co-Authored-By: Sameera Deshpande <sameera.deshpande@arm.com> From-SVN: r188744
This commit is contained in:
parent
f79b86a43e
commit
482baa63f3
|
@ -1,3 +1,11 @@
|
|||
2012-06-18 Ian Bolton <ian.bolton@arm.com>
|
||||
Sameera Deshpande <sameera.deshpande@arm.com>
|
||||
Greta Yorsh <greta.yorsh@arm.com>
|
||||
|
||||
* config/arm/arm-protos.h (thumb2_expand_return): New declaration.
|
||||
* config/arm/arm.c (thumb2_expand_return): New function.
|
||||
* config/arm/arm.md (return): Update condition and code.
|
||||
|
||||
2012-06-18 Ian Bolton <ian.bolton@arm.com>
|
||||
Sameera Deshpande <sameera.deshpande@arm.com>
|
||||
Greta Yorsh <greta.yorsh@arm.com>
|
||||
|
|
|
@ -31,6 +31,7 @@ extern int arm_volatile_func (void);
|
|||
extern const char *arm_output_epilogue (rtx);
|
||||
extern void arm_expand_prologue (void);
|
||||
extern void arm_expand_epilogue (bool);
|
||||
extern void thumb2_expand_return (void);
|
||||
extern const char *arm_strip_name_encoding (const char *);
|
||||
extern void arm_asm_output_labelref (FILE *, const char *);
|
||||
extern void thumb2_asm_output_opcode (FILE *);
|
||||
|
|
|
@ -23265,6 +23265,52 @@ thumb1_expand_prologue (void)
|
|||
cfun->machine->lr_save_eliminated = 0;
|
||||
}
|
||||
|
||||
/* Generate pattern *pop_multiple_with_stack_update_and_return if single
|
||||
POP instruction can be generated. LR should be replaced by PC. All
|
||||
the checks required are already done by USE_RETURN_INSN (). Hence,
|
||||
all we really need to check here is if single register is to be
|
||||
returned, or multiple register return. */
|
||||
void
|
||||
thumb2_expand_return (void)
|
||||
{
|
||||
int i, num_regs;
|
||||
unsigned long saved_regs_mask;
|
||||
arm_stack_offsets *offsets;
|
||||
|
||||
offsets = arm_get_frame_offsets ();
|
||||
saved_regs_mask = offsets->saved_regs_mask;
|
||||
|
||||
for (i = 0, num_regs = 0; i <= LAST_ARM_REGNUM; i++)
|
||||
if (saved_regs_mask & (1 << i))
|
||||
num_regs++;
|
||||
|
||||
if (saved_regs_mask)
|
||||
{
|
||||
if (num_regs == 1)
|
||||
{
|
||||
rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
|
||||
rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
|
||||
rtx addr = gen_rtx_MEM (SImode,
|
||||
gen_rtx_POST_INC (SImode,
|
||||
stack_pointer_rtx));
|
||||
set_mem_alias_set (addr, get_frame_alias_set ());
|
||||
XVECEXP (par, 0, 0) = ret_rtx;
|
||||
XVECEXP (par, 0, 1) = gen_rtx_SET (SImode, reg, addr);
|
||||
RTX_FRAME_RELATED_P (XVECEXP (par, 0, 1)) = 1;
|
||||
emit_jump_insn (par);
|
||||
}
|
||||
else
|
||||
{
|
||||
saved_regs_mask &= ~ (1 << LR_REGNUM);
|
||||
saved_regs_mask |= (1 << PC_REGNUM);
|
||||
arm_emit_multi_reg_pop (saved_regs_mask);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_jump_insn (simple_return_rtx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
thumb1_expand_epilogue (void)
|
||||
|
|
|
@ -8505,8 +8505,20 @@
|
|||
|
||||
(define_expand "return"
|
||||
[(return)]
|
||||
"TARGET_32BIT && USE_RETURN_INSN (FALSE)"
|
||||
"")
|
||||
"(TARGET_ARM || (TARGET_THUMB2
|
||||
&& ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
|
||||
&& !IS_STACKALIGN (arm_current_func_type ())))
|
||||
&& USE_RETURN_INSN (FALSE)"
|
||||
"
|
||||
{
|
||||
if (TARGET_THUMB2)
|
||||
{
|
||||
thumb2_expand_return ();
|
||||
DONE;
|
||||
}
|
||||
}
|
||||
"
|
||||
)
|
||||
|
||||
;; Often the return insn will be the same as loading from memory, so set attr
|
||||
(define_insn "*arm_return"
|
||||
|
|
Loading…
Reference in New Issue