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]

Patch to mark return values in mark_regs_live_at_end instead of using USE insns



Hi
This is patch to change mark_regs_live_at_end to mark return values of
functions.  The resulting flowgraph is now closer to what actually happends
and it fixes possible problems with find_free_register and friends
clobbering return register in epilogue code and also fixes (I hope) last
important kludge in my reg-stack flow rewrite that prevents it from
applying...

I've changed the return code expanders to not expand uses when return
value is live and to expand clobbers when function declared to return
something don't return it.  This is required to avoid register lifetimes
from bloat and regstack from complaining.
After reload this clobbers are removed, so lifetimes are enlarged, but this
happends only in at least partially bad code and hurts only find_free_register.
On the other hand this change seems to result in better dead code eliminations
because some branches becomes useless. So overall the resulting code is slightly
better (about 0.5% of the compiler size)

Tue Aug 10 19:55:53 EDT 1999  Jan Hubicka  <hubicka@freesoft.cz>
	* builtins.c (expand_builtin_return): Do not emit USEs, call
	expand_nonnull_return instead of call_null_return.
	* flow.c: Include tree.h
	(mark_regs_live_at_end): Mark function return registers.
	* function.c (expand_function_end): Clobber return value
	(thread_prologue_and_epilogue_insns): Do not move the USE insns.
	* stmt.c (expand_null_return): Rename to expand_nonnull_return.
	(expand_null_return_1): Rename to expand_nonnull_return_1.
	(expand_null_return): New function to clobber return value.
	(expand_value_return): Do not emit USE insns.
	* rtl.h (expand_nonnull_return): Declare.
	* tree.h (expand_nonnull_return): Declare.

*** builtins.c.nore	Tue Aug 10 17:25:49 1999
--- builtins.c	Tue Aug 10 19:08:31 1999
*************** expand_builtin_return (result)
*** 1035,1041 ****
      }
  #endif
  
!   /* Restore the return value and note that each value is used.  */
    size = 0;
    for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
      if ((mode = apply_result_mode[regno]) != VOIDmode)
--- 1035,1041 ----
      }
  #endif
  
!   /* Restore the return value.  */
    size = 0;
    for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
      if ((mode = apply_result_mode[regno]) != VOIDmode)
*************** expand_builtin_return (result)
*** 1050,1067 ****
  						       size)));
  
  	push_to_sequence (call_fusage);
- 	emit_insn (gen_rtx_USE (VOIDmode, reg));
  	call_fusage = get_insns ();
  	end_sequence ();
  	size += GET_MODE_SIZE (mode);
        }
  
!   /* Put the USE insns before the return.  */
    emit_insns (call_fusage);
  
    /* Return whatever values was restored by jumping directly to the end
       of the function.  */
!   expand_null_return ();
  }
  
  /* Expand a call to __builtin_classify_type with arguments found in
--- 1050,1066 ----
  						       size)));
  
  	push_to_sequence (call_fusage);
  	call_fusage = get_insns ();
  	end_sequence ();
  	size += GET_MODE_SIZE (mode);
        }
  
!   /* Put the move insns before the return.  */
    emit_insns (call_fusage);
  
    /* Return whatever values was restored by jumping directly to the end
       of the function.  */
!   expand_nonnull_return ();
  }
  
  /* Expand a call to __builtin_classify_type with arguments found in
*** flow.c.nore	Tue Aug 10 18:01:45 1999
--- flow.c	Tue Aug 10 19:15:15 1999
*************** Boston, MA 02111-1307, USA.  */
*** 132,137 ****
--- 132,138 ----
  #include "recog.h"
  #include "insn-flags.h"
  #include "resource.h"
+ #include "tree.h"
  
  #include "obstack.h"
  #define obstack_chunk_alloc xmalloc
*************** mark_regs_live_at_end (set)
*** 2265,2270 ****
--- 2266,2272 ----
       regset set;
  {
    int i;
+   rtx result = DECL_RTL ( DECL_RESULT (current_function_decl));
    
    /* If exiting needs the right stack value, consider the stack pointer
       live at the end of the function.  */
*************** mark_regs_live_at_end (set)
*** 2301,2307 ****
  	)
        SET_REGNO_REG_SET (set, i);
  
