PATCH for sibcalls on i386

Andreas Bauer baueran@in.tum.de
Tue Sep 24 22:24:00 GMT 2002


Dear all,

I have been following Richard's and Zack's insightful comments and points
of criticism and want to submit a new patch incorporating these new ideas.

Both patches are attached and the ChangeLog for these is in clear text
(as required from the page "Contributing to GCC").  The first entry for
"gcc.diff" reflects changes made inside the gcc/ directory:

ChangeLog:

2002-09-25  Andreas Bauer  <baueran@in.tum.de>

	* calls.c (expand_call): Removed the `no indirect check'
	for sibcall optimization, and replaced it by making use
	of the new target hook "function_ok_for_sibcall".
	* hooks.c: Added function hook_tree_tree_bool_false to
	disable all sibcall optimization on all targets by
	default, so that certain targets can later override this
	setting with their individual hooks.
	* hooks.h: Declared hook_tree_tree_bool_false.
	* target-def.h: Defined and added TARGET_FUNCTION_OK_FOR_SIBCALL
	to TARGET_INITIALIZER
	* target.h: Declared the function_ok_for_sibcall
	function.

The second entry for "config.diff" reflects all changes made inside the
config/ directory:

ChangeLog:

2002-09-25  Andreas Bauer  <baueran@in.tum.de>

	* alpha.c: Added static function alpha_function_ok_for_sibcall
	and according TARGET_FUNCTION_OK_FOR_SIBCALL definition.
	* alpha.h: Removed FUNCTION_OK_FOR_SIBCALL macro.
        * i386.c: Added static function ix86_function_ok_for_sibcall
        and according TARGET_FUNCTION_OK_FOR_SIBCALL definition. 
        * i386.h: Removed FUNCTION_OK_FOR_SIBCALL macro.
        * i386.c: Added static function ix86_function_ok_for_sibcall
        and according TARGET_FUNCTION_OK_FOR_SIBCALL definition. 
        * sparc.h: Removed FUNCTION_OK_FOR_SIBCALL macro.
        * sparc.c: Added static function sparc_function_ok_for_sibcall
        and according TARGET_FUNCTION_OK_FOR_SIBCALL definition. 
        * arm.h: Removed FUNCTION_OK_FOR_SIBCALL macro.
        * arm.c: Made function arm_function_ok_for_sibcall static and
	accept yet another parameter.
	* arm-protos.h: Removed definition for arm_function_ok_for_sibcall.
        * rs6000.c: Added static function rs6000_function_ok_for_sibcall
	and according TARGET_FUNCTION_OK_FOR_SIBCALL definition.
	* rs6000.h: Removed FUNCTION_OK_FOR_SIBCALL macro.
	* rs6000-protos.h: Removed definition for function_ok_for_sibcall.
        * pa.c: Added static function pa_function_ok_for_sibcall
        and according TARGET_FUNCTION_OK_FOR_SIBCALL definition. 
        * pa.h: Removed FUNCTION_OK_FOR_SIBCALL macro.
	* pa-linux.h: Removed FUNCTION_OK_FOR_SIBCALL macro and replaced
	it with by defining TARGET_FUNCTION_OK_FOR_SIBCALL to
	hook_tree_tree_bool_false.
        * sh.c: Added static function sh_function_ok_for_sibcall
        and according TARGET_FUNCTION_OK_FOR_SIBCALL definition. 
        * sh.h: Removed FUNCTION_OK_FOR_SIBCALL macro.
        * xtensia.c: Added static function xtensia_function_ok_for_sibcall
        and according TARGET_FUNCTION_OK_FOR_SIBCALL definition. 
        * xtensia.h: Removed FUNCTION_OK_FOR_SIBCALL macro.
        * frv.c: Added static function frv_function_ok_for_sibcall
        and according TARGET_FUNCTION_OK_FOR_SIBCALL definition. 
        * frv.h: Removed FUNCTION_OK_FOR_SIBCALL macro.

I would appreciate feedback on the two patches very much.  I hope, I got
everything complete and working this time.  There is, however, one issue
I am not 100% convinced I did right:  pa-linux.h used to redefine
FUNCTION_OK_FOR_SIBCALL to `false' and I simply redefined
TARGET_FUNCTION_OK_FOR_SIBCALL to hook_tree_tree_bool_false which also
resolves to `false'.  Was that ok?

Other than that, could someone point out how I should update the
documentation to reflect these rather substantial changes?  All comments
and ideas are highly appreciated.

Thank you in advance.

Cheers,
Andi.
-------------- next part --------------
Index: alpha/alpha.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.272.2.3
diff -u -p -r1.272.2.3 alpha.c
--- alpha/alpha.c	20 Sep 2002 01:29:08 -0000	1.272.2.3
+++ alpha/alpha.c	25 Sep 2002 03:59:03 -0000
@@ -118,6 +118,8 @@ int alpha_this_literal_sequence_number;
 int alpha_this_gpdisp_sequence_number;
 
 /* Declarations of static functions.  */
+static int alpha_function_ok_for_sibcall
+  PARAMS ((tree, tree));
 static int tls_symbolic_operand_1
   PARAMS ((rtx, enum machine_mode, int, int));
 static enum tls_model tls_symbolic_operand_type
@@ -292,6 +294,9 @@ static void unicosmk_unique_section PARA
 #undef  TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN alpha_expand_builtin
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL alpha_function_ok_for_sibcall
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Parse target option strings.  */
@@ -2267,6 +2272,22 @@ alpha_legitimize_address (x, scratch, mo
 
     return plus_constant (x, low);
   }
+}
+
+/* We do not allow indirect calls to be optimized into sibling calls, nor
+   can we allow a call to a function in a different compilation unit to
+   be optimized into a sibcall.  */
+static int
+alpha_function_ok_for_sibcall (decl, exp)
+     tree decl;
+     tree exp;
+{
+  if (decl
+      && (! TREE_PUBLIC (decl)
+	  || (TREE_ASM_WRITTEN (decl) && (*targetm.binds_local_p) (decl))))
+    return 1;
+  else
+    return 0;
 }
 
 /* For TARGET_EXPLICIT_RELOCS, we don't obfuscate a SYMBOL_REF to a
Index: alpha/alpha.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/alpha/alpha.h,v
retrieving revision 1.176.4.7
diff -u -p -r1.176.4.7 alpha.h
--- alpha/alpha.h	23 Sep 2002 04:38:44 -0000	1.176.4.7
+++ alpha/alpha.h	25 Sep 2002 03:59:12 -0000
@@ -1165,14 +1165,6 @@ extern int alpha_memory_latency;
     }									\
 }
 
-/* We do not allow indirect calls to be optimized into sibling calls, nor
-   can we allow a call to a function in a different compilation unit to
-   be optimized into a sibcall.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL)			\
-  (DECL							\
-   && (! TREE_PUBLIC (DECL)				\
-       || (TREE_ASM_WRITTEN (DECL) && (*targetm.binds_local_p) (DECL))))
-
 /* Try to output insns to set TARGET equal to the constant C if it can be
    done in less than N insns.  Do all computations in MODE.  Returns the place
    where the output has been placed if it can be done and the insns have been
Index: arm/arm-protos.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/arm/arm-protos.h,v
retrieving revision 1.29.8.2
diff -u -p -r1.29.8.2 arm-protos.h
--- arm/arm-protos.h	17 Sep 2002 22:58:53 -0000	1.29.8.2
+++ arm/arm-protos.h	25 Sep 2002 03:59:14 -0000
@@ -41,7 +41,6 @@ extern unsigned int  arm_compute_initial
 #ifdef TREE_CODE
 extern int    arm_return_in_memory	PARAMS ((tree));
 extern void   arm_encode_call_attribute	PARAMS ((tree, int));
-extern int    arm_function_ok_for_sibcall PARAMS ((tree));
 #endif
 #ifdef RTX_CODE
 extern int    arm_hard_regno_mode_ok	PARAMS ((unsigned int, enum machine_mode));
Index: arm/arm.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.223.2.5
diff -u -p -r1.223.2.5 arm.c
--- arm/arm.c	20 Sep 2002 01:29:09 -0000	1.223.2.5
+++ arm/arm.c	25 Sep 2002 03:59:48 -0000
@@ -117,6 +117,7 @@ static void	 arm_set_default_type_attrib
 static int	 arm_adjust_cost		PARAMS ((rtx, rtx, rtx, int));
 static int	 count_insns_for_constant	PARAMS ((HOST_WIDE_INT, int));
 static int	 arm_get_strip_length		PARAMS ((int));
+static int       arm_function_ok_for_sibcall    PARAMS ((tree, tree));
 #ifdef OBJECT_FORMAT_ELF
 static void	 arm_elf_asm_named_section	PARAMS ((const char *, unsigned int));
 #endif
@@ -192,6 +193,9 @@ static void	 arm_internal_label		PARAMS 
 #undef TARGET_ASM_INTERNAL_LABEL
 #define TARGET_ASM_INTERNAL_LABEL arm_internal_label
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Obstack for minipool constant handling.  */
@@ -2266,9 +2270,10 @@ arm_is_longcall_p (sym_ref, call_cookie,
 
 /* Return nonzero if it is ok to make a tail-call to DECL.  */
 
-int
-arm_function_ok_for_sibcall (decl)
+static int
+arm_function_ok_for_sibcall (decl, exp)
      tree decl;
+     tree exp;
 {
   int call_type = TARGET_LONG_CALLS ? CALL_LONG : CALL_NORMAL;
 
Index: arm/arm.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.155.4.5
diff -u -p -r1.155.4.5 arm.h
--- arm/arm.h	20 Sep 2002 01:29:10 -0000	1.155.4.5
+++ arm/arm.h	25 Sep 2002 04:00:00 -0000
@@ -1502,12 +1502,6 @@ typedef struct
 #define FUNCTION_ARG_REGNO_P(REGNO)	(IN_RANGE ((REGNO), 0, 3))
 
 
-/* Tail calling.  */
-
-/* A C expression that evaluates to true if it is ok to perform a sibling
-   call to DECL.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) arm_function_ok_for_sibcall ((DECL))
-
 /* Perform any actions needed for a function that is receiving a variable
    number of arguments.  CUM is as above.  MODE and TYPE are the mode and type
    of the current parameter.  PRETEND_SIZE is a variable that should be set to
Index: frv/frv.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/frv/frv.c,v
retrieving revision 1.2.10.3
diff -u -p -r1.2.10.3 frv.c
--- frv/frv.c	20 Sep 2002 01:29:12 -0000	1.2.10.3
+++ frv/frv.c	25 Sep 2002 04:00:30 -0000
@@ -279,6 +279,7 @@ static void frv_encode_section_info		PAR
 static void frv_init_builtins			PARAMS ((void));
 static rtx frv_expand_builtin			PARAMS ((tree, rtx, rtx, enum machine_mode, int));
 static bool frv_in_small_data_p			PARAMS ((tree));
+static int  frv_function_ok_for_sibcall         PARAMS ((tree, tree));
 
 /* Initialize the GCC target structure.  */
 #undef  TARGET_ASM_FUNCTION_PROLOGUE
@@ -297,6 +298,8 @@ static bool frv_in_small_data_p			PARAMS
 #define TARGET_EXPAND_BUILTIN frv_expand_builtin
 #undef TARGET_IN_SMALL_DATA_P
 #define TARGET_IN_SMALL_DATA_P frv_in_small_data_p
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL frv_function_ok_for_sibcall
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -9773,4 +9776,13 @@ frv_in_small_data_p (decl)
 
   return symbol_ref_small_data_p (XEXP (DECL_RTL (decl), 0))
     && size > 0 && size <= g_switch_value;
+}
+
+/* Return true if a function is ok to be called as a sibcall.  */
+static int
+frv_function_ok_for_sibcall (decl, exp)
+     tree decl;
+     tree exp;
+{
+  return 0;
 }
Index: frv/frv.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/frv/frv.h,v
retrieving revision 1.3.2.5
diff -u -p -r1.3.2.5 frv.h
--- frv/frv.h	20 Sep 2002 01:29:12 -0000	1.3.2.5
+++ frv/frv.h	25 Sep 2002 04:00:48 -0000
@@ -3539,9 +3539,6 @@ frv_ifcvt_modify_multiple_tests (CE_INFO
    scheduling.  */
 #define FIRST_CYCLE_MULTIPASS_SCHEDULING_LOOKAHEAD frv_sched_lookahead
 
-/* Return true if a function is ok to be called as a sibcall.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) 0
-
 enum frv_builtins
 {
   FRV_BUILTIN_MAND,
Index: i386/i386.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.447.2.3
diff -u -p -r1.447.2.3 i386.c
--- i386/i386.c	17 Sep 2002 22:58:57 -0000	1.447.2.3
+++ i386/i386.c	25 Sep 2002 04:01:35 -0000
@@ -742,6 +742,7 @@ static int ix86_save_reg PARAMS ((unsign
 static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
 static int ix86_comp_type_attributes PARAMS ((tree, tree));
 const struct attribute_spec ix86_attribute_table[];
+static int ix86_function_ok_for_sibcall PARAMS ((tree, tree));
 static tree ix86_handle_cdecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static tree ix86_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static int ix86_value_regno PARAMS ((enum machine_mode));
@@ -843,6 +844,9 @@ static enum x86_64_reg_class merge_class
 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
   ia32_multipass_dfa_lookahead
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL ix86_function_ok_for_sibcall
+
 #ifdef HAVE_AS_TLS
 #undef TARGET_HAVE_TLS
 #define TARGET_HAVE_TLS true
@@ -1286,6 +1290,41 @@ const struct attribute_spec ix86_attribu
 #endif
   { NULL,        0, 0, false, false, false, NULL }
 };
+
+/* If PIC, we cannot make sibling calls to global functions
+   because the PLT requires %ebx live.
+   If we are returning floats on the register stack, we cannot make
+   sibling calls to functions that return floats.  (The stack adjust
+   instruction will wind up after the sibcall jump, and not be executed.)  */
+
+static int
+ix86_function_ok_for_sibcall (decl, exp)
+     tree decl;
+     tree exp;
+{
+  /* If we are generating position-independent code, we cannot sibcall
+     optimize any indirect call, or a direct call to a global
+     function, as the PLT requires %ebx be live.  */
+  if (flag_pic && (!decl || !TREE_PUBLIC (decl)))
+    return 0;
+  
+  /* If we are returning floats on the 80387 register stack, we cannot
+     make a sibcall from a function that doesn't return a float to a
+     function that does; the necessary stack adjustment will not be
+     executed.  */
+  if (TARGET_FLOAT_RETURNS_IN_80387
+      && FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (exp)))
+      && !FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (cfun->decl)))))
+    return 0;
+  
+  /* TODO: Indirect sibcalls are not yet supported by the 64-bit call
+     patterns.  */
+  if (!decl && TARGET_64BIT)
+    return 0;
+  
+  /* Otherwise okay.  */
+  return 1;
+}
 
 /* Handle a "cdecl" or "stdcall" attribute;
    arguments as in struct attribute_spec.handler.  */
Index: i386/i386.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.280.4.5
diff -u -p -r1.280.4.5 i386.h
--- i386/i386.h	23 Sep 2002 04:38:45 -0000	1.280.4.5
+++ i386/i386.h	25 Sep 2002 04:01:49 -0000
@@ -1674,17 +1674,9 @@ typedef struct ix86_args {
 
 #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
 
-/* If PIC, we cannot make sibling calls to global functions
-   because the PLT requires %ebx live.
-   If we are returning floats on the register stack, we cannot make
-   sibling calls to functions that return floats.  (The stack adjust
-   instruction will wind up after the sibcall jump, and not be executed.) */
-#define FUNCTION_OK_FOR_SIBCALL(DECL)					\
-  ((DECL)								\
-   && (! flag_pic || ! TREE_PUBLIC (DECL))				\
-   && (! TARGET_FLOAT_RETURNS_IN_80387					\
-       || ! FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (DECL))))	\
-       || FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (cfun->decl))))))
+/* Checks whether the call can be sibcall optimized.  More information
+   can be found in i386.c  */
+/* #define FUNCTION_OK_FOR_SIBCALL(DECL, EXP) ix86_function_ok_for_sibcall ((DECL, EXP)) */
 
 /* Perform any needed actions needed for a function that is receiving a
    variable number of arguments.
Index: pa/pa-linux.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/pa/pa-linux.h,v
retrieving revision 1.24.2.1
diff -u -p -r1.24.2.1 pa-linux.h
--- pa/pa-linux.h	2 Sep 2002 02:54:02 -0000	1.24.2.1
+++ pa/pa-linux.h	25 Sep 2002 04:01:52 -0000
@@ -81,10 +81,6 @@ Boston, MA 02111-1307, USA.  */
       %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
       %{static:-static}}"
 
-/* Sibcalls, stubs, and elf sections don't play well.  */
-#undef FUNCTION_OK_FOR_SIBCALL
-#define FUNCTION_OK_FOR_SIBCALL(x) 0
-
 /* glibc's profiling functions don't need gcc to allocate counters.  */
 #define NO_PROFILE_COUNTERS 1
 
@@ -189,3 +185,7 @@ Boston, MA 02111-1307, USA.  */
 /* Linux always uses gas.  */
 #undef TARGET_GAS
 #define TARGET_GAS 1
+
+/* Sibcalls, stubs, and elf sections don't play well.  */
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL hook_tree_tree_bool_false
Index: pa/pa.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/pa/pa.c,v
retrieving revision 1.177.2.3
diff -u -p -r1.177.2.3 pa.c
--- pa/pa.c	17 Sep 2002 22:59:03 -0000	1.177.2.3
+++ pa/pa.c	25 Sep 2002 04:02:18 -0000
@@ -116,6 +116,7 @@ static void pa_select_section PARAMS ((t
      ATTRIBUTE_UNUSED;
 static void pa_encode_section_info PARAMS ((tree, int));
 static const char *pa_strip_name_encoding PARAMS ((const char *));
+static int pa_function_ok_for_sibcall PARAMS ((tree, tree));
 static void pa_globalize_label PARAMS ((FILE *, const char *))
      ATTRIBUTE_UNUSED;
 
@@ -194,6 +195,9 @@ static size_t n_deferred_plabels = 0;
 #undef TARGET_STRIP_NAME_ENCODING
 #define TARGET_STRIP_NAME_ENCODING pa_strip_name_encoding
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL pa_function_ok_for_sibcall
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 void
@@ -6631,6 +6635,43 @@ pa_asm_output_mi_thunk (file, thunk_fnde
       function_section (thunk_fndecl);
     }
   current_thunk_number++;
+}
+
+/* Only direct calls to static functions are allowed to be sibling (tail)
+   call optimized.
+
+   This restriction is necessary because some linker generated stubs will
+   store return pointers into rp' in some cases which might clobber a
+   live value already in rp'.
+
+   In a sibcall the current function and the target function share stack
+   space.  Thus if the path to the current function and the path to the
+   target function save a value in rp', they save the value into the
+   same stack slot, which has undesirable consequences.
+
+   Because of the deferred binding nature of shared libraries any function
+   with external scope could be in a different load module and thus require
+   rp' to be saved when calling that function.  So sibcall optimizations
+   can only be safe for static function.
+
+   Note that GCC never needs return value relocations, so we don't have to
+   worry about static calls with return value relocations (which require
+   saving rp').
+
+   It is safe to perform a sibcall optimization when the target function
+   will never return.  */
+static int
+pa_function_ok_for_sibcall (decl, exp)
+     tree decl;
+     tree exp;
+{
+  if (decl
+      && ! TARGET_PORTABLE_RUNTIME
+      && ! TARGET_64BIT
+      && ! TREE_PUBLIC (decl))
+    return 1;
+  else
+    return 0;
 }
 
 /* Returns 1 if the 6 operands specified in OPERANDS are suitable for
Index: pa/pa.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/pa/pa.h,v
retrieving revision 1.166.2.4
diff -u -p -r1.166.2.4 pa.h
--- pa/pa.h	17 Sep 2002 22:59:03 -0000	1.166.2.4
+++ pa/pa.h	25 Sep 2002 04:02:26 -0000
@@ -1831,35 +1831,6 @@ do { 									\
 /* The number of Pmode words for the setjmp buffer.  */
 #define JMP_BUF_SIZE 50
 
-/* Only direct calls to static functions are allowed to be sibling (tail)
-   call optimized.
-
-   This restriction is necessary because some linker generated stubs will
-   store return pointers into rp' in some cases which might clobber a
-   live value already in rp'.
-
-   In a sibcall the current function and the target function share stack
-   space.  Thus if the path to the current function and the path to the
-   target function save a value in rp', they save the value into the
-   same stack slot, which has undesirable consequences.
-
-   Because of the deferred binding nature of shared libraries any function
-   with external scope could be in a different load module and thus require
-   rp' to be saved when calling that function.  So sibcall optimizations
-   can only be safe for static function.
-
-   Note that GCC never needs return value relocations, so we don't have to
-   worry about static calls with return value relocations (which require
-   saving rp').
-
-   It is safe to perform a sibcall optimization when the target function
-   will never return.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) \
-  (DECL \
-   && ! TARGET_PORTABLE_RUNTIME \
-   && ! TARGET_64BIT \
-   && ! TREE_PUBLIC (DECL))
-
 #define PREDICATE_CODES							\
   {"reg_or_0_operand", {SUBREG, REG, CONST_INT}},			\
   {"call_operand_address", {LABEL_REF, SYMBOL_REF, CONST_INT,		\
Index: rs6000/rs6000-protos.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.43.4.1
diff -u -p -r1.43.4.1 rs6000-protos.h
--- rs6000/rs6000-protos.h	17 Sep 2002 22:59:05 -0000	1.43.4.1
+++ rs6000/rs6000-protos.h	25 Sep 2002 04:02:28 -0000
@@ -151,7 +151,6 @@ extern void setup_incoming_varargs PARAM
 					    int *, int));
 extern struct rtx_def *rs6000_va_arg PARAMS ((tree, tree));
 extern void output_mi_thunk PARAMS ((FILE *, tree, int, tree));
-extern int function_ok_for_sibcall PARAMS ((tree));
 #ifdef ARGS_SIZE_RTX
 /* expr.h defines ARGS_SIZE_RTX and `enum direction' */
 extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree));
