aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@cygnus.com>1998-07-06 23:39:32 +0000
committerJeff Law <law@gcc.gnu.org>1998-07-06 17:39:32 -0600
commit3403c6ca8f7d0abdb9c9907d7100136f3d2ae061 (patch)
treeeba0dcca0c1c2cc66414929c47f7e56794db0f55
parenteb04ab5a1ad20cfd72b6e461d1be026ac418818e (diff)
downloadgcc-3403c6ca8f7d0abdb9c9907d7100136f3d2ae061.zip
gcc-3403c6ca8f7d0abdb9c9907d7100136f3d2ae061.tar.gz
gcc-3403c6ca8f7d0abdb9c9907d7100136f3d2ae061.tar.bz2
i386.c (ix86_epilogue): For pentium processors...
* i386.c (ix86_epilogue): For pentium processors, try to deallocate 4 or 8 byte stacks with pop instructions instead of an add instruction. From-SVN: r20979
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/i386/i386.c55
2 files changed, 54 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b95a792..83eaeac 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+Tue Jul 7 00:36:41 1998 Ulrich Drepper <drepper@cygnus.com>
+
+ * i386.c (ix86_epilogue): For pentium processors, try to deallocate
+ 4 or 8 byte stacks with pop instructions instead of an add instruction.
+
Tue Jul 7 00:30:08 1998 Klaus Kaempf <kkaempf@rmi.de>
* alpha.c: Include tree.h before expr.h.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 45612c7..42c4dbb 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2353,14 +2353,57 @@ ix86_epilogue (do_rtl)
else if (tsize)
{
- /* If there is no frame pointer, we must still release the frame. */
- xops[0] = GEN_INT (tsize);
+ /* Intel's docs say that for 4 or 8 bytes of stack frame one should
+ use `pop' and not `add'. */
+ int use_pop = tsize == 4;
- if (do_rtl)
- emit_insn (gen_rtx (SET, VOIDmode, xops[2],
- gen_rtx (PLUS, SImode, xops[2], xops[0])));
+ /* Use two pops only for the Pentium processors. */
+ if (tsize == 8 && !TARGET_386 && !TARGET_486)
+ {
+ rtx retval = current_function_return_rtx;
+
+ xops[1] = gen_rtx_REG (SImode, 1); /* %edx */
+
+ /* This case is a bit more complex. Since we cannot pop into
+ %ecx twice we need a second register. But this is only
+ available if the return value is not of DImode in which
+ case the %edx register is not available. */
+ use_pop = (retval == NULL
+ || ! reg_overlap_mentioned_p (xops[1], retval));
+ }
+
+ if (use_pop)
+ {
+ xops[0] = gen_rtx_REG (SImode, 2); /* %ecx */
+
+ if (do_rtl)
+ {
+ /* We have to prevent the two pops here from being scheduled.
+ GCC otherwise would try in some situation to put other
+ instructions in between them which has a bad effect. */
+ emit_insn (gen_blockage ());
+ emit_insn (gen_pop (xops[0]));
+ if (tsize == 8)
+ emit_insn (gen_pop (xops[1]));
+ }
+ else
+ {
+ output_asm_insn ("pop%L0 %0", xops);
+ if (tsize == 8)
+ output_asm_insn ("pop%L1 %1", xops);
+ }
+ }
else
- output_asm_insn (AS2 (add%L2,%0,%2), xops);
+ {
+ /* If there is no frame pointer, we must still release the frame. */
+ xops[0] = GEN_INT (tsize);
+
+ if (do_rtl)
+ emit_insn (gen_rtx (SET, VOIDmode, xops[2],
+ gen_rtx (PLUS, SImode, xops[2], xops[0])));
+ else
+ output_asm_insn (AS2 (add%L2,%0,%2), xops);
+ }
}
#ifdef FUNCTION_BLOCK_PROFILER_EXIT