diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/calls.c | 15 | ||||
-rw-r--r-- | gcc/tree-inline.c | 30 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
4 files changed, 54 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f323ff1..9bfbfae 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +Sun Nov 17 00:01:28 CET 2002 Jan Hubicka <jh@suse.cz> + + * calls.c (alloca_call_p): New global function. + * tree.h (alloca_call_p): New. + * tree-inline.c (inlinable_function_p): Do not inline when + function calls alloca. + (find_alloca_call, find_alloca_call_1): New functions. + 2002-11-18 Kazu Hirata <kazu@cs.umass.edu> * config/h8300/h8300.md (*andorqi3): Use bor between bld and diff --git a/gcc/calls.c b/gcc/calls.c index f2f9c57..99722b5 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -801,6 +801,21 @@ setjmp_call_p (fndecl) return special_function_p (fndecl, 0) & ECF_RETURNS_TWICE; } +/* Return true when exp contains alloca call. */ +bool +alloca_call_p (exp) + tree exp; +{ + if (TREE_CODE (exp) == CALL_EXPR + && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR + && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) + == FUNCTION_DECL) + && (special_function_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), + 0) & ECF_MAY_BE_ALLOCA)) + return true; + return false; +} + /* Detect flags (function attributes) from the function decl or type node. */ static int diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 362ddd1..73ba48a 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -122,6 +122,8 @@ static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *)); static tree initialize_inlined_parameters PARAMS ((inline_data *, tree, tree, tree)); static void remap_block PARAMS ((tree *, tree, inline_data *)); static tree add_stmt_to_compound PARAMS ((tree, tree, tree)); +static tree find_alloca_call_1 PARAMS ((tree *, int *, void *)); +static tree find_alloca_call PARAMS ((tree)); #endif /* INLINER_FOR_JAVA */ /* The approximate number of instructions per statement. This number @@ -857,6 +859,27 @@ tree_inlinable_function_p (fn) return inlinable_function_p (fn, NULL); } +/* if *TP is possibly call to alloca, return nonzero. */ +static tree +find_alloca_call_1 (tp, walk_subtrees, data) + tree *tp; + int *walk_subtrees ATTRIBUTE_UNUSED; + void *data ATTRIBUTE_UNUSED; +{ + if (alloca_call_p (*tp)) + return *tp; + return NULL; +} + +/* Return subexpression representing possible alloca call, + if any. */ +static tree +find_alloca_call (exp) + tree exp; +{ + return walk_tree (&exp, find_alloca_call_1, NULL, NULL); +} + /* Returns nonzero if FN is a function that can be inlined into the inlining context ID_. If ID_ is NULL, check whether the function can be inlined at all. */ @@ -897,6 +920,13 @@ inlinable_function_p (fn, id) else if (! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn) && currfn_insns > MAX_INLINE_INSNS_SINGLE) ; + /* 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))) + ; /* All is well. We can inline this function. Traditionally, GCC has refused to inline functions using alloca, or functions whose values are returned in a PARALLEL, and a few other such obscure @@ -3018,6 +3018,7 @@ extern rtx emit_line_note PARAMS ((const char *, int)); /* In calls.c */ extern int setjmp_call_p PARAMS ((tree)); +extern bool alloca_call_p PARAMS ((tree)); /* In attribs.c. */ |