aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-inline.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2003-09-11 01:45:05 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2003-09-10 23:45:05 +0000
commitf08545a8f225fe7adfbfab9a652bb8c325494d3c (patch)
tree240ef70cc4d941a711b2312423640e7e93085f12 /gcc/tree-inline.c
parent25c84396dd1bfb44ff5365d8ff512f1233101dfd (diff)
downloadgcc-f08545a8f225fe7adfbfab9a652bb8c325494d3c.zip
gcc-f08545a8f225fe7adfbfab9a652bb8c325494d3c.tar.gz
gcc-f08545a8f225fe7adfbfab9a652bb8c325494d3c.tar.bz2
c-objc-common.c (c_cannot_inline_tree_fn): Warn on why function is not inlinable; do not check the body.
* c-objc-common.c (c_cannot_inline_tree_fn): Warn on why function is not inlinable; do not check the body. (inline_forbidden_p): Move to... * tree-inline.c (inline_forbidden_p_1): ... here; Add warnings; deal with alloca, longjmp. (inline_forbidden_p): New static function. (find_alloca_call_1, find_alloca_call, find_builtin_longjmp_call_1, find_builtin_longjmp_call): Kill. From-SVN: r71283
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r--gcc/tree-inline.c196
1 files changed, 133 insertions, 63 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 8893b26..43e9848 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -128,10 +128,6 @@ static tree initialize_inlined_parameters (inline_data *, tree, tree, tree);
static void remap_block (tree *, tree, inline_data *);
static tree add_stmt_to_compound (tree, tree, tree);
#endif /* INLINER_FOR_JAVA */
-static tree find_alloca_call_1 (tree *, int *, void *);
-static tree find_alloca_call (tree);
-static tree find_builtin_longjmp_call_1 (tree *, int *, void *);
-static tree find_builtin_longjmp_call (tree);
/* Remap DECL during the copying of the BLOCK tree for the function. */
@@ -880,50 +876,148 @@ tree_inlinable_function_p (tree fn)
return inlinable_function_p (fn);
}
-/* If *TP is possibly call to alloca, return nonzero. */
-static tree
-find_alloca_call_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
- void *data ATTRIBUTE_UNUSED)
-{
- if (alloca_call_p (*tp))
- return *tp;
- return NULL;
-}
+static const char *inline_forbidden_reason;
-/* Return subexpression representing possible alloca call, if any. */
static tree
-find_alloca_call (tree exp)
+inline_forbidden_p_1 (tree *nodep, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *fn)
{
- location_t saved_loc = input_location;
- tree ret = walk_tree_without_duplicates
- (&exp, find_alloca_call_1, NULL);
- input_location = saved_loc;
- return ret;
-}
+ tree node = *nodep;
+ tree t;
-static tree
-find_builtin_longjmp_call_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
- void *data ATTRIBUTE_UNUSED)
-{
- tree exp = *tp, decl;
+ switch (TREE_CODE (node))
+ {
+ case CALL_EXPR:
+ /* Refuse to inline alloca call unless user explicitly forced so as this
+ may change program's memory overhead drastically when the function
+ using alloca is called in loop. In GCC present in SPEC2000 inlining
+ into schedule_block cause it to require 2GB of ram instead of 256MB. */
+ if (alloca_call_p (node)
+ && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
+ {
+ inline_forbidden_reason = "%Hfunction '%F' can never be inlined "
+ "because it uses alloca (override using "
+ "the always_inline attribute)";
+ return node;
+ }
+ t = get_callee_fndecl (node);
+ if (! t)
+ break;
+
+
+ /* We cannot inline functions that call setjmp. */
+ if (setjmp_call_p (t))
+ {
+ inline_forbidden_reason = "%Hfunction '%F' can never be inlined"
+ " because it uses setjmp";
+ return node;
+ }
- if (TREE_CODE (exp) == CALL_EXPR
- && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
- && (decl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
- TREE_CODE (decl) == FUNCTION_DECL)
- && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (decl) == BUILT_IN_LONGJMP)
- return decl;
+ switch (DECL_FUNCTION_CODE (t))
+ {
+ /* We cannot inline functions that take a variable number of
+ arguments. */
+ case BUILT_IN_VA_START:
+ case BUILT_IN_STDARG_START:
+ {
+ inline_forbidden_reason = "%Hfunction '%F' can never be inlined "
+ "because it uses variable argument lists";
+ return node;
+ }
+ case BUILT_IN_LONGJMP:
+ {
+ /* We can't inline functions that call __builtin_longjmp at all.
+ The non-local goto machinery really requires the destination
+ be in a different function. If we allow the function calling
+ __builtin_longjmp to be inlined into the function calling
+ __builtin_setjmp, Things will Go Awry. */
+ /* ??? Need front end help to identify "regular" non-local goto. */
+ if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL)
+ {
+ inline_forbidden_reason = "%Hfunction '%F' can never be inlined "
+ "because it uses setjmp-longjmp "
+ "exception handling";
+ return node;
+ }
+ }
+
+ default:
+ break;
+ }
+ break;
- return NULL;
+#ifndef INLINER_FOR_JAVA
+ case DECL_STMT:
+ /* We cannot inline functions that contain other functions. */
+ if (TREE_CODE (TREE_OPERAND (node, 0)) == FUNCTION_DECL
+ && DECL_INITIAL (TREE_OPERAND (node, 0)))
+ {
+ inline_forbidden_reason = "%Hfunction '%F' can never be inlined "
+ "because it contains a nested function";
+ return node;
+ }
+ break;
+
+ case GOTO_STMT:
+ case GOTO_EXPR:
+ t = TREE_OPERAND (node, 0);
+
+ /* We will not inline a function which uses computed goto. The
+ addresses of its local labels, which may be tucked into
+ global storage, are of course not constant across
+ instantiations, which causes unexpected behavior. */
+ if (TREE_CODE (t) != LABEL_DECL)
+ {
+ inline_forbidden_reason = "%Hfunction '%F' can never be inlined "
+ "because it contains a nonlocal label";
+ return node;
+ }
+
+ /* We cannot inline a nested function that jumps to a nonlocal
+ label. */
+ if (TREE_CODE (t) == LABEL_DECL && DECL_CONTEXT (t) != fn)
+ {
+ inline_forbidden_reason = "%Hfunction '%F' can never be inlined "
+ "because it contains a nonlocal goto";
+ return node;
+ }
+
+ break;
+
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ /* We cannot inline a function of the form
+
+ void F (int i) { struct S { int ar[i]; } s; }
+
+ Attempting to do so produces a catch-22.
+ If walk_tree examines the TYPE_FIELDS chain of RECORD_TYPE/
+ UNION_TYPE nodes, then it goes into infinite recursion on a
+ structure containing a pointer to its own type. If it doesn't,
+ then the type node for S doesn't get adjusted properly when
+ F is inlined, and we abort in find_function_data. */
+ for (t = TYPE_FIELDS (node); t; t = TREE_CHAIN (t))
+ if (variably_modified_type_p (TREE_TYPE (t)))
+ {
+ inline_forbidden_reason = "%Hfunction '%F' can never be inlined "
+ "because it uses variable sized variables";
+ return node;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return NULL_TREE;
}
+/* Return subexpression representing possible alloca call, if any. */
static tree
-find_builtin_longjmp_call (tree exp)
+inline_forbidden_p (tree fndecl)
{
location_t saved_loc = input_location;
tree ret = walk_tree_without_duplicates
- (&exp, find_builtin_longjmp_call_1, NULL);
+ (&DECL_SAVED_TREE (fndecl), inline_forbidden_p_1, fndecl);
input_location = saved_loc;
return ret;
}
@@ -935,8 +1029,6 @@ static bool
inlinable_function_p (tree fn)
{
bool inlinable = true;
- bool calls_builtin_longjmp = false;
- bool calls_alloca = false;
/* If we've already decided this function shouldn't be inlined,
there's no need to check again. */
@@ -980,24 +1072,7 @@ inlinable_function_p (tree fn)
inlinable = false;
#endif /* INLINER_FOR_JAVA */
- /* We can't inline functions that call __builtin_longjmp at all.
- The non-local goto machinery really requires the destination
- be in a different function. If we allow the function calling
- __builtin_longjmp to be inlined into the function calling
- __builtin_setjmp, Things will Go Awry. */
- /* ??? Need front end help to identify "regular" non-local goto. */
- else if (find_builtin_longjmp_call (DECL_SAVED_TREE (fn)))
- calls_builtin_longjmp = true;
-
- /* Refuse to inline alloca call unless user explicitly forced so as this
- may change program's memory overhead drastically when the function
- using alloca is called in loop. In GCC present in SPEC2000 inlining
- into schedule_block cause it to require 2GB of ram instead of 256MB. */
- else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL
- && find_alloca_call (DECL_SAVED_TREE (fn)))
- calls_alloca = true;
-
- if (calls_builtin_longjmp || calls_alloca)
+ else if (inline_forbidden_p (fn))
{
/* See if we should warn about uninlinable functions. Previously,
some of these warnings would be issued while trying to expand
@@ -1012,13 +1087,8 @@ inlinable_function_p (tree fn)
&& DECL_DECLARED_INLINE_P (fn)
&& !DECL_IN_SYSTEM_HEADER (fn));
- if (do_warning && calls_builtin_longjmp)
- warning ("%Hfunction '%F' can never be inlined because it uses "
- "setjmp-longjmp exception handling",
- &DECL_SOURCE_LOCATION (fn), fn);
- if (do_warning && calls_alloca)
- warning ("%Hfunction '%F' can never be inlined because it uses "
- "setjmp-longjmp exception handling",
+ if (do_warning)
+ warning (inline_forbidden_reason,
&DECL_SOURCE_LOCATION (fn), fn);
inlinable = false;