This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

I960 p elimination patch.



Hello.

When i960 gcc compiler uses g8-g11 in leaf procedure and eliminates
frame pointer, it generates incorrect displacements for stack
variables.  Also it is not good idea to eliminate frame pointer when
-O2 because negative displacement (when sp is used instead of fp)
requires one more word.

I've committed the following patch or solution the problem.

Fri Nov 12 15:14:19 1999  Vladimir Makarov  <vmakarov@tofu.to.cygnus.com>

	* i960.h (CAN_DEBUG_WITHOUT_FP): Don't define it.
	(FRAME_POINTER_REQUIRED): Don't worry about nonlocal goto.
	(ELIMINABLE_REGS, CAN_ELIMINATE, INITIAL_ELIMINATION_OFFSET): New.
	(INITIAL_FRAME_POINTER_OFFSET): Remove it.

	* i960.c (i960_function_prologue): Don't allocate space for g8-g11
 	saved on the stack.  Output more accurate stack frame statistics
	into assembler file.

Index: config/i960/i960.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i960/i960.c,v
retrieving revision 1.14
diff -c -p -r1.14 i960.c
*** i960.c	1999/10/28 17:14:59	1.14
--- i960.c	1999/11/12 20:20:38
*************** i960_function_prologue (file, size)
*** 1333,1340 ****
       unsigned int size;
  {
    register int i, j, nr;
!   int n_iregs = 0;
!   int rsize = 0;
    int actual_fsize, offset;
    int gnw, lnw;
    struct reg_group *g, *l;
--- 1333,1341 ----
       unsigned int size;
  {
    register int i, j, nr;
!   int n_saved_regs = 0;
!   int n_remaining_saved_regs;
!   int lvar_size;
    int actual_fsize, offset;
    int gnw, lnw;
    struct reg_group *g, *l;
*************** i960_function_prologue (file, size)
*** 1357,1367 ****
  	regs[i] = -1;
          /* Count global registers that need saving.  */
  	if (i < 16)
! 	  n_iregs++;
        }
      else
        regs[i] = 0;
  
    epilogue_string[0] = '\0';
  
    if (profile_flag || profile_block_flag)
--- 1358,1370 ----
  	regs[i] = -1;
          /* Count global registers that need saving.  */
  	if (i < 16)
! 	  n_saved_regs++;
        }
      else
        regs[i] = 0;
  
+   n_remaining_saved_regs = n_saved_regs;
+ 
    epilogue_string[0] = '\0';
  
    if (profile_flag || profile_block_flag)
*************** i960_function_prologue (file, size)
*** 1397,1403 ****
  		    (g->length == 2) ? "l" : ""),
  		   reg_names[l->start_reg], reg_names[g->start_reg]);
  	  strcat (epilogue_string, tmpstr);
! 	  n_iregs -= g->length;
  	  for (i = 0; i < g->length; i++)
  	    {
  	      regs [i + g->start_reg] = 1;
--- 1400,1406 ----
  		    (g->length == 2) ? "l" : ""),
  		   reg_names[l->start_reg], reg_names[g->start_reg]);
  	  strcat (epilogue_string, tmpstr);
! 	  n_remaining_saved_regs -= g->length;
  	  for (i = 0; i < g->length; i++)
  	    {
  	      regs [i + g->start_reg] = 1;
*************** i960_function_prologue (file, size)
*** 1414,1425 ****
        else
  	lnw = i960_split_reg_group (l, lnw, g->length);
      }
- 
-   /* N_iregs is now the number of global registers that haven't been saved
-      yet.  */
  
!   rsize = (n_iregs * 4);
!   actual_fsize = compute_frame_size (size) + rsize;
  #if 0
    /* ??? The 1.2.1 compiler does this also.  This is meant to round the frame
       size up to the nearest multiple of 16.  I don't know whether this is
--- 1417,1424 ----
        else
  	lnw = i960_split_reg_group (l, lnw, g->length);
      }
  
!   actual_fsize = compute_frame_size (size);
  #if 0
    /* ??? The 1.2.1 compiler does this also.  This is meant to round the frame
       size up to the nearest multiple of 16.  I don't know whether this is
*************** i960_function_prologue (file, size)
*** 1443,1453 ****
  
    /* Take hardware register save area created by the call instruction
       into account, but store them before the argument block area.  */
!   offset = 64 + actual_fsize - compute_frame_size (0) - rsize;
    /* Save registers on stack if needed.  */
    /* ??? Is it worth to use the same algorithm as one for saving
       global registers in local registers? */
!   for (i = 0, j = n_iregs; j > 0 && i < 16; i++)
      {
        if (regs[i] != -1)
  	continue;
--- 1442,1453 ----
  
    /* Take hardware register save area created by the call instruction
       into account, but store them before the argument block area.  */
!   lvar_size = actual_fsize - compute_frame_size (0) - n_saved_regs * 4;
!   offset = 64 + lvar_size;
    /* Save registers on stack if needed.  */
    /* ??? Is it worth to use the same algorithm as one for saving
       global registers in local registers? */
!   for (i = 0, j = n_remaining_saved_regs; j > 0 && i < 16; i++)
      {
        if (regs[i] != -1)
  	continue;
*************** i960_function_prologue (file, size)
*** 1480,1496 ****
        offset += nr * 4;
      }
  
!   if (actual_fsize == 0 && size == 0 && rsize == 0)
      return;
  
    fprintf (file, "\t#Prologue stats:\n");
    fprintf (file, "\t#  Total Frame Size: %d bytes\n", actual_fsize);
  
!   if (size)
!     fprintf (file, "\t#  Local Variable Size: %d bytes\n", size);
!   if (rsize)
      fprintf (file, "\t#  Register Save Size: %d regs, %d bytes\n",
! 	     n_iregs, rsize);
    fprintf (file, "\t#End Prologue#\n");
  }
  
