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: restore sibcall optimization


On May 24, after updating my GCC tree from CVS, I noticed that the
sibling call optimization stopped working in my backend.  If stopped
working because the call to call_ends_block_p from
optimize_sibling_and_tail_recursive_calls no longer returned 1 for
tail calls.

The reason is that the called functions return value is no longer
copied directly to the callee's return value register.  Instead, it's
copied into another pseudo, and then copied from that pseudo into the
return value register.

This patch makes skip_copy_to_return_value recognize this new
situation.  It has been bootstrapped and checked without regressions
on powerpc-unknown-linux-gnu.

2001-06-01  Lars Brinkhoff  <lars@nocrew.org>

	* sibcall.c (skip_copy_to_return_value): recognize the situation
	when the called function's return value is copied into an
	intermediate pseudo, and then into the calling functions return
	value register.

Index: sibcall.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/sibcall.c,v
retrieving revision 1.15
diff -c -3 -p -r1.15 sibcall.c
*** sibcall.c	2001/03/28 06:53:49	1.15
--- sibcall.c	2001/06/01 07:37:47
*************** skip_copy_to_return_value (orig_insn)
*** 169,174 ****
--- 169,198 ----
        && SET_SRC (set) == softret)
      return insn;
  
+   /* Recognize the situation when the called function's return value
+      is copied in two steps: first into an intermediate pseudo, then
+      the into the calling functions return value register.  */
+ 
+   if (REG_P (SET_DEST (set))
+       && SET_SRC (set) == softret)
+     {
+       rtx x = SET_DEST (set);
+ 
+       insn = next_nonnote_insn (insn);
+       if (! insn)
+ 	return orig_insn;
+ 
+       set = single_set (insn);
+       if (! set)
+ 	return orig_insn;
+ 
+       if (SET_DEST (set) == current_function_return_rtx
+ 	  && REG_P (SET_DEST (set))
+ 	  && OUTGOING_REGNO (REGNO (SET_DEST (set))) == REGNO (hardret)
+ 	  && SET_SRC (set) == x)
+ 	return insn;
+     }
+ 
    /* It did not look like a copy of the return value, so return the
       same insn we were passed.  */
    return orig_insn;


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