Index: rs6000/rs6000.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.366.2.5
diff -u -p -r1.366.2.5 rs6000.c
--- rs6000/rs6000.c	20 Sep 2002 01:29:19 -0000	1.366.2.5
+++ rs6000/rs6000.c	25 Sep 2002 04:03:13 -0000
@@ -165,6 +165,7 @@ struct builtin_description
   const enum rs6000_builtins code;
 };
 
+static int rs6000_function_ok_for_sibcall PARAMS ((tree, tree));
 static void rs6000_add_gc_roots PARAMS ((void));
 static int num_insns_constant_wide PARAMS ((HOST_WIDE_INT));
 static void validate_condition_mode 
@@ -376,6 +377,9 @@ static const char alt_reg_names[][8] =
 /* The VRSAVE bitmask puts bit %v0 as the most significant bit.  */
 #define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL rs6000_function_ok_for_sibcall
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Override command line options.  Mostly we process the processor
@@ -9403,9 +9407,10 @@ rs6000_return_addr (count, frame)
    vector parameters are required to have a prototype, so the argument
    type info must be available here.  (The tail recursion case can work
    with vector parameters, but there's no way to distinguish here.) */
-int
-function_ok_for_sibcall (fndecl)
+static int
+rs6000_function_ok_for_sibcall (fndecl, exp)
     tree fndecl;
+    tree exp;
 {
   tree type;
   if (fndecl)
Index: rs6000/rs6000.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.224.4.6
diff -u -p -r1.224.4.6 rs6000.h
--- rs6000/rs6000.h	23 Sep 2002 04:38:47 -0000	1.224.4.6
+++ rs6000/rs6000.h	25 Sep 2002 04:03:27 -0000
@@ -1804,10 +1804,6 @@ typedef struct rs6000_args
    argument is passed depends on whether or not it is a named argument.  */
 #define STRICT_ARGUMENT_NAMING 1
 
-/* We do not allow indirect calls to be optimized into sibling calls, nor
-   do we allow calls with vector parameters.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) function_ok_for_sibcall ((DECL))
-
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
 
Index: sh/sh.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.169.4.4
diff -u -p -r1.169.4.4 sh.c
--- sh/sh.c	20 Sep 2002 01:29:21 -0000	1.169.4.4
+++ sh/sh.c	25 Sep 2002 04:03:51 -0000
@@ -199,6 +199,7 @@ static void sh_insert_attributes PARAMS 
 static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
 static int sh_use_dfa_interface PARAMS ((void));
 static int sh_issue_rate PARAMS ((void));
+static int sh_function_ok_for_sibcall PARAMS ((tree, tree));
 
 static bool sh_cannot_modify_jumps_p PARAMS ((void));
 static bool sh_ms_bitfield_layout_p PARAMS ((tree));
@@ -259,6 +260,9 @@ static void flow_dependent_p_1 PARAMS ((
 #undef TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN sh_expand_builtin
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL sh_function_ok_for_sibcall
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Print the operand address in x to the stream.  */
@@ -7383,6 +7387,20 @@ sh_initialize_trampoline (tramp, fnaddr,
     }
 }
 
+/* FIXME: This is overly conservative.  A SHcompact function that
+   receives arguments ``by reference'' will have them stored in its
+   own stack frame, so it must not pass pointers or references to
+   these arguments to other functions by means of sibling calls.  */
+static int
+sh_function_ok_for_sibcall (decl, exp)
+     tree decl;
+     tree exp;
+{
+  if (! TARGET_SHCOMPACT || current_function_args_info.stack_regs == 0)
+    return 1;
+  else
+    return 0;
+}
 
 /* Machine specific built-in functions.  */
 
Index: sh/sh.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.166.4.6
diff -u -p -r1.166.4.6 sh.h
--- sh/sh.h	23 Sep 2002 04:38:48 -0000	1.166.4.6
+++ sh/sh.h	25 Sep 2002 04:04:05 -0000
@@ -1706,13 +1706,6 @@ struct sh_args {
     (CUM).outgoing = 0;						\
   } while (0)
  
-/* FIXME: This is overly conservative.  A SHcompact function that
-   receives arguments ``by reference'' will have them stored in its
-   own stack frame, so it must not pass pointers or references to
-   these arguments to other functions by means of sibling calls.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) \
-  (! TARGET_SHCOMPACT || current_function_args_info.stack_regs == 0)
-
 /* Update the data in CUM to advance over an argument
    of mode MODE and data type TYPE.
    (TYPE is null for libcalls where that information may not be
Index: sparc/sparc.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.226.4.4
diff -u -p -r1.226.4.4 sparc.c
--- sparc/sparc.c	20 Sep 2002 01:29:21 -0000	1.226.4.4
+++ sparc/sparc.c	25 Sep 2002 04:04:47 -0000
@@ -176,6 +176,8 @@ static void emit_soft_tfmode_cvt PARAMS 
 static void emit_hard_tfmode_operation PARAMS ((enum rtx_code, rtx *));
 
 static void sparc_encode_section_info PARAMS ((tree, int));
+
+static int sparc_function_ok_for_sibcall PARAMS ((tree, tree));
 
 /* Option handling.  */
 
@@ -239,6 +241,9 @@ enum processor_type sparc_cpu;
 #undef TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO sparc_encode_section_info
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL sparc_function_ok_for_sibcall
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Validate and override various options, and do some machine dependent
@@ -8021,6 +8026,35 @@ sparc_elf_asm_named_section (name, flags
   fputc ('\n', asm_out_file);
 }
 #endif /* OBJECT_FORMAT_ELF */
+
+/* We do not allow sibling calls if -mflat, nor
+   we do not allow indirect calls to be optimized into sibling calls.
+   
+   Also, on sparc 32-bit we cannot emit a sibling call when the
+   current function returns a structure.  This is because the "unimp
+   after call" convention would cause the callee to return to the
+   wrong place.  The generic code already disallows cases where the
+   function being called returns a structure.
+
+   It may seem strange how this last case could occur.  Usually there
+   is code after the call which jumps to epilogue code which dumps the
+   return value into the struct return area.  That ought to invalidate
+   the sibling call right?  Well, in the c++ case we can end up passing
+   the pointer to the struct return area to a constructor (which returns
+   void) and then nothing else happens.  Such a sibling call would look
+   valid without the added check here.  */
+static int
+sparc_function_ok_for_sibcall (decl, exp)
+     tree decl;
+     tree exp;
+{
+  if (decl
+      && ! TARGET_FLAT
+      && (TARGET_ARCH64 || ! current_function_returns_struct))
+    return 1;
+  else
+    return 0;
+}
 
 /* ??? Similar to the standard section selection, but force reloc-y-ness
    if SUNOS4_SHARED_LIBRARIES.  Unclear why this helps (as opposed to
Index: sparc/sparc.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/sparc/sparc.h,v
retrieving revision 1.207.4.6
diff -u -p -r1.207.4.6 sparc.h
--- sparc/sparc.h	23 Sep 2002 04:38:48 -0000	1.207.4.6
+++ sparc/sparc.h	25 Sep 2002 04:05:00 -0000
@@ -1934,27 +1934,6 @@ do {									\
 
 #define STRICT_ARGUMENT_NAMING TARGET_V9
 
-/* We do not allow sibling calls if -mflat, nor
-   we do not allow indirect calls to be optimized into sibling calls.
-
-   Also, on sparc 32-bit we cannot emit a sibling call when the
-   current function returns a structure.  This is because the "unimp
-   after call" convention would cause the callee to return to the
-   wrong place.  The generic code already disallows cases where the
-   function being called returns a structure.
-
-   It may seem strange how this last case could occur.  Usually there
-   is code after the call which jumps to epilogue code which dumps the
-   return value into the struct return area.  That ought to invalidate
-   the sibling call right?  Well, in the c++ case we can end up passing
-   the pointer to the struct return area to a constructor (which returns
-   void) and then nothing else happens.  Such a sibling call would look
-   valid without the added check here.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) \
-	(DECL \
-	 && ! TARGET_FLAT \
-	 && (TARGET_ARCH64 || ! current_function_returns_struct))
-
 /* Generate RTL to flush the register windows so as to make arbitrary frames
    available.  */
 #define SETUP_FRAME_ADDRESSES()		\
Index: xtensa/xtensa.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/xtensa/xtensa.c,v
retrieving revision 1.18.4.1
diff -u -p -r1.18.4.1 xtensa.c
--- xtensa/xtensa.c	5 Sep 2002 17:47:31 -0000	1.18.4.1
+++ xtensa/xtensa.c	25 Sep 2002 04:05:08 -0000
@@ -202,6 +202,7 @@ static unsigned int xtensa_multibss_sect
 static void xtensa_select_rtx_section
   PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT));
 static void xtensa_encode_section_info PARAMS ((tree, int));
