Commit 954954d1 by Paul Brook Committed by Paul Brook

arm.c (use_return_insn): Use offsets->saved_regs_mask instead of {arm,thumb}_compute_save_reg_mask.

2008-03-12  Paul Brook  <paul@codesourcery.com>

	gcc/
	* config/arm/arm.c (use_return_insn): Use offsets->saved_regs_mask
	instead of {arm,thumb}_compute_save_reg_mask.
	(output_return_instruction): Ditto.
	(thumb_unexpanded_epilogue): Ditto.
	(thumb1_expand_prologue): Ditto.
	(thumb1_output_function_prologue): Ditto.
	(arm_set_return_address): Ditto.
	(thumb_set_return_address): Ditto.
	(arm_get_frame_offsets): Set offsets->saved_regs_mask.  Push extra
	regs to achieve stack alignment.
	(thumb1_compute_save_reg_mask): Fix compiler warning.
	(arm_output_epilogue): Use offsets->saved_regs_mask.
	Adjust stack pointer by poping call clobered registers.
	(arm_expand_prologue): Use offsets->saved_regs_mask.
	Adjust stack pointer by pushing extra registers.
	* gcc/config/arm.h (arm_stack_offsets): Add saved_regs_mask.

From-SVN: r133148
parent 4b700ab0
2008-03-12 Paul Brook <paul@codesourcery.com>
* config/arm/arm.c (use_return_insn): Use offsets->saved_regs_mask
instead of {arm,thumb}_compute_save_reg_mask.
(output_return_instruction): Ditto.
(thumb_unexpanded_epilogue): Ditto.
(thumb1_expand_prologue): Ditto.
(thumb1_output_function_prologue): Ditto.
(arm_set_return_address): Ditto.
(thumb_set_return_address): Ditto.
(arm_get_frame_offsets): Set offsets->saved_regs_mask. Push extra
regs to achieve stack alignment.
(thumb1_compute_save_reg_mask): Fix compiler warning.
(arm_output_epilogue): Use offsets->saved_regs_mask.
Adjust stack pointer by poping call clobered registers.
(arm_expand_prologue): Use offsets->saved_regs_mask.
Adjust stack pointer by pushing extra registers.
* gcc/config/arm.h (arm_stack_offsets): Add saved_regs_mask.
2008-03-12 Paolo Bonzini <bonzini@gnu.org>
PR tree-opt/35422
......
......@@ -74,7 +74,6 @@ static int thumb1_base_register_rtx_p (rtx, enum machine_mode, int);
inline static int thumb1_index_register_rtx_p (rtx, int);
static int thumb_far_jump_used_p (void);
static bool thumb_force_lr_save (void);
static unsigned long thumb1_compute_save_reg_mask (void);
static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
static rtx emit_sfm (int, int);
static unsigned arm_size_return_regs (void);
......@@ -1666,7 +1665,7 @@ use_return_insn (int iscond, rtx sibling)
&& stack_adjust == 4)))
return 0;
saved_int_regs = arm_compute_save_reg_mask ();
saved_int_regs = offsets->saved_regs_mask;
/* Unfortunately, the insn
......@@ -10750,7 +10749,8 @@ arm_compute_save_reg0_reg12_mask (void)
/* Compute a bit mask of which registers need to be
saved on the stack for the current function. */
saved on the stack for the current function.
This is used by arm_get_frame_offsets, which may add extra registers. */
static unsigned long
arm_compute_save_reg_mask (void)
......@@ -10878,7 +10878,7 @@ thumb1_compute_save_reg_mask (void)
reg = thumb_find_work_register (1 << LAST_LO_REGNUM);
/* Make sure the register returned by thumb_find_work_register is
not part of the return value. */
if (reg * UNITS_PER_WORD <= arm_size_return_regs ())
if (reg * UNITS_PER_WORD <= (unsigned) arm_size_return_regs ())
reg = LAST_LO_REGNUM;
if (! call_used_regs[reg])
......@@ -10975,7 +10975,8 @@ output_return_instruction (rtx operand, int really_return, int reverse)
return_used_this_function = 1;
live_regs_mask = arm_compute_save_reg_mask ();
offsets = arm_get_frame_offsets ();
live_regs_mask = offsets->saved_regs_mask;
if (live_regs_mask)
{
......@@ -11037,7 +11038,6 @@ output_return_instruction (rtx operand, int really_return, int reverse)
{
unsigned HOST_WIDE_INT stack_adjust;
offsets = arm_get_frame_offsets ();
stack_adjust = offsets->outgoing_args - offsets->saved_regs;
gcc_assert (stack_adjust == 0 || stack_adjust == 4);
......@@ -11285,7 +11285,7 @@ arm_output_epilogue (rtx sibling)
gcc_assert (!current_function_calls_eh_return || really_return);
offsets = arm_get_frame_offsets ();
saved_regs_mask = arm_compute_save_reg_mask ();
saved_regs_mask = offsets->saved_regs_mask;
if (TARGET_IWMMXT)
lrm_count = bit_count (saved_regs_mask);
......@@ -11482,8 +11482,35 @@ arm_output_epilogue (rtx sibling)
}
else
{
unsigned long count;
operands[0] = stack_pointer_rtx;
amount = offsets->outgoing_args - offsets->saved_regs;
/* pop call clobbered registers if it avoids a
separate stack adjustment. */
count = offsets->saved_regs - offsets->saved_args;
if (optimize_size
&& count != 0
&& !current_function_calls_eh_return
&& bit_count(saved_regs_mask) * 4 == count
&& !IS_INTERRUPT (func_type)
&& !cfun->tail_call_emit)
{
unsigned long mask;
mask = (1 << (arm_size_return_regs() / 4)) - 1;
mask ^= 0xf;
mask &= ~saved_regs_mask;
reg = 0;
while (bit_count (mask) * 4 > amount)
{
while ((mask & (1 << reg)) == 0)
reg++;
mask &= ~(1 << reg);
}
if (bit_count (mask) * 4 == amount) {
amount = 0;
saved_regs_mask |= mask;
}
}
}
if (amount)
......@@ -11954,7 +11981,8 @@ thumb_force_lr_save (void)
/* Calculate stack offsets. These are used to calculate register elimination
offsets and in prologue/epilogue code. */
offsets and in prologue/epilogue code. Also calculates which registers
should be saved. */
static arm_stack_offsets *
arm_get_frame_offsets (void)
......@@ -11963,7 +11991,9 @@ arm_get_frame_offsets (void)
unsigned long func_type;
int leaf;
int saved;
int core_saved;
HOST_WIDE_INT frame_size;
int i;
offsets = &cfun->machine->stack_offsets;
......@@ -11996,7 +12026,9 @@ arm_get_frame_offsets (void)
{
unsigned int regno;
saved = bit_count (arm_compute_save_reg_mask ()) * 4;
offsets->saved_regs_mask = arm_compute_save_reg_mask ();
core_saved = bit_count (offsets->saved_regs_mask) * 4;
saved = core_saved;
/* We know that SP will be doubleword aligned on entry, and we must
preserve that condition at any subroutine call. We also require the
......@@ -12027,7 +12059,9 @@ arm_get_frame_offsets (void)
}
else /* TARGET_THUMB1 */
{
saved = bit_count (thumb1_compute_save_reg_mask ()) * 4;
offsets->saved_regs_mask = thumb1_compute_save_reg_mask ();
core_saved = bit_count (offsets->saved_regs_mask) * 4;
saved = core_saved;
if (TARGET_BACKTRACE)
saved += 16;
}
......@@ -12047,7 +12081,39 @@ arm_get_frame_offsets (void)
/* Ensure SFP has the correct alignment. */
if (ARM_DOUBLEWORD_ALIGN
&& (offsets->soft_frame & 7))
{
offsets->soft_frame += 4;
/* Try to align stack by pushing an extra reg. Don't bother doing this
when there is a stack frame as the alignment will be rolled into
the normal stack adjustment. */
if (frame_size + current_function_outgoing_args_size == 0)
{
int reg = -1;
for (i = 4; i <= (TARGET_THUMB1 ? LAST_LO_REGNUM : 11); i++)
{
if ((offsets->saved_regs_mask & (1 << i)) == 0)
{
reg = i;
break;
}
}
if (reg == -1 && arm_size_return_regs () <= 12
&& !cfun->tail_call_emit)
{
/* Push/pop an argument register (r3) if all callee saved
registers are already being pushed. */
reg = 3;
}
if (reg != -1)
{
offsets->saved_regs += 4;
offsets->saved_regs_mask |= (1 << reg);
}
}
}
offsets->locals_base = offsets->soft_frame + frame_size;
offsets->outgoing_args = (offsets->locals_base
......@@ -12303,7 +12369,8 @@ arm_expand_prologue (void)
args_to_push = current_function_pretend_args_size;
/* Compute which register we will have to save onto the stack. */
live_regs_mask = arm_compute_save_reg_mask ();
offsets = arm_get_frame_offsets ();
live_regs_mask = offsets->saved_regs_mask;
ip_rtx = gen_rtx_REG (SImode, IP_REGNUM);
......@@ -12456,8 +12523,28 @@ arm_expand_prologue (void)
if (live_regs_mask)
{
insn = emit_multi_reg_push (live_regs_mask);
saved_regs += bit_count (live_regs_mask) * 4;
if (optimize_size && !frame_pointer_needed
&& saved_regs == offsets->saved_regs - offsets->saved_args)
{
/* If no coprocessor registers are being pushed and we don't have
to worry about a frame pointer then push extra registers to
create the stack frame. This is done is a way that does not
alter the frame layout, so is independent of the epilogue. */
int n;
int frame;
n = 0;
while (n < 8 && (live_regs_mask & (1 << n)) == 0)
n++;
frame = offsets->outgoing_args - (offsets->saved_args + saved_regs);
if (frame && n * 4 >= frame)
{
n = frame / 4;
live_regs_mask |= (1 << n) - 1;
saved_regs += frame;
}
}
insn = emit_multi_reg_push (live_regs_mask);
RTX_FRAME_RELATED_P (insn) = 1;
}
......@@ -12498,7 +12585,6 @@ arm_expand_prologue (void)
}
}
offsets = arm_get_frame_offsets ();
if (offsets->outgoing_args != offsets->saved_args + saved_regs)
{
/* This add can produce multiple insns for a large constant, so we
......@@ -16494,6 +16580,7 @@ is_called_in_ARM_mode (tree func)
const char *
thumb_unexpanded_epilogue (void)
{
arm_stack_offsets *offsets;
int regno;
unsigned long live_regs_mask = 0;
int high_regs_pushed = 0;
......@@ -16506,7 +16593,8 @@ thumb_unexpanded_epilogue (void)
if (IS_NAKED (arm_current_func_type ()))
return "";
live_regs_mask = thumb1_compute_save_reg_mask ();
offsets = arm_get_frame_offsets ();
live_regs_mask = offsets->saved_regs_mask;
high_regs_pushed = bit_count (live_regs_mask & 0x0f00);
/* If we can deduce the registers used from the function's return value.
......@@ -16768,7 +16856,8 @@ thumb1_expand_prologue (void)
return;
}
live_regs_mask = thumb1_compute_save_reg_mask ();
offsets = arm_get_frame_offsets ();
live_regs_mask = offsets->saved_regs_mask;
/* Load the pic register before setting the frame pointer,
so we can use r7 as a temporary work register. */
if (flag_pic && arm_pic_register != INVALID_REGNUM)
......@@ -16778,7 +16867,6 @@ thumb1_expand_prologue (void)
emit_move_insn (gen_rtx_REG (Pmode, ARM_HARD_FRAME_POINTER_REGNUM),
stack_pointer_rtx);
offsets = arm_get_frame_offsets ();
amount = offsets->outgoing_args - offsets->saved_regs;
if (amount)
{
......@@ -16940,6 +17028,7 @@ thumb1_expand_epilogue (void)
static void
thumb1_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
arm_stack_offsets *offsets;
unsigned long live_regs_mask = 0;
unsigned long l_mask;
unsigned high_regs_pushed = 0;
......@@ -17024,7 +17113,8 @@ thumb1_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
}
/* Get the registers we are going to push. */
live_regs_mask = thumb1_compute_save_reg_mask ();
offsets = arm_get_frame_offsets ();
live_regs_mask = offsets->saved_regs_mask;
/* Extract a mask of the ones we can give to the Thumb's push instruction. */
l_mask = live_regs_mask & 0x40ff;
/* Then count how many other high registers will need to be pushed. */
......@@ -18152,7 +18242,8 @@ arm_set_return_address (rtx source, rtx scratch)
rtx addr;
unsigned long saved_regs;
saved_regs = arm_compute_save_reg_mask ();
offsets = arm_get_frame_offsets ();
saved_regs = offsets->saved_regs_mask;
if ((saved_regs & (1 << LR_REGNUM)) == 0)
emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source);
......@@ -18163,7 +18254,6 @@ arm_set_return_address (rtx source, rtx scratch)
else
{
/* LR will be the first saved register. */
offsets = arm_get_frame_offsets ();
delta = offsets->outgoing_args - (offsets->frame + 4);
......@@ -18196,11 +18286,10 @@ thumb_set_return_address (rtx source, rtx scratch)
emit_insn (gen_rtx_USE (VOIDmode, source));
mask = thumb1_compute_save_reg_mask ();
offsets = arm_get_frame_offsets ();
mask = offsets->saved_regs_mask;
if (mask & (1 << LR_REGNUM))
{
offsets = arm_get_frame_offsets ();
limit = 1024;
/* Find the saved regs. */
if (frame_pointer_needed)
......
......@@ -1538,6 +1538,7 @@ typedef struct arm_stack_offsets GTY(())
int soft_frame; /* FRAME_POINTER_REGNUM. */
int locals_base; /* THUMB_HARD_FRAME_POINTER_REGNUM. */
int outgoing_args; /* STACK_POINTER_REGNUM. */
unsigned int saved_regs_mask;
}
arm_stack_offsets;
......
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