--- 1480,1496 ----
        offset += nr * 4;
      }
  
!   if (actual_fsize == 0)
      return;
  
    fprintf (file, "\t#Prologue stats:\n");
    fprintf (file, "\t#  Total Frame Size: %d bytes\n", actual_fsize);
  
!   if (lvar_size)
!     fprintf (file, "\t#  Local Variable Size: %d bytes\n", lvar_size);
!   if (n_saved_regs)
      fprintf (file, "\t#  Register Save Size: %d regs, %d bytes\n",
! 	     n_saved_regs, n_saved_regs * 4);
    fprintf (file, "\t#End Prologue#\n");
  }
  
Index: config/i960/i960.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i960/i960.h,v
retrieving revision 1.28
retrieving revision 1.30
diff -c -p -r1.28 -r1.30
*** i960.h	1999/09/07 05:48:37	1.28
--- i960.h	1999/11/12 20:28:43	1.30
*************** Boston, MA 02111-1307, USA.  */
*** 94,101 ****
  #define LIB_SPEC "%{!nostdlib:-lcg %{p:-lprof}%{pg:-lgprof}\
  	  %{mka:-lfpg}%{msa:-lfpg}%{mca:-lfpg}%{mcf:-lfpg} -lgnu}"
  
! /* Show we can debug even without a frame pointer.  */
! #define CAN_DEBUG_WITHOUT_FP
  
  /* Do leaf procedure and tail call optimizations for -O2 and higher.  */
  #define OPTIMIZATION_OPTIONS(LEVEL,SIZE)	\
--- 94,106 ----
  #define LIB_SPEC "%{!nostdlib:-lcg %{p:-lprof}%{pg:-lgprof}\
  	  %{mka:-lfpg}%{msa:-lfpg}%{mca:-lfpg}%{mcf:-lfpg} -lgnu}"
  
! /* Defining the macro shows we can debug even without a frame pointer.
!    Actually, we can debug without FP.  But defining the macro results in
!    that -O means FP elimination.  Addressing through sp requires
!    negative offset and more one word addressing in the most cases
!    (offsets except for 0-4095 require one more word).  Therefore we've
!    not defined the macro. */
! /*#define CAN_DEBUG_WITHOUT_FP*/
  
  /* Do leaf procedure and tail call optimizations for -O2 and higher.  */
  #define OPTIMIZATION_OPTIONS(LEVEL,SIZE)	\
*************** extern int hard_regno_mode_ok ();
*** 607,628 ****
  /* ??? It isn't clear to me why this is here.  Perhaps because of a bug (since
     fixed) in the definition of INITIAL_FRAME_POINTER_OFFSET which would have
     caused this to fail.  */
! /* ??? Must check current_function_has_nonlocal_goto, otherwise frame pointer
!    elimination messes up nonlocal goto sequences.  I think this works for other
!    targets because they use indirect jumps for the return which disables fp
!    elimination.  */
! #define FRAME_POINTER_REQUIRED \
!   (! leaf_function_p () || current_function_has_nonlocal_goto)
  
! /* C statement to store the difference between the frame pointer
!    and the stack pointer values immediately after the function prologue.
  
     Since the stack grows upward on the i960, this must be a negative number.
     This includes the 64 byte hardware register save area and the size of
     the frame.  */
  
! #define INITIAL_FRAME_POINTER_OFFSET(VAR) \
!   do { (VAR) = - (64 + compute_frame_size (get_frame_size ())); } while (0)
  
  /* Base register for access to arguments of the function.  */
  #define ARG_POINTER_REGNUM 14
--- 612,641 ----
  /* ??? It isn't clear to me why this is here.  Perhaps because of a bug (since
     fixed) in the definition of INITIAL_FRAME_POINTER_OFFSET which would have
     caused this to fail.  */
! #define FRAME_POINTER_REQUIRED (! leaf_function_p ())
  
! /* Definitions for register eliminations.
  
+    This is an array of structures.  Each structure initializes one pair
+    of eliminable registers.  The "from" register number is given first,
+    followed by "to".  Eliminations of the same "from" register are listed
+    in order of preference.. */
+ 
+ #define ELIMINABLE_REGS	 {{FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
+ 
+ /* Given FROM and TO register numbers, say whether this elimination is allowed.
+    Frame pointer elimination is automatically handled.  */
+ #define CAN_ELIMINATE(FROM, TO) 1
+ 
+ /* Define the offset between two registers, one to be eliminated, and
+    the other its replacement, at the start of a routine.
+ 
     Since the stack grows upward on the i960, this must be a negative number.
     This includes the 64 byte hardware register save area and the size of
     the frame.  */
  
! #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)			\
!   do { (OFFSET) = - (64 + compute_frame_size (get_frame_size ())); } while (0)
  
  /* Base register for access to arguments of the function.  */
  #define ARG_POINTER_REGNUM 14


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]