ia64 prologue/epilogue rewrite 1/N

Richard Henderson rth@cygnus.com
Tue Aug 8 01:33:00 GMT 2000


I'm going to try to break this up into as distinct many pieces as
possible, especially where generic code is concerned; last I checked
the whole thing was 350k.  Do note, however, that I havn't tested
each of these separately.

The following allows a target to tell flow that some registers do
not contain live data at function exit, despite being marked as
call-saved.  This might have been seen on Sparc and others, had
they emitted epilogues as rtl.

This doesn't actually affect code correctness, merely code quality.



r~


        * tm.texi (LOCAL_REGNO): Document.
        * flow.c (LOCAL_REGNO, EPILOGUE_USES): Provide default.
        (mark_regs_live_at_end): Don't mark LOCAL_REGNO registers.
        * reload1.c (reload): Likewise when considering nonlocal labels.

        * config/ia64/ia64.h (LOCAL_REGNO): New.
        * config/sparc/sparc.h (LOCAL_REGNO): New.

Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.319
diff -c -p -d -r1.319 flow.c
*** flow.c	2000/08/07 07:07:21	1.319
--- flow.c	2000/08/08 08:21:28
*************** Boston, MA 02111-1307, USA.  */
*** 163,168 ****
--- 163,175 ----
  #define HAVE_sibcall_epilogue 0
  #endif
  
+ #ifndef LOCAL_REGNO
+ #define LOCAL_REGNO(REGNO)  0
+ #endif
+ #ifndef EPILOGUE_USES
+ #define EPILOGUE_USES(REGNO)  0
+ #endif
+ 
  /* The contents of the current function definition are allocated
     in this obstack, and all are freed at the end of the function.
     For top-level functions, this is temporary_obstack.
*************** mark_regs_live_at_end (set)
*** 3051,3058 ****
      {
        SET_REGNO_REG_SET (set, FRAME_POINTER_REGNUM);
  #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
!       /* If they are different, also mark the hard frame pointer as live */
!       SET_REGNO_REG_SET (set, HARD_FRAME_POINTER_REGNUM);
  #endif      
      }
  
--- 3058,3066 ----
      {
        SET_REGNO_REG_SET (set, FRAME_POINTER_REGNUM);
  #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
!       /* If they are different, also mark the hard frame pointer as live.  */
!       if (! LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM))
!         SET_REGNO_REG_SET (set, HARD_FRAME_POINTER_REGNUM);
  #endif      
      }
  
*************** mark_regs_live_at_end (set)
*** 3070,3087 ****
       as being live at the end of the function since they may be
       referenced by our caller.  */
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
!     if (global_regs[i]
! #ifdef EPILOGUE_USES
! 	|| EPILOGUE_USES (i)
! #endif
! 	)
        SET_REGNO_REG_SET (set, i);
  
    /* Mark all call-saved registers that we actaully used.  */
    if (HAVE_epilogue && reload_completed)
      {
        for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! 	if (! call_used_regs[i] && regs_ever_live[i])
  	  SET_REGNO_REG_SET (set, i);
      }
  
--- 3078,3091 ----
       as being live at the end of the function since they may be
       referenced by our caller.  */
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
!     if (global_regs[i] || EPILOGUE_USES (i))
        SET_REGNO_REG_SET (set, i);
  
    /* Mark all call-saved registers that we actaully used.  */
    if (HAVE_epilogue && reload_completed)
      {
        for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! 	if (regs_ever_live[i] && ! call_used_regs[i] && ! LOCAL_REGNO (i))
  	  SET_REGNO_REG_SET (set, i);
      }
  
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.219
diff -c -p -d -r1.219 reload1.c
*** reload1.c	2000/08/04 20:28:05	1.219
--- reload1.c	2000/08/08 08:21:29
*************** Boston, MA 02111-1307, USA.  */
*** 85,90 ****
--- 85,94 ----
  #ifndef REGISTER_MOVE_COST
  #define REGISTER_MOVE_COST(x, y) 2
  #endif
+ 
+ #ifndef LOCAL_REGNO
+ #define LOCAL_REGNO(REGNO)  0
+ #endif
  
  /* During reload_as_needed, element N contains a REG rtx for the hard reg
     into which reg N has been reloaded (perhaps for a previous insn).  */
*************** reload (first, global, dumpfile)
*** 654,663 ****
       registers.  */
    if (current_function_has_nonlocal_label)
      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
!       {
! 	if (! call_used_regs[i] && ! fixed_regs[i])
! 	  regs_ever_live[i] = 1;
!       }
  
    /* Find all the pseudo registers that didn't get hard regs
       but do have known equivalent constants or memory slots.
--- 658,665 ----
       registers.  */
    if (current_function_has_nonlocal_label)
      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
!       if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
! 	regs_ever_live[i] = 1;
  
    /* Find all the pseudo registers that didn't get hard regs
       but do have known equivalent constants or memory slots.
Index: tm.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tm.texi,v
retrieving revision 1.137
diff -c -p -d -r1.137 tm.texi
*** tm.texi	2000/08/06 17:50:07	1.137
--- tm.texi	2000/08/08 08:21:30
*************** corresponding to the register number @va
*** 1489,1494 ****
--- 1489,1502 ----
  function.  Return @var{in} if register number @var{in} is not an inbound
  register.
  
+ @findex LOCAL_REGNO
+ @item LOCAL_REGNO (@var{regno})
+ Define this macro if the target machine has register windows.  This C
+ expression returns true if the register is call-saved but is in the
+ register window.  Unlike most call-saved registers, such registers
+ need not be explicitly restored on function exit or during non-local
+ gotos.
+ 
  @ignore
  @findex PC_REGNUM
  @item PC_REGNUM
Index: config/ia64/ia64.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.h,v
retrieving revision 1.31
diff -c -p -d -r1.31 ia64.h
*** ia64.h	2000/07/30 23:57:59	1.31
--- ia64.h	2000/08/08 08:21:31
*************** while (0)
*** 686,691 ****
--- 686,697 ----
  #define OUTGOING_REGNO(IN) \
    ((unsigned) ((IN) - IN_REG (0)) < 8 ? OUT_REG ((IN) - IN_REG (0)) : (IN))
  
+ /* Define this macro if the target machine has register windows.  This
+    C expression returns true if the register is call-saved but is in the
+    register window.  */
+ 
+ #define LOCAL_REGNO(REGNO) \
+   (IN_REGNO_P (REGNO) || LOC_REGNO_P (REGNO))
  
  /* Order of allocation of registers */
  
Index: config/sparc/sparc.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sparc/sparc.h,v
retrieving revision 1.115
diff -c -p -d -r1.115 sparc.h
*** sparc.h	2000/06/27 02:26:23	1.115
--- sparc.h	2000/08/08 08:21:33
*************** extern char leaf_reg_remap[];
*** 1711,1716 ****
--- 1711,1723 ----
  #define OUTGOING_REGNO(IN) \
   ((TARGET_FLAT || (IN) < 24 || (IN) > 31) ? (IN) : (IN) - 16)
  
+ /* Define this macro if the target machine has register windows.  This
+    C expression returns true if the register is call-saved but is in the
+    register window.  */
+ 
+ #define LOCAL_REGNO(REGNO) \
+   (TARGET_FLAT ? 0 : (REGNO) >= 16 && (REGNO) <= 31)
+ 
  /* Define how to find the value returned by a function.
     VALTYPE is the data type of the value (as a tree).
     If the precise function being called is known, FUNC is its FUNCTION_DECL;


More information about the Gcc-patches mailing list