!   /* ??? Mark function return value here rather than as uses.  */
  }
  
  /* Determine which registers are live at the start of each
--- 2303,2329 ----
  	)
        SET_REGNO_REG_SET (set, i);
  
!   /* Mark function return value here.  
!      ??? remove uses?  */
! 
!   if (result && GET_CODE (result) == REG)
!     {
!       SET_REGNO_REG_SET (set, REGNO (result));
!     }
!   /* Handle calls that return values in multiple non-contiguous locations.
!      The Irix 6 ABI has examples of this.  */
!   else if (result && GET_CODE (result) == PARALLEL)
!     {
!       int i;
! 
!       for (i = 0; i < XVECLEN (result, 0); i++)
!         {
!            rtx x = XEXP (XVECEXP (result, 0, i), 0);
! 
!            if (GET_CODE (x) == REG)
! 	     SET_REGNO_REG_SET (set, REGNO (x));
!         }
!       }
  }
  
  /* Determine which registers are live at the start of each
*** function.c.nore	Tue Aug 10 17:59:12 1999
--- function.c	Tue Aug 10 19:11:32 1999
*************** expand_function_end (filename, line, end
*** 6325,6330 ****
--- 6325,6331 ----
       int end_bindings;
  {
    register int i;
+   rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
    tree link;
  
  #ifdef TRAMPOLINE_TEMPLATE
*************** expand_function_end (filename, line, end
*** 6466,6471 ****
--- 6467,6495 ----
    clear_pending_stack_adjust ();
    do_pending_stack_adjust ();
  
+   /* Clobber return value to keep lifetimes consistent.  */
+   if (return_reg && GET_CODE (return_reg) == REG
+       && REGNO (return_reg) < FIRST_PSEUDO_REGISTER)
+     {
+       emit_insn (gen_rtx_CLOBBER (VOIDmode, return_reg));
+     }
+   /* Handle calls that return values in multiple non-contiguous locations.
+      The Irix 6 ABI has examples of this.  */
+   else if (return_reg && GET_CODE (return_reg) == PARALLEL)
+     {
+       int i;
+ 
+       for (i = 0; i < XVECLEN (return_reg, 0); i++)
+         {
+            rtx x = XEXP (XVECEXP (return_reg, 0, i), 0);
+ 
+            if (GET_CODE (x) == REG
+                && REGNO (x) < FIRST_PSEUDO_REGISTER)
+ 	     emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+         }
+      }
+ 
+ 
    /* Mark the end of the function body.
       If control reaches this insn, the function can drop through
       without returning a value.  */
