diff options
author | Ulrich Drepper <drepper@cygnus.com> | 1998-07-06 23:39:32 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1998-07-06 17:39:32 -0600 |
commit | 3403c6ca8f7d0abdb9c9907d7100136f3d2ae061 (patch) | |
tree | eba0dcca0c1c2cc66414929c47f7e56794db0f55 | |
parent | eb04ab5a1ad20cfd72b6e461d1be026ac418818e (diff) | |
download | gcc-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/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 55 |
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 |