diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/builtins.c | 2 | ||||
-rw-r--r-- | gcc/cfgexpand.c | 7 | ||||
-rw-r--r-- | gcc/function.c | 2 | ||||
-rw-r--r-- | gcc/gimple.c | 7 | ||||
-rw-r--r-- | gcc/gimple.h | 24 | ||||
-rw-r--r-- | gcc/gimplify.c | 2 | ||||
-rw-r--r-- | gcc/tree-inline.c | 5 | ||||
-rw-r--r-- | gcc/tree.h | 5 |
9 files changed, 63 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 41877aa..8fe8856 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2011-04-15 Michael Matz <matz@suse.de> + + * tree.h (ALLOCA_FOR_VAR_P): Rename to CALL_ALLOCA_FOR_VAR_P. + * builtins.c (expand_builtin): Use CALL_ALLOCA_FOR_VAR_P. + * function.c (gimplify_parameters): Ditto. + * gimplify.c (gimplify_vla_decl): Ditto. + + * gimple.h (enum gf_mask): Add GF_CALL_ALLOCA_FOR_VAR. + (gimple_call_set_alloca_for_var): New inline function. + (gimple_call_alloca_for_var_p): Ditto. + * gimple.c (gimple_build_call_from_tree): Remember CALL_ALLOCA_FOR_VAR_P + state. + * cfgexpand.c (expand_call_stmt): Restore CALL_ALLOCA_FOR_VAR_P state. + + * tree-inline.c (inline_forbidden_p_stmt): Don't reject alloca + calls if they were for VLA objects. + 2011-04-15 Martin Jambor <mjambor@suse.cz> * ipa-prop.c (ipa_analyze_virtual_call_uses): Remove handling diff --git a/gcc/builtins.c b/gcc/builtins.c index 81f7ec6..b2534ce 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -6025,7 +6025,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, case BUILT_IN_ALLOCA: /* If the allocation stems from the declaration of a variable-sized object, it cannot accumulate. */ - target = expand_builtin_alloca (exp, ALLOCA_FOR_VAR_P (exp)); + target = expand_builtin_alloca (exp, CALL_ALLOCA_FOR_VAR_P (exp)); if (target) return target; break; diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index c2d71f4..365f061 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1879,7 +1879,12 @@ expand_call_stmt (gimple stmt) CALL_EXPR_TAILCALL (exp) = gimple_call_tail_p (stmt); CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_p (stmt); - CALL_FROM_THUNK_P (exp) = gimple_call_from_thunk_p (stmt); + if (decl + && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA) + CALL_ALLOCA_FOR_VAR_P (exp) = gimple_call_alloca_for_var_p (stmt); + else + CALL_FROM_THUNK_P (exp) = gimple_call_from_thunk_p (stmt); CALL_CANNOT_INLINE_P (exp) = gimple_call_cannot_inline_p (stmt); CALL_EXPR_VA_ARG_PACK (exp) = gimple_call_va_arg_pack_p (stmt); SET_EXPR_LOCATION (exp, gimple_location (stmt)); diff --git a/gcc/function.c b/gcc/function.c index dd42fba..c14a339 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3652,7 +3652,7 @@ gimplify_parameters (void) t = built_in_decls[BUILT_IN_ALLOCA]; t = build_call_expr (t, 1, DECL_SIZE_UNIT (parm)); /* The call has been built for a variable-sized object. */ - ALLOCA_FOR_VAR_P (t) = 1; + CALL_ALLOCA_FOR_VAR_P (t) = 1; t = fold_convert (ptr_type, t); t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t); gimplify_and_add (t, &stmts); diff --git a/gcc/gimple.c b/gcc/gimple.c index 5dc62ea..f19b219 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -303,7 +303,12 @@ gimple_build_call_from_tree (tree t) gimple_call_set_tail (call, CALL_EXPR_TAILCALL (t)); gimple_call_set_cannot_inline (call, CALL_CANNOT_INLINE_P (t)); gimple_call_set_return_slot_opt (call, CALL_EXPR_RETURN_SLOT_OPT (t)); - gimple_call_set_from_thunk (call, CALL_FROM_THUNK_P (t)); + if (fndecl + && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA) + gimple_call_set_alloca_for_var (call, CALL_ALLOCA_FOR_VAR_P (t)); + else + gimple_call_set_from_thunk (call, CALL_FROM_THUNK_P (t)); gimple_call_set_va_arg_pack (call, CALL_EXPR_VA_ARG_PACK (t)); gimple_call_set_nothrow (call, TREE_NOTHROW (t)); gimple_set_no_warning (call, TREE_NO_WARNING (t)); diff --git a/gcc/gimple.h b/gcc/gimple.h index 840e149..788ffe6 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -102,6 +102,7 @@ enum gf_mask { GF_CALL_TAILCALL = 1 << 3, GF_CALL_VA_ARG_PACK = 1 << 4, GF_CALL_NOTHROW = 1 << 5, + GF_CALL_ALLOCA_FOR_VAR = 1 << 6, GF_OMP_PARALLEL_COMBINED = 1 << 0, /* True on an GIMPLE_OMP_RETURN statement if the return does not require @@ -2330,6 +2331,29 @@ gimple_call_nothrow_p (gimple s) return (gimple_call_flags (s) & ECF_NOTHROW) != 0; } +/* If FOR_VAR is true, GIMPLE_CALL S is a call to builtin_alloca that + is known to be emitted for VLA objects. Those are wrapped by + stack_save/stack_restore calls and hence can't lead to unbounded + stack growth even when they occur in loops. */ + +static inline void +gimple_call_set_alloca_for_var (gimple s, bool for_var) +{ + GIMPLE_CHECK (s, GIMPLE_CALL); + if (for_var) + s->gsbase.subcode |= GF_CALL_ALLOCA_FOR_VAR; + else + s->gsbase.subcode &= ~GF_CALL_ALLOCA_FOR_VAR; +} + +/* Return true of S is a call to builtin_alloca emitted for VLA objects. */ + +static inline bool +gimple_call_alloca_for_var_p (gimple s) +{ + GIMPLE_CHECK (s, GIMPLE_CALL); + return (s->gsbase.subcode & GF_CALL_ALLOCA_FOR_VAR) != 0; +} /* Copy all the GF_CALL_* flags from ORIG_CALL to DEST_CALL. */ diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 34bdabf..f24bea2 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1337,7 +1337,7 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p) t = built_in_decls[BUILT_IN_ALLOCA]; t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl)); /* The call has been built for a variable-sized object. */ - ALLOCA_FOR_VAR_P (t) = 1; + CALL_ALLOCA_FOR_VAR_P (t) = 1; t = fold_convert (ptr_type, t); t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t); diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 84307ac..79c9538 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -2997,8 +2997,11 @@ inline_forbidden_p_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, 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. */ + RAM instead of 256MB. Don't do so for alloca calls emitted for + VLA objects as those can't cause unbounded growth (they're always + wrapped inside stack_save/stack_restore regions. */ if (gimple_alloca_call_p (stmt) + && !gimple_call_alloca_for_var_p (stmt) && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))) { inline_forbidden_reason @@ -574,7 +574,7 @@ struct GTY(()) tree_common { all decls CALL_FROM_THUNK_P and - ALLOCA_FOR_VAR_P in + CALL_ALLOCA_FOR_VAR_P in CALL_EXPR side_effects_flag: @@ -1388,7 +1388,8 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, /* In a CALL_EXPR, if the function being called is BUILT_IN_ALLOCA, means that it has been built for the declaration of a variable-sized object. */ -#define ALLOCA_FOR_VAR_P(NODE) (CALL_EXPR_CHECK (NODE)->base.protected_flag) +#define CALL_ALLOCA_FOR_VAR_P(NODE) \ + (CALL_EXPR_CHECK (NODE)->base.protected_flag) /* In a type, nonzero means that all objects of the type are guaranteed by the language or front-end to be properly aligned, so we can indicate that a MEM |