*************** thread_prologue_and_epilogue_insns (f)
*** 6792,6843 ****
  	  /* FALLTHRU */
  	case 0:
  	  {
! 	    rtx prev, seq, first_use;
  
- 	    /* Move the USE insns at the end of a function onto a list.  */
  	    prev = tail;
  	    if (GET_CODE (prev) == BARRIER
  		|| GET_CODE (prev) == NOTE)
  	      prev = prev_nonnote_insn (prev);
  
- 	    first_use = 0;
- 	    if (prev
- 		&& GET_CODE (prev) == INSN
- 		&& GET_CODE (PATTERN (prev)) == USE)
- 	      {
- 		/* If the end of the block is the use, grab hold of something
- 		   else so that we emit barriers etc in the right place.  */
- 		if (prev == tail)
- 		  {
- 		    do 
- 		      tail = PREV_INSN (tail);
- 		    while (GET_CODE (tail) == INSN
- 			   && GET_CODE (PATTERN (tail)) == USE);
- 		  }
- 
- 		do
- 		  {
- 		    rtx use = prev;
- 		    prev = prev_nonnote_insn (prev);
- 
- 		    remove_insn (use);
- 		    if (first_use)
- 		      {
- 			NEXT_INSN (use) = first_use;
- 			PREV_INSN (first_use) = use;
- 		      }
- 		    else
- 		      NEXT_INSN (use) = NULL_RTX;
- 		    first_use = use;
- 		  }
- 		while (prev
- 		       && GET_CODE (prev) == INSN
- 		       && GET_CODE (PATTERN (prev)) == USE);
- 	      }
- 
  	    /* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, the
! 	       epilogue insns, the USE insns at the end of a function,
! 	       the jump insn that returns, and then a BARRIER.  */
  
  	    if (GET_CODE (tail) != BARRIER)
  	      {
--- 6816,6831 ----
  	  /* FALLTHRU */
  	case 0:
  	  {
! 	    rtx prev, seq;
  
  	    prev = tail;
  	    if (GET_CODE (prev) == BARRIER
  		|| GET_CODE (prev) == NOTE)
  	      prev = prev_nonnote_insn (prev);
  
  	    /* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, the
! 	       epilogue insns, the jump insn that returns, and then
! 	       a BARRIER.  */
  
  	    if (GET_CODE (tail) != BARRIER)
  	      {
*************** thread_prologue_and_epilogue_insns (f)
*** 6850,6859 ****
  	    prev = tail;
  	    tail = emit_jump_insn_after (seq, tail);
  
- 	    /* Insert the USE insns immediately before the return insn, which
- 	       must be the last instruction emitted in the sequence.  */
- 	    if (first_use)
- 	      emit_insns_before (first_use, tail);
  	    emit_note_after (NOTE_INSN_EPILOGUE_BEG, prev);
  
  	    /* Update the tail of the basic block.  */
--- 6838,6843 ----
*** rtl.h.nore	Tue Aug 10 17:22:32 1999
--- rtl.h	Tue Aug 10 17:23:11 1999
*************** extern int safe_from_earlyclobber	PROTO 
*** 1474,1479 ****
--- 1474,1480 ----
  
  /* In stmt.c */
  extern void expand_null_return		PROTO((void));
+ extern void expand_nonnull_return	PROTO((void));
  extern void emit_jump			PROTO ((rtx));
  extern int preserve_subexpressions_p	PROTO ((void));
  
*** stmt.c.nore	Tue Aug 10 17:14:34 1999
--- stmt.c	Tue Aug 10 19:11:14 1999
*************** static void expand_nl_goto_receiver	PROT
*** 394,400 ****
  static void expand_nl_goto_receivers	PROTO((struct nesting *));
  static void fixup_gotos			PROTO((struct nesting *, rtx, tree,
  					       rtx, int));
! static void expand_null_return_1	PROTO((rtx, int));
  static void expand_value_return		PROTO((rtx));
  static int tail_recursion_args		PROTO((tree, tree));
  static void expand_cleanups		PROTO((tree, tree, int, int));
--- 394,400 ----
  static void expand_nl_goto_receivers	PROTO((struct nesting *));
  static void fixup_gotos			PROTO((struct nesting *, rtx, tree,
  					       rtx, int));
! static void expand_nonnull_return_1	PROTO((rtx, int));
  static void expand_value_return		PROTO((rtx));
  static int tail_recursion_args		PROTO((tree, tree));
  static void expand_cleanups		PROTO((tree, tree, int, int));
*************** expand_exit_something ()
*** 2474,2484 ****
    return 0;
  }
  
! /* Generate RTL to return from the current function, with no value.
!    (That is, we do not do anything about returning any value.)  */
  
  void
! expand_null_return ()
  {
    struct nesting *block = block_stack;
    rtx last_insn = 0;
--- 2474,2484 ----
    return 0;
  }
  
! /* Generate RTL to return from the current function.
!    (we do not do anything about returning value.)  */
  
  void
! expand_nonnull_return ()
  {
    struct nesting *block = block_stack;
    rtx last_insn = 0;
*************** expand_null_return ()
*** 2490,2496 ****
  
    /* If yes, use a goto to return, since that runs cleanups.  */
  
!   expand_null_return_1 (last_insn, block != 0);
  }
  
  /* Generate RTL to return from the current function, with value VAL.  */
--- 2490,2527 ----
  
    /* If yes, use a goto to return, since that runs cleanups.  */
  
!   expand_nonnull_return_1 (last_insn, block != 0);
! }
! 
! /* Generate RTL to return from the current function, with no value.
!    (That is, we do clobber the return value to keep lifetimes consistent.)  */
! 
! void
! expand_null_return ()
! {
!   rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
! 
!   if (return_reg && GET_CODE (return_reg) == REG
!       && REGNO (return_reg) < FIRST_PSEUDO_REGISTER)
!   {
!     emit_insn (gen_rtx_CLOBBER (VOIDmode, return_reg));
!   }
!   /* Handle calls that return values in multiple non-contiguous locations.
!      The Irix 6 ABI has examples of this.  */
!   else if (return_reg && GET_CODE (return_reg) == PARALLEL)
!     {
!       int i;
! 
!       for (i = 0; i < XVECLEN (return_reg, 0); i++)
! 	{
! 	  rtx x = XEXP (XVECEXP (return_reg, 0, i), 0);
! 
! 	  if (GET_CODE (x) == REG
! 	      && REGNO (x) < FIRST_PSEUDO_REGISTER)
! 	    emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
! 	}
!     }
!   expand_nonnull_return ();
  }
  
  /* Generate RTL to return from the current function, with value VAL.  */
*************** expand_value_return (val)
*** 2521,2544 ****
  #endif
  	emit_move_insn (return_reg, val);
      }
-   if (GET_CODE (return_reg) == REG
-       && REGNO (return_reg) < FIRST_PSEUDO_REGISTER)
-     emit_insn (gen_rtx_USE (VOIDmode, return_reg));
-   /* Handle calls that return values in multiple non-contiguous locations.
-      The Irix 6 ABI has examples of this.  */
-   else if (GET_CODE (return_reg) == PARALLEL)
-     {
-       int i;
- 
-       for (i = 0; i < XVECLEN (return_reg, 0); i++)
- 	{
- 	  rtx x = XEXP (XVECEXP (return_reg, 0, i), 0);
- 
- 	  if (GET_CODE (x) == REG
- 	      && REGNO (x) < FIRST_PSEUDO_REGISTER)
- 	    emit_insn (gen_rtx_USE (VOIDmode, x));
- 	}
-     }
  
    /* Does any pending block have cleanups?  */
  
--- 2552,2557 ----
*************** expand_value_return (val)
*** 2548,2554 ****
    /* If yes, use a goto to return, since that runs cleanups.
       Use LAST_INSN to put cleanups *before* the move insn emitted above.  */
  
!   expand_null_return_1 (last_insn, block != 0);
  }
  
  /* Output a return with no value.  If LAST_INSN is nonzero,
--- 2561,2567 ----
    /* If yes, use a goto to return, since that runs cleanups.
       Use LAST_INSN to put cleanups *before* the move insn emitted above.  */
  
!   expand_nonnull_return_1 (last_insn, block != 0);
  }
  
  /* Output a return with no value.  If LAST_INSN is nonzero,
*************** expand_value_return (val)
*** 2558,2564 ****
     of pending blocks to be executed normally.  */
  
  static void
! expand_null_return_1 (last_insn, use_goto)
       rtx last_insn;
       int use_goto;
  {
--- 2571,2577 ----
     of pending blocks to be executed normally.  */
  
  static void
! expand_nonnull_return_1 (last_insn, use_goto)
       rtx last_insn;
       int use_goto;
  {
*** tree.h.nore	Tue Aug 10 17:22:54 1999
--- tree.h	Tue Aug 10 17:23:30 1999
*************** extern int expand_exit_loop_if_false		PR
*** 1954,1959 ****
--- 1954,1960 ----
  extern int expand_exit_something		PROTO((void));
  
  extern void expand_null_return			PROTO((void));
+ extern void expand_nonnull_return		PROTO((void));
  extern void expand_return			PROTO((tree));
  extern int optimize_tail_recursion		PROTO((tree, struct rtx_def *));
  extern void expand_start_bindings		PROTO((int));


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