+static int xtensa_function_ok_for_sibcall PARAMS ((tree, tree));
 
 static rtx frame_size_const;
 static int current_function_arg_words;
@@ -238,6 +239,9 @@ static const int reg_nonleaf_alloc_order
 #undef TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO  xtensa_encode_section_info
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL xtensa_function_ok_for_sibcall
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
@@ -1624,6 +1628,16 @@ xtensa_emit_loop_end (insn, operands)
   output_asm_insn ("# loop end for %0", operands);
 }
 
+/* A C expression that evaluates to true if it is ok to perform a
+   sibling call to DECL.  */
+/* TODO: fix this up to allow at least some sibcalls */
+static int
+xtensa_function_ok_for_sibcall (decl, exp)
+     tree decl;
+     tree exp;
+{
+  return 0;
+}
 
 char *
 xtensa_emit_call (callop, operands)
Index: xtensa/xtensa.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/xtensa/xtensa.h,v
retrieving revision 1.20.4.1
diff -u -p -r1.20.4.1 xtensa.h
--- xtensa/xtensa.h	16 Sep 2002 17:38:28 -0000	1.20.4.1
+++ xtensa/xtensa.h	25 Sep 2002 04:05:15 -0000
@@ -1287,11 +1287,6 @@ typedef struct xtensa_args {
    indexing purposes) so give the MEM rtx a words's mode.  */
 #define FUNCTION_MODE SImode
 
