aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2010-08-04 16:58:33 -0700
committerRichard Henderson <rth@gcc.gnu.org>2010-08-04 16:58:33 -0700
commit87ec2632b86f9ecab4308bbbadb9f791bcd2e8fa (patch)
tree0cd27af831961cd09d4b844b2dffad6217d201ff /gcc
parentc9f4c45115dfba1d84958c1a971a333763976b7f (diff)
downloadgcc-87ec2632b86f9ecab4308bbbadb9f791bcd2e8fa.zip
gcc-87ec2632b86f9ecab4308bbbadb9f791bcd2e8fa.tar.gz
gcc-87ec2632b86f9ecab4308bbbadb9f791bcd2e8fa.tar.bz2
Remove code duplication in ix86_expand_epilogue.
Union the undo of the frame pointer between the pop and move code paths. Combine the local frame stack deallocation with the one for ix86_static_chain_on_stack, if possible. From-SVN: r162890
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/config/i386/i386.c129
2 files changed, 46 insertions, 87 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9866d8e..51249f2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,9 @@
2010-08-04 Richard Henderson <rth@redhat.com>
+ * config/i386/i386.c (ix86_expand_epilogue): Eliminate code
+ duplication deconstructing the frame pointer. Simplify
+ deallocation of the local stack frame.
+
* reg-notes.def (CFA_EXPRESSION): New.
* dwarf2out.c (dwarf2out_frame_debug): Handle it.
(dwarf2out_frame_debug_cfa_expression): New.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 96897be..4c1ebb8 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10101,49 +10101,11 @@ ix86_expand_epilogue (int style)
}
m->fs.sp_offset = UNITS_PER_WORD;
}
- else if (!frame_pointer_needed)
- {
- pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (m->fs.sp_offset
- - frame.reg_save_offset
- + frame.nregs * UNITS_PER_WORD),
- style, !using_drap);
- }
- else
- {
- if (stack_realign_fp)
- {
- /* We're re-defining what it means to be the local stack
- frame. Thus the FP is suddenly valid and the SP isn't. */
- m->fs.fp_valid = true;
- m->fs.sp_valid = false;
- m->fs.realigned = false;
- }
-
- /* Leave results in shorter dependency chains on CPUs that are
- able to grok it fast. */
- if (TARGET_USE_LEAVE
- || optimize_function_for_size_p (cfun)
- || !cfun->machine->use_fast_prologue_epilogue)
- ix86_emit_leave ();
- else
- {
- pro_epilogue_adjust_stack (stack_pointer_rtx,
- hard_frame_pointer_rtx,
- const0_rtx, style, !using_drap);
- ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx);
- }
- }
}
else
{
/* First step is to deallocate the stack frame so that we can
- pop the registers.
-
- If we realign stack with frame pointer, then stack pointer
- won't be able to recover via lea $offset(%bp), %sp, because
- there is a padding area between bp and sp for realign.
- "add $to_allocate, %sp" must be used instead. */
+ pop the registers. */
if (!m->fs.sp_valid)
{
pro_epilogue_adjust_stack (stack_pointer_rtx, hard_frame_pointer_rtx,
@@ -10161,34 +10123,38 @@ ix86_expand_epilogue (int style)
}
ix86_emit_restore_regs_using_pop ();
+ }
- if (frame_pointer_needed)
+ /* If we used a stack pointer and haven't already got rid of it,
+ then do so now. */
+ if (m->fs.fp_valid || stack_realign_fp)
+ {
+ if (stack_realign_fp)
{
- if (stack_realign_fp)
- {
- /* We're re-defining what it means to be the local stack
- frame. Thus the FP is suddenly valid and the SP isn't. */
- m->fs.fp_valid = true;
- m->fs.sp_valid = false;
- m->fs.realigned = false;
- }
-
- /* Leave results in shorter dependency chains on CPUs that are
- able to grok it fast. */
- if (TARGET_USE_LEAVE
- || (stack_realign_fp
- && (optimize_function_for_size_p (cfun)
- || !cfun->machine->use_fast_prologue_epilogue)))
- ix86_emit_leave ();
- else
- {
- if (stack_realign_fp)
- pro_epilogue_adjust_stack (stack_pointer_rtx,
- hard_frame_pointer_rtx,
- const0_rtx, style, !using_drap);
- ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx);
- }
- }
+ /* We're re-defining what it means to be the local stack
+ frame. Thus the FP is suddenly valid and the SP isn't. */
+ m->fs.fp_valid = true;
+ m->fs.sp_valid = false;
+ m->fs.realigned = false;
+ }
+
+ /* If the stack pointer is valid and pointing at the frame
+ pointer store address, then we only need a pop. */
+ if (m->fs.sp_valid && m->fs.sp_offset == frame.hard_frame_pointer_offset)
+ ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx);
+ /* Leave results in shorter dependency chains on CPUs that are
+ able to grok it fast. */
+ else if (TARGET_USE_LEAVE
+ || optimize_function_for_size_p (cfun)
+ || !cfun->machine->use_fast_prologue_epilogue)
+ ix86_emit_leave ();
+ else
+ {
+ pro_epilogue_adjust_stack (stack_pointer_rtx,
+ hard_frame_pointer_rtx,
+ const0_rtx, style, !using_drap);
+ ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx);
+ }
}
if (using_drap)
@@ -10222,31 +10188,20 @@ ix86_expand_epilogue (int style)
ix86_emit_restore_reg_using_pop (crtl->drap_reg);
}
- /* Remove the saved static chain from the stack. The use of ECX is
- merely as a scratch register, not as the actual static chain. */
- if (ix86_static_chain_on_stack)
- {
- rtx r, insn;
-
- gcc_assert (m->fs.cfa_reg == stack_pointer_rtx);
- m->fs.cfa_offset -= UNITS_PER_WORD;
- m->fs.sp_offset -= UNITS_PER_WORD;
-
- r = gen_rtx_REG (Pmode, CX_REG);
- insn = emit_insn (ix86_gen_pop1 (r));
-
- r = plus_constant (stack_pointer_rtx, UNITS_PER_WORD);
- r = gen_rtx_SET (VOIDmode, stack_pointer_rtx, r);
- add_reg_note (insn, REG_CFA_ADJUST_CFA, r);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- /* At this point we should have de-allocated the entire stack frame,
- so the stack pointer points to the return address. */
- gcc_assert (m->fs.sp_offset == UNITS_PER_WORD);
+ /* At this point the stack pointer must be valid, and we must have
+ restored all of the registers. We may not have deallocated the
+ entire stack frame. We've delayed this until now because it may
+ be possible to merge the local stack deallocation with the
+ deallocation forced by ix86_static_chain_on_stack. */
gcc_assert (m->fs.sp_valid);
gcc_assert (!m->fs.fp_valid);
gcc_assert (!m->fs.realigned);
+ if (m->fs.sp_offset != UNITS_PER_WORD)
+ {
+ pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (m->fs.sp_offset - UNITS_PER_WORD),
+ style, true);
+ }
/* Sibcall epilogues don't want a return instruction. */
if (style == 0)