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:
Ian Bolton 2012-06-18 18:02:03 +00:00 committed by Greta Yorsh
parent f79b86a43e
commit 482baa63f3
4 changed files with 69 additions and 2 deletions

View File

@ -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>

View File

@ -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 *);

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

View File

@ -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"