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 for noreturn/sibcall lossage


The sibcall optimizer confuses some of the warning-generation code in
the C front end: it doesn't get the 'noreturn function does return'
and related warnings right all the time.  This patch attempts to fix
that.

The problem is that a function that ends with a sibcall will not be
considered to have reached its end.  Therefore, if there are no other
exits from the function, the C front end will think it never returns.
My patch fixes this by having optimize_sibling_and_tail_recursive_calls
set a flag indicating that the function does sibcalls, which the front
end can pick up on.  The flag might get set more often than it should;
I can't figure out how to tell the difference between recursion and
jumping to another function.

This fixes the gcc.dg/noreturn-1 failures.  It may break
c-torture/special/eeprof-1; I am not sure whether that's actually
something unrelated, or what.  If it is this patch, the culprit is
probably the tweak to c-decl.c to remember noreturn functions that
don't have an __attribute__ - I couldn't tell you why that's a
problem, though.

Other front end probably need to be adjusted to take advantage of
the new information.

zw

	* flags.h (has_sibcall): New variable.
	* rtl.h (NORETURN_CALL_PLACEHOLDER_P): New macro.
	* sibcall.c: Define has_sibcall.
	(optimize_sibling_and_tail_recursive_calls): If the function makes
	at least one sibcall that will return to our caller, set
	has_sibcall; otherwise, clear it.  Use NORETURN_CALL_PLACEHOLDER_P
	to detect sibcalls that don't return.
	* calls.c (expand_call): Set NORETURN_CALL_PLACEHOLDER_P on call
	placeholders.

	* c-decl.c (finish_function): Check has_sibcall and set
	current_function_returns_null or current_function_returns_value as
	appropriate.  If a function doesn't return and is declared to return
	void, mark it as noreturn for future reference.

===================================================================
Index: c-decl.c
--- c-decl.c	2000/03/27 01:26:16	1.105
+++ c-decl.c	2000/04/04 06:46:26
@@ -6504,16 +6504,30 @@ finish_function (nested)
 
   current_function_returns_null |= can_reach_end;
 
-  if (warn_missing_noreturn
-      && !TREE_THIS_VOLATILE (fndecl)
-      && !current_function_returns_null
-      && !current_function_returns_value)
-    warning ("function might be possible candidate for attribute `noreturn'");
+  /* If the current function makes a sibcall, that means it returns
+     what it's supposed to return - either null or value.  */
+  if (has_sibcall)
+    {
+      if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) == void_type_node)
+	current_function_returns_null = 1;
+      else
+	current_function_returns_value = 1;
+    }
 
+  if (!current_function_returns_null && !current_function_returns_value)
+    {
+      if (warn_missing_noreturn && !TREE_THIS_VOLATILE (fndecl))
+	warning ("function might be a candidate for attribute `noreturn'");
+      /* If it's safe, mark the function noreturn now.  */
+      if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) == void_type_node)
+	TREE_THIS_VOLATILE (fndecl) = 1;
+    }
+
   if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
     warning ("`noreturn' function does return");
   else if (warn_return_type && can_reach_end
-	   && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != void_type_node)
+	   && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
+	       != void_type_node))
     /* If this function returns non-void and control can drop through,
        complain.  */
     warning ("control reaches end of non-void function");
===================================================================
Index: calls.c
--- calls.c	2000/04/01 00:09:21	1.112
+++ calls.c	2000/04/04 06:46:27
@@ -3075,6 +3073,7 @@ expand_call (exp, target, ignore)
      One of them will be selected later.  */
   if (tail_recursion_insns || tail_call_insns)
     {
+      rtx callplace;
       /* The tail recursion label must be kept around.  We could expose
 	 its use in the CALL_PLACEHOLDER, but that creates unwanted edges
 	 and makes determining true tail recursion sites difficult.
@@ -3083,10 +3082,12 @@ expand_call (exp, target, ignore)
 	 one of the call sequences after rtl generation is complete.  */
       if (tail_recursion_insns)
 	LABEL_PRESERVE_P (tail_recursion_label) = 1;
-      emit_call_insn (gen_rtx_CALL_PLACEHOLDER (VOIDmode, normal_call_insns,
-						tail_call_insns,
-						tail_recursion_insns,
-						tail_recursion_label));
+      callplace = gen_rtx_CALL_PLACEHOLDER (VOIDmode, normal_call_insns,
+					    tail_call_insns,
+					    tail_recursion_insns,
+					    tail_recursion_label);
+      NORETURN_CALL_PLACEHOLDER_P (callplace) = is_volatile;
+      emit_call_insn (callplace);
     }
   else
     emit_insns (normal_call_insns);
