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]
Other format: [Raw text]

Re: [patch] PR19616, take 2


On Tuesday 25 January 2005 22:58, Richard Henderson wrote:
> On Tue, Jan 25, 2005 at 10:11:50PM +0100, Steven Bosscher wrote:
> > A less pessimistic fix is to just disallow TER to propagate expressions
> > into the argument list of a call that may be a tail call.  That way, to
> > expand all the arguments will be GIMPLE registers, and the arguments
> > are always evaluated before setting up the arguments for the sibcall.
>
> Except that only works if all the arguments are registers.  Consider
>
> 	struct S { int w, x, y, z; };
> 	struct T { int r; struct S s; };
>
> 	void bar(struct S, int);
>
> 	void foo(int a, struct T b)
> 	{
> 	  struct S *c = 0;
> 	  if (a)
> 	    c = &b.s;
> 	  bar (*c, a);
> 	}

After some chatting, we decided that:
1) bar is not marked as a sibcall because of PR19633, which
   is about b being incorrectly marked as call-clobbered;
2) my patch would probably fail with arguments that overlap
   with themselves if bar would be a sibcall; and
3) whatever we do, it'd better be conservative.

So, new approach: Just do not allow sibcalls for functions with
one or more addressable function arguments, like below.  I'm
testing this patch now.

Gr.
Steven

Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.377
diff -u -3 -p -r1.377 calls.c
--- calls.c	18 Jan 2005 23:06:55 -0000	1.377
+++ calls.c	26 Jan 2005 00:11:18 -0000
@@ -1670,7 +1670,7 @@ check_sibcall_argument_overlap_1 (rtx x)
 	       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
 	i = INTVAL (XEXP (XEXP (x, 0), 1));
       else
-	return 1;
+	return 0;
 
 #ifdef ARGS_GROW_DOWNWARD
       i = -i - GET_MODE_SIZE (GET_MODE (x));
Index: tree-tailcall.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-tailcall.c,v
retrieving revision 2.34
diff -u -3 -p -r2.34 tree-tailcall.c
--- tree-tailcall.c	25 Nov 2004 22:31:09 -0000	2.34
+++ tree-tailcall.c	26 Jan 2005 00:11:19 -0000
@@ -159,6 +159,8 @@ suitable_for_tail_opt_p (void)
 static bool
 suitable_for_tail_call_opt_p (void)
 {
+  tree param;
+
   /* alloca (until we have stack slot life analysis) inhibits
      sibling call optimizations, but not tail recursion.  */
   if (current_function_calls_alloca)
@@ -176,6 +178,14 @@ suitable_for_tail_call_opt_p (void)
   if (current_function_calls_setjmp)
     return false;
 
+  /* ??? It is OK if the argument of a function is taken in some cases,
+     but not in all cases.  See PR15387 and PR19616.  Revisit for 4.1.  */
+  for (param = DECL_ARGUMENTS (current_function_decl);
+       param;
+       param = TREE_CHAIN (param))
+    if (TREE_ADDRESSABLE (param))
+      return false;
+
   return true;
 }
 
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.679
diff -u -3 -p -r1.679 tree.h
--- tree.h	16 Jan 2005 15:28:15 -0000	1.679
+++ tree.h	26 Jan 2005 00:11:19 -0000
@@ -824,6 +824,9 @@ extern void tree_operand_check_failed (i
    had its address taken.  That matters for inline functions.  */
 #define TREE_ADDRESSABLE(NODE) ((NODE)->common.addressable_flag)
 
+/* Set on a CALL_EXPR if the call is in a tail position, ie. just before the
+   exit of a function.  Calls for which this is true are candidates for tail
+   call optimizations.  */
 #define CALL_EXPR_TAILCALL(NODE) (CALL_EXPR_CHECK(NODE)->common.addressable_flag)
 
 /* In a VAR_DECL, nonzero means allocate static storage.


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