@@ -13273,10 +13273,13 @@ choose_basereg (HOST_WIDE_INT cfa_offset, rtx &base_reg,
}
/* Return an RTX that points to CFA_OFFSET within the stack frame and
- the alignment of address. If align is non-null, it should point to
+ the alignment of address. If ALIGN is non-null, it should point to
an alignment value (in bits) that is preferred or zero and will
- recieve the alignment of the base register that was selected. The
- valid base registers are taken from CFUN->MACHINE->FS. */
+ recieve the alignment of the base register that was selected,
+ irrespective of rather or not CFA_OFFSET is a multiple of that
+ alignment value.
+
+ The valid base registers are taken from CFUN->MACHINE->FS. */
static rtx
choose_baseaddr (HOST_WIDE_INT cfa_offset, unsigned int *align)
@@ -14322,35 +14325,35 @@ ix86_emit_outlined_ms2sysv_save (const struct ix86_frame &frame)
rtx sym, addr;
rtx rax = gen_rtx_REG (word_mode, AX_REG);
const struct xlogue_layout &xlogue = xlogue_layout::get_instance ();
- HOST_WIDE_INT rax_offset = xlogue.get_stub_ptr_offset () + m->fs.sp_offset;
- HOST_WIDE_INT stack_alloc_size = frame.stack_pointer_offset - m->fs.sp_offset;
- HOST_WIDE_INT stack_align_off_in = xlogue.get_stack_align_off_in ();
+ HOST_WIDE_INT allocate = frame.stack_pointer_offset - m->fs.sp_offset;
+
+ /* AL should only be live with sysv_abi. */
+ gcc_assert (!ix86_eax_live_at_start_p ());
+
+ /* Setup RAX as the stub's base pointer. We use stack_realign_offset rather
+ we've actually realigned the stack or not. */
+ align = GET_MODE_ALIGNMENT (V4SFmode);
+ addr = choose_baseaddr (frame.stack_realign_offset
+ + xlogue.get_stub_ptr_offset (), &align);
+ gcc_assert (align >= GET_MODE_ALIGNMENT (V4SFmode));
+ emit_insn (gen_rtx_SET (rax, addr));
- /* Verify that the incoming stack 16-byte alignment offset matches the
- layout we're using. */
- gcc_assert (stack_align_off_in == (m->fs.sp_offset & UNITS_PER_WORD));
+ /* Allocate stack if not already done. */
+ if (allocate > 0)
+ pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (-allocate), -1, false);
/* Get the stub symbol. */
sym = xlogue.get_stub_rtx (frame_pointer_needed ? XLOGUE_STUB_SAVE_HFP
: XLOGUE_STUB_SAVE);
RTVEC_ELT (v, vi++) = gen_rtx_USE (VOIDmode, sym);
- /* Setup RAX as the stub's base pointer. */
- align = GET_MODE_ALIGNMENT (V4SFmode);
- addr = choose_baseaddr (rax_offset, &align);
- gcc_assert (align >= GET_MODE_ALIGNMENT (V4SFmode));
- insn = emit_insn (gen_rtx_SET (rax, addr));
-
- gcc_assert (stack_alloc_size >= xlogue.get_stack_space_used ());
- pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-stack_alloc_size), -1,
- m->fs.cfa_reg == stack_pointer_rtx);
for (i = 0; i < ncregs; ++i)
{
const xlogue_layout::reginfo &r = xlogue.get_reginfo (i);
rtx reg = gen_rtx_REG ((SSE_REGNO_P (r.regno) ? V4SFmode : word_mode),
r.regno);
- RTVEC_ELT (v, vi++) = gen_frame_store (reg, rax, -r.offset);;
+ RTVEC_ELT (v, vi++) = gen_frame_store (reg, rax, -r.offset);
}
gcc_assert (vi == (unsigned)GET_NUM_ELEM (v));
@@ -14608,8 +14611,8 @@ ix86_expand_prologue (void)
that we must allocate the size of the register save area before
performing the actual alignment. Otherwise we cannot guarantee
that there's enough storage above the realignment point. */
- allocate = frame.stack_realign_allocate_offset - m->fs.sp_offset;
- if (allocate && !m->call_ms2sysv)
+ allocate = frame.stack_realign_allocate;
+ if (allocate)
pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (-allocate), -1, false);
@@ -14618,8 +14621,7 @@ ix86_expand_prologue (void)
stack_pointer_rtx,
GEN_INT (-align_bytes)));
m->fs.sp_offset = ROUND_UP (m->fs.sp_offset, align_bytes);
- m->fs.sp_realigned = true;
- m->fs.sp_realigned_offset = m->fs.sp_offset - frame.nsseregs * 16;
+ m->fs.sp_realigned_offset = m->fs.sp_offset - allocate;
/* The stack pointer may no longer be equal to CFA - m->fs.sp_offset.
Beyond this point, stack access should be done via choose_baseaddr or
by using sp_valid_at and fp_valid_at to determine the correct base
@@ -14627,6 +14629,8 @@ ix86_expand_prologue (void)
and not physical. */
gcc_assert (m->fs.sp_realigned_offset >= m->fs.sp_realigned_fp_last);
gcc_assert (m->fs.sp_realigned_offset == frame.stack_realign_offset);
+ m->fs.sp_realigned = true;
+
/* SEH unwind emit doesn't currently support REG_CFA_EXPRESSION, which
is needed to describe where a register is saved using a realigned
stack pointer, so we need to invalidate the stack pointer for that
@@ -14688,7 +14692,7 @@ ix86_expand_prologue (void)
so probe if the size is non-negative to preserve the protection area. */
if (allocate >= 0 && flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
{
- /* We expect the registers to be saved when probes are used. */
+ /* We expect the GP registers to be saved when probes are used. */
gcc_assert (int_registers_saved);
if (STACK_CHECK_MOVING_SP)
The SP allocation calculation is now done in ix86_compute_frame_layout and the result stored in ix86_frame::stack_realign_allocate. This change also updates comments for choose_baseaddr to clarify that the alignment returned doesn't necessarily reflect the alignment of the cfa_offset passed (e.g., you can pass cfa_offset 48 and it can return an alignment of 64 bytes). Since the alignment required may be more than 16-bytes, we cannot defer SP allocation to ix86_emit_outlined_ms2sysv_save (when it's enabled), so that function needs to be updated as well. Signed-off-by: Daniel Santos <daniel.santos@pobox.com> --- gcc/config/i386/i386.c | 54 +++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 25 deletions(-)