diff options
author | Jan Hubicka <jh@suse.cz> | 2003-09-11 01:45:05 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2003-09-10 23:45:05 +0000 |
commit | f08545a8f225fe7adfbfab9a652bb8c325494d3c (patch) | |
tree | 240ef70cc4d941a711b2312423640e7e93085f12 /gcc/tree-inline.c | |
parent | 25c84396dd1bfb44ff5365d8ff512f1233101dfd (diff) | |
download | gcc-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.c | 196 |
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; |