From 65954bd8cb428dbefe4d8342330e625fe5698a34 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Mon, 22 Mar 1999 15:47:07 -0700 Subject: [PATCH] i386.h (PREFERRED_STACK_BOUNDARY): Define. * i386.h (PREFERRED_STACK_BOUNDARY): Define. * i386.c (ix86_compute_frame_size): New function. (ix86_prologue, ix86_epilogue): Use it. * i386.h (INITIAL_ELIMINATION_OFFSET): Likewise. * reload1.c: Provide default for PREFERRED_STACK_BOUNDARY. From-SVN: r25909 --- gcc/ChangeLog | 11 ++++++ gcc/config/i386/i386.c | 81 +++++++++++++++++++++++++++++++++--------- gcc/config/i386/i386.h | 29 +++++++++------ gcc/reload1.c | 4 +++ 4 files changed, 98 insertions(+), 27 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f498514b605..b6d9332f3df 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +Mon Mar 22 23:41:49 1999 Jeffrey A Law (law@cygnus.com) + + * i386.h (PREFERRED_STACK_BOUNDARY): Define. + +Mon Mar 22 23:41:31 1999 John Wehle (john@feith.com) + + * i386.c (ix86_compute_frame_size): New function. + (ix86_prologue, ix86_epilogue): Use it. + * i386.h (INITIAL_ELIMINATION_OFFSET): Likewise. + * reload1.c: Provide default for PREFERRED_STACK_BOUNDARY. + Mon Mar 22 18:06:59 1999 Jim Wilson * mips/mips.h (TARGET_SWITCHES, TARGET_OPTIONS): Add option doc diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 4d279b892a5..a989cac66ec 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2077,6 +2077,62 @@ load_pic_register (do_rtl) emit_insn (gen_blockage ()); } +/* Compute the size of local storage taking into consideration the + desired stack alignment which is to be maintained. Also determine + the number of registers saved below the local storage. */ + +HOST_WIDE_INT +ix86_compute_frame_size (size, nregs_on_stack) + HOST_WIDE_INT size; + int *nregs_on_stack; +{ + int limit; + int nregs; + int regno; + int padding; + int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table + || current_function_uses_const_pool); + HOST_WIDE_INT total_size; + + limit = frame_pointer_needed + ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM; + + nregs = 0; + + for (regno = limit - 1; regno >= 0; regno--) + if ((regs_ever_live[regno] && ! call_used_regs[regno]) + || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) + nregs++; + + padding = 0; + total_size = size + (nregs * UNITS_PER_WORD); + +#ifdef PREFERRED_STACK_BOUNDARY + { + int offset; + int preferred_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; + + offset = 4; + if (frame_pointer_needed) + offset += UNITS_PER_WORD; + + total_size += offset; + + padding = ((total_size + preferred_alignment - 1) + & -preferred_alignment) - total_size; + + if (padding < (((offset + preferred_alignment - 1) + & -preferred_alignment) - offset)) + padding += preferred_alignment; + } +#endif + + if (nregs_on_stack) + *nregs_on_stack = nregs; + + return size + padding; +} + static void ix86_prologue (do_rtl) int do_rtl; @@ -2086,7 +2142,7 @@ ix86_prologue (do_rtl) rtx xops[4]; int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table || current_function_uses_const_pool); - long tsize = get_frame_size (); + HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), (int *)0); rtx insn; int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset; @@ -2299,28 +2355,18 @@ ix86_epilogue (do_rtl) int do_rtl; { register int regno; - register int nregs, limit; - int offset; + register int limit; + int nregs; rtx xops[3]; int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table || current_function_uses_const_pool); int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging; - long tsize = get_frame_size (); - - /* Compute the number of registers to pop */ - - limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); - - nregs = 0; - - for (regno = limit - 1; regno >= 0; regno--) - if ((regs_ever_live[regno] && ! call_used_regs[regno]) - || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) - nregs++; + HOST_WIDE_INT offset; + HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), &nregs); /* sp is often unreliable so we may have to go off the frame pointer. */ - offset = - tsize - (nregs * UNITS_PER_WORD); + offset = -(tsize + nregs * UNITS_PER_WORD); xops[2] = stack_pointer_rtx; @@ -2340,6 +2386,9 @@ ix86_epilogue (do_rtl) less work than reloading sp and popping the register. Otherwise, restore sp (if necessary) and pop the registers. */ + limit = frame_pointer_needed + ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM; + if (nregs > 1 || sp_valid) { if ( !sp_valid ) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index e1456f9081c..417627f2afd 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -410,6 +410,10 @@ extern int ix86_arch; /* Boundary (in *bits*) on which stack pointer should be aligned. */ #define STACK_BOUNDARY 32 +/* We want to keep the stack aligned to 64bits when possible. But the + compiler can not rely on the stack having this alignment.*/ +#define PREFERRED_STACK_BOUNDARY 64 + /* Allocation boundary (in *bits*) for the code of a function. For i486, we get better performance by aligning to a cache line (i.e. 16 byte) boundary. */ @@ -1627,20 +1631,23 @@ do { \ (OFFSET) = 8; /* Skip saved PC and previous frame pointer */ \ else \ { \ - int regno; \ - int offset = 0; \ + int nregs; \ + int offset; \ + int preferred_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; \ + HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), \ + &nregs); \ \ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ - if ((regs_ever_live[regno] && ! call_used_regs[regno]) \ - || ((current_function_uses_pic_offset_table \ - || current_function_uses_const_pool) \ - && flag_pic && regno == PIC_OFFSET_TABLE_REGNUM)) \ - offset += 4; \ + (OFFSET) = (tsize + nregs * UNITS_PER_WORD); \ \ - (OFFSET) = offset + get_frame_size (); \ + offset = 4; \ + if (frame_pointer_needed) \ + offset += UNITS_PER_WORD; \ \ - if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) += 4; /* Skip saved PC */ \ + if ((FROM) == ARG_POINTER_REGNUM) \ + (OFFSET) += offset; \ + else \ + (OFFSET) -= ((offset + preferred_alignment - 1) \ + & -preferred_alignment) - offset; \ } \ } diff --git a/gcc/reload1.c b/gcc/reload1.c index 1295d322ee5..621594af607 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -39,6 +39,10 @@ Boston, MA 02111-1307, USA. */ #include "real.h" #include "toplev.h" +#if !defined PREFERRED_STACK_BOUNDARY && defined STACK_BOUNDARY +#define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY +#endif + /* This file contains the reload pass of the compiler, which is run after register allocation has been done. It checks that each insn is valid (operands required to be in registers really -- 2.30.2