===================================================================
Index: flags.h
--- flags.h	2000/03/29 09:54:30	1.41
+++ flags.h	2000/04/04 06:46:27
@@ -522,6 +522,12 @@ extern int frame_pointer_needed;
 
 extern int can_reach_end;
 
+/* Set nonzero if optimize_sibling_and_tail_recursive_calls finds that
+   this function makes a sibling call which returns (to this function's
+   caller).  Unlike can_reach_end, the front end need not clear this.  */
+
+extern int has_sibcall;
+
 /* Nonzero if GCC must add code to check memory access (used by Checker).  */
 
 extern int flag_check_memory_usage;
===================================================================
Index: rtl.h
--- rtl.h	2000/03/31 16:24:30	1.183
+++ rtl.h	2000/04/04 06:46:28
@@ -142,6 +142,7 @@ typedef struct rtx_def
      if it is deleted.
      1 in a REG expression if corresponds to a variable declared by the user.
      0 for an internally generated temporary.
+     In a CALL_PLACEHOLDER, 1 if the call does not return.
      In a SYMBOL_REF, this flag is used for machine-specific purposes.
      In a LABEL_REF or in a REG_LABEL note, this is LABEL_REF_NONLOCAL_P.  */
   unsigned int volatil : 1;
@@ -387,6 +388,9 @@ extern void rtvec_check_failed_bounds PA
 
 /* 1 if insn (assumed to be a CALL_INSN) is a sibling call.  */
 #define SIBLING_CALL_P(INSN) ((INSN)->jump)
+
+/* 1 if pattern is a noreturn CALL_PLACEHOLDER.  */
+#define NORETURN_CALL_PLACEHOLDER_P(PATTERN) ((PATTERN)->volatil)
 
 /* 1 if insn is a branch that should not unconditionally execute its
    delay slots, i.e., it is an annulled branch.   */
===================================================================
Index: sibcall.c
--- sibcall.c	2000/03/28 21:03:37	1.4
+++ sibcall.c	2000/04/04 06:46:28
@@ -364,6 +364,11 @@ replace_call_placeholder (insn, use)
   NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
 }
 
+/* optimize_sibling_and_tail_recursive_calls sets this flag if the
+   current function exits by making a sibcall.  */
+
+int has_sibcall;
+
 /* Given a (possibly empty) set of potential sibling or tail recursion call
    sites, determine if optimization is possible.
 
@@ -380,6 +385,7 @@ optimize_sibling_and_tail_recursive_call
   basic_block alternate_exit = EXIT_BLOCK_PTR;
   int current_function_uses_addressof;
   int successful_sibling_call = 0;
+  int sibcall_returns = 0;
   int replaced_call_placeholder = 0;
   edge e;
 
@@ -553,7 +559,11 @@ success:
 	     a tail/sibling call.  */
   
 	  if (sibcall)
-	    successful_sibling_call = 1;
+	    {
+	      successful_sibling_call = 1;
+	      if (! NORETURN_CALL_PLACEHOLDER_P (PATTERN (insn)))
+		sibcall_returns = 1;
+	    }
 	  replaced_call_placeholder = 1;
 	  replace_call_placeholder (insn, 
 				    tailrecursion != 0 
@@ -563,6 +573,8 @@ success:
 					 : sibcall_use_normal);
 	}
     }
+
+  has_sibcall = successful_sibling_call && sibcall_returns;
 
   /* A sibling call sequence invalidates any REG_EQUIV notes made for
      this function's incoming arguments. 

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