-/* A C expression that evaluates to true if it is ok to perform a
-   sibling call to DECL.  */
-/* TODO: fix this up to allow at least some sibcalls */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) 0
-
 /* Xtensa constant costs.  */
 #define CONST_COSTS(X, CODE, OUTER_CODE)				\
   case CONST_INT:							\
-------------- next part --------------
Index: hooks.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/hooks.c,v
retrieving revision 1.5
diff -u -p -r1.5 hooks.c
--- hooks.c	21 Aug 2002 02:41:44 -0000	1.5
+++ hooks.c	25 Sep 2002 04:51:01 -0000
@@ -62,3 +62,13 @@ hook_FILEptr_constcharptr_void (a, b)
      const char *b ATTRIBUTE_UNUSED;
 {
 }
+
+/* Hook that takes a function definition and an expression node and
+   returns false.  */
+bool
+hook_tree_tree_bool_false (a, b)
+     tree a ATTRIBUTE_UNUSED;
+     tree b ATTRIBUTE_UNUSED;
+{
+  return false;
+}
Index: hooks.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/hooks.h,v
retrieving revision 1.5
diff -u -p -r1.5 hooks.h
--- hooks.h	21 Aug 2002 02:41:44 -0000	1.5
+++ hooks.h	25 Sep 2002 04:51:01 -0000
@@ -27,5 +27,5 @@ bool hook_tree_bool_false PARAMS ((tree)
 void hook_tree_int_void PARAMS ((tree, int));
 void hook_void_void PARAMS ((void));
 void hook_FILEptr_constcharptr_void PARAMS ((FILE *, const char *));
-
+bool hook_tree_tree_bool_false PARAMS ((tree, tree));
 #endif
Index: target-def.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.30.2.3
diff -u -p -r1.30.2.3 target-def.h
--- target-def.h	17 Sep 2002 22:58:47 -0000	1.30.2.3
+++ target-def.h	25 Sep 2002 04:51:02 -0000
@@ -245,6 +245,7 @@ Foundation, 59 Temple Place - Suite 330,
 
 /* In hook.c.  */
 #define TARGET_CANNOT_MODIFY_JUMPS_P hook_void_bool_false
+#define TARGET_FUNCTION_OK_FOR_SIBCALL hook_tree_tree_bool_false
 
 #ifndef TARGET_IN_SMALL_DATA_P
 #define TARGET_IN_SMALL_DATA_P hook_tree_bool_false
@@ -271,6 +272,7 @@ Foundation, 59 Temple Place - Suite 330,
   TARGET_EXPAND_BUILTIN,			\
   TARGET_SECTION_TYPE_FLAGS,			\
   TARGET_CANNOT_MODIFY_JUMPS_P,			\
+  TARGET_FUNCTION_OK_FOR_SIBCALL,		\
   TARGET_IN_SMALL_DATA_P,			\
   TARGET_BINDS_LOCAL_P,				\
   TARGET_ENCODE_SECTION_INFO,			\
Index: target.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/target.h,v
retrieving revision 1.33.2.3
diff -u -p -r1.33.2.3 target.h
--- target.h	17 Sep 2002 22:58:47 -0000	1.33.2.3
+++ target.h	25 Sep 2002 04:51:03 -0000
@@ -244,6 +244,10 @@ struct gcc_target
      not, at the current point in the compilation.  */
   bool (* cannot_modify_jumps_p) PARAMS ((void));
 
+  /* True if function defined in either the function declaration, or
+     pointed to via function pointer is ok to be sibcall optimized.  */
+  bool (*function_ok_for_sibcall) PARAMS ((tree, tree));
+
   /* True if EXP should be placed in a "small data" section.  */
   bool (* in_small_data_p) PARAMS ((tree));
 
Index: calls.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/calls.c,v
retrieving revision 1.231.4.5
diff -u -p -r1.231.4.5 calls.c
--- calls.c	20 Sep 2002 01:29:06 -0000	1.231.4.5
+++ calls.c	25 Sep 2002 04:51:20 -0000
@@ -36,10 +36,6 @@ Software Foundation, 59 Temple Place - S
 #include "langhooks.h"
 #include "target.h"
 
-#if !defined FUNCTION_OK_FOR_SIBCALL
-#define FUNCTION_OK_FOR_SIBCALL(DECL) 1
-#endif
-
 /* Decide whether a function's arguments should be processed
    from first to last or from last to first.
 
@@ -2443,17 +2439,12 @@ expand_call (exp, target, ignore)
 	 It does not seem worth the effort since few optimizable
 	 sibling calls will return a structure.  */
       || structure_value_addr != NULL_RTX
-      /* If the register holding the address is a callee saved
-	 register, then we lose.  We have no way to prevent that,
-	 so we only allow calls to named functions.  */
-      /* ??? This could be done by having the insn constraints
-	 use a register class that is all call-clobbered.  Any
-	 reload insns generated to fix things up would appear
-	 before the sibcall_epilogue.  */
-      || fndecl == NULL_TREE
+      /* Check for indirect calls.  Not all targets have register
+	 classes to support sibcall optimization for indirect calls,
+	 but some like ix86, do.  */
+      || (*targetm.function_ok_for_sibcall) (fndecl, exp)
       || (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP))
-      || TREE_THIS_VOLATILE (fndecl)
-      || !FUNCTION_OK_FOR_SIBCALL (fndecl)
+      || (fndecl != NULL_TREE && TREE_THIS_VOLATILE (fndecl))
       /* If this function requires more stack slots than the current
 	 function, we cannot change it into a sibling call.  */
       || args_size.constant > current_function_args_size


More information about the Gcc-patches mailing list