* Remember/restore ALLOCA_FOR_VAR_P over tuples
@ 2011-04-14 15:18 Michael Matz
2011-04-14 15:24 ` Richard Guenther
2011-04-14 15:49 ` Eric Botcazou
0 siblings, 2 replies; 7+ messages in thread
From: Michael Matz @ 2011-04-14 15:18 UTC (permalink / raw)
To: gcc-patches
Hello,
as my patch for stack-arrays in fortran reveals we a problem that VLA
objects basically prevent all inlining to happen. They're transformed
into alloca calls and those are considered to disable inlining. The
(correct) fear being that inlining a bare alloca call into a loop leads to
unbounded stack growth.
But the situation is different for alloca calls emitted for dealing with
VLA objects. They always are wrapped with stack_save/stack_restore calls.
Inlining such regions always is okay, even into loops. The stack space
usage will be exactly the same at runtime.
We have a flag for this already on the CALL_EXPR. But we don't retain it
over tuples, and hence we also don't look at it in
inline_forbidden_p_stmt. This patch fixes both. (The strange testing of
builtin-ness is because in CALL_EXPR the ALLOCA_FOR_VAR_P and
CALL_FROM_THUNK_P flags are overloaded)
(This fixes the regression of fatigue with the stack-arrays patch)
regstrapping on x86_64-linux in progress, okay for trunk?
Ciao,
Michael.
* 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 ALLOCA_FOR_VAR_P
state.
* cfgexpand.c (expand_call_stmt): Restore ALLOCA_FOR_VAR_P state.
* tree-inline.c (inline_forbidden_p_stmt): Don't reject alloca
calls if they were for VLA objects.
Index: cfgexpand.c
===================================================================
*** cfgexpand.c (revision 172431)
--- cfgexpand.c (working copy)
*************** expand_call_stmt (gimple stmt)
*** 1873,1879 ****
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);
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));
--- 1873,1884 ----
CALL_EXPR_TAILCALL (exp) = gimple_call_tail_p (stmt);
CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_p (stmt);
! if (decl
! && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
! && DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA)
! 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));
Index: tree-inline.c
===================================================================
*** tree-inline.c (revision 172431)
--- tree-inline.c (working copy)
*************** inline_forbidden_p_stmt (gimple_stmt_ite
*** 2997,3004 ****
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 (gimple_alloca_call_p (stmt)
&& !lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
{
inline_forbidden_reason
--- 2997,3007 ----
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. 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
Index: gimple.c
===================================================================
*** gimple.c (revision 172431)
--- gimple.c (working copy)
*************** gimple_build_call_from_tree (tree t)
*** 303,309 ****
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));
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));
--- 303,314 ----
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));
! if (fndecl
! && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
! && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA)
! gimple_call_set_alloca_for_var (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));
Index: gimple.h
===================================================================
*** gimple.h (revision 172431)
--- gimple.h (working copy)
*************** enum gf_mask {
*** 102,107 ****
--- 102,108 ----
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
*************** gimple_call_nothrow_p (gimple s)
*** 2329,2334 ****
--- 2330,2358 ----
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. */
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Remember/restore ALLOCA_FOR_VAR_P over tuples
2011-04-14 15:18 Remember/restore ALLOCA_FOR_VAR_P over tuples Michael Matz
@ 2011-04-14 15:24 ` Richard Guenther
2011-04-14 15:49 ` Eric Botcazou
1 sibling, 0 replies; 7+ messages in thread
From: Richard Guenther @ 2011-04-14 15:24 UTC (permalink / raw)
To: Michael Matz; +Cc: gcc-patches
On Thu, Apr 14, 2011 at 5:18 PM, Michael Matz <matz@suse.de> wrote:
> Hello,
>
> as my patch for stack-arrays in fortran reveals we a problem that VLA
> objects basically prevent all inlining to happen. They're transformed
> into alloca calls and those are considered to disable inlining. The
> (correct) fear being that inlining a bare alloca call into a loop leads to
> unbounded stack growth.
>
> But the situation is different for alloca calls emitted for dealing with
> VLA objects. They always are wrapped with stack_save/stack_restore calls.
> Inlining such regions always is okay, even into loops. The stack space
> usage will be exactly the same at runtime.
>
> We have a flag for this already on the CALL_EXPR. But we don't retain it
> over tuples, and hence we also don't look at it in
> inline_forbidden_p_stmt. This patch fixes both. (The strange testing of
> builtin-ness is because in CALL_EXPR the ALLOCA_FOR_VAR_P and
> CALL_FROM_THUNK_P flags are overloaded)
>
> (This fixes the regression of fatigue with the stack-arrays patch)
>
> regstrapping on x86_64-linux in progress, okay for trunk?
Ok.
Thanks,
Richard.
>
> Ciao,
> Michael.
>
> * 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 ALLOCA_FOR_VAR_P
> state.
> * cfgexpand.c (expand_call_stmt): Restore ALLOCA_FOR_VAR_P state.
>
> * tree-inline.c (inline_forbidden_p_stmt): Don't reject alloca
> calls if they were for VLA objects.
>
> Index: cfgexpand.c
> ===================================================================
> *** cfgexpand.c (revision 172431)
> --- cfgexpand.c (working copy)
> *************** expand_call_stmt (gimple stmt)
> *** 1873,1879 ****
>
> 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);
> 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));
> --- 1873,1884 ----
>
> CALL_EXPR_TAILCALL (exp) = gimple_call_tail_p (stmt);
> CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_p (stmt);
> ! if (decl
> ! && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
> ! && DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA)
> ! 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));
> Index: tree-inline.c
> ===================================================================
> *** tree-inline.c (revision 172431)
> --- tree-inline.c (working copy)
> *************** inline_forbidden_p_stmt (gimple_stmt_ite
> *** 2997,3004 ****
> 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 (gimple_alloca_call_p (stmt)
> && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
> {
> inline_forbidden_reason
> --- 2997,3007 ----
> 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. 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
> Index: gimple.c
> ===================================================================
> *** gimple.c (revision 172431)
> --- gimple.c (working copy)
> *************** gimple_build_call_from_tree (tree t)
> *** 303,309 ****
> 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));
> 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));
> --- 303,314 ----
> 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));
> ! if (fndecl
> ! && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
> ! && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA)
> ! gimple_call_set_alloca_for_var (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));
> Index: gimple.h
> ===================================================================
> *** gimple.h (revision 172431)
> --- gimple.h (working copy)
> *************** enum gf_mask {
> *** 102,107 ****
> --- 102,108 ----
> 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
> *************** gimple_call_nothrow_p (gimple s)
> *** 2329,2334 ****
> --- 2330,2358 ----
> 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. */
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Remember/restore ALLOCA_FOR_VAR_P over tuples
2011-04-14 15:18 Remember/restore ALLOCA_FOR_VAR_P over tuples Michael Matz
2011-04-14 15:24 ` Richard Guenther
@ 2011-04-14 15:49 ` Eric Botcazou
2011-04-14 16:07 ` Michael Matz
1 sibling, 1 reply; 7+ messages in thread
From: Eric Botcazou @ 2011-04-14 15:49 UTC (permalink / raw)
To: Michael Matz; +Cc: gcc-patches
> We have a flag for this already on the CALL_EXPR. But we don't retain it
> over tuples, and hence we also don't look at it in
> inline_forbidden_p_stmt. This patch fixes both. (The strange testing of
> builtin-ness is because in CALL_EXPR the ALLOCA_FOR_VAR_P and
> CALL_FROM_THUNK_P flags are overloaded)
More precisely, we don't expose it on tuples; we do retain it over tuples since
we tuplify CALL_FROM_THUNK_P and we rematerialize it in expand_call_stmt. The
flag is later passed to expand_builtin_alloca.
> * 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 ALLOCA_FOR_VAR_P
> state.
> * cfgexpand.c (expand_call_stmt): Restore ALLOCA_FOR_VAR_P state.
>
> * tree-inline.c (inline_forbidden_p_stmt): Don't reject alloca
> calls if they were for VLA objects.
Nice patch. The idea also occurred to me recently because we often run into
the inlining limitation in Ada.
Btw, I don't remember why I chose ALLOCA_FOR_VAR_P over CALL_ALLOCA_FOR_VAR_P
but, given the name of the GIMPLE flag and predicate, it's probably time to
change it.
--
Eric Botcazou
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Remember/restore ALLOCA_FOR_VAR_P over tuples
2011-04-14 15:49 ` Eric Botcazou
@ 2011-04-14 16:07 ` Michael Matz
2011-04-15 20:25 ` Michael Matz
0 siblings, 1 reply; 7+ messages in thread
From: Michael Matz @ 2011-04-14 16:07 UTC (permalink / raw)
To: Eric Botcazou; +Cc: gcc-patches
Hi,
On Thu, 14 Apr 2011, Eric Botcazou wrote:
> > We have a flag for this already on the CALL_EXPR. But we don't retain
> > it over tuples, and hence we also don't look at it in
> > inline_forbidden_p_stmt. This patch fixes both. (The strange testing
> > of builtin-ness is because in CALL_EXPR the ALLOCA_FOR_VAR_P and
> > CALL_FROM_THUNK_P flags are overloaded)
>
> More precisely, we don't expose it on tuples; we do retain it over
> tuples since we tuplify CALL_FROM_THUNK_P and we rematerialize it in
> expand_call_stmt.
Right, that's correct, although of course it relies on the sharing of both
flags on the tree side, which surprised me a bit as no comments in
gimple.c/cfgexpand.c prepared me for that :) I chose to not retain this
sharing of flags for the gimple tuple, we have enough bits available for
now.
> Nice patch. The idea also occurred to me recently because we often run
> into the inlining limitation in Ada.
>
> Btw, I don't remember why I chose ALLOCA_FOR_VAR_P over
> CALL_ALLOCA_FOR_VAR_P but, given the name of the GIMPLE flag and
> predicate, it's probably time to change it.
Good idea, I'll rename it before checking in.
Ciao,
Michael.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Remember/restore ALLOCA_FOR_VAR_P over tuples
2011-04-14 16:07 ` Michael Matz
@ 2011-04-15 20:25 ` Michael Matz
2011-04-16 12:53 ` Eric Botcazou
2011-05-11 9:08 ` H.J. Lu
0 siblings, 2 replies; 7+ messages in thread
From: Michael Matz @ 2011-04-15 20:25 UTC (permalink / raw)
To: Eric Botcazou; +Cc: gcc-patches
Hi,
On Thu, 14 Apr 2011, Michael Matz wrote:
> > Btw, I don't remember why I chose ALLOCA_FOR_VAR_P over
> > CALL_ALLOCA_FOR_VAR_P but, given the name of the GIMPLE flag and
> > predicate, it's probably time to change it.
>
> Good idea, I'll rename it before checking in.
r172516, for reference also below. I later saw that my patch causes
cxg2001 to fail. I've analyzed it enough to be sure that it's only
exposed by this patch (due to inlining now happening), in fact it's a
problem in IRA that is reproducible with a C++ testcase even without the
patch. I've filed PR48633 for this.
Ciao,
Michael.
* 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.
Index: tree.h
===================================================================
*** tree.h (revision 172431)
--- tree.h (working copy)
*************** struct GTY(()) tree_common {
*** 574,580 ****
all decls
CALL_FROM_THUNK_P and
! ALLOCA_FOR_VAR_P in
CALL_EXPR
side_effects_flag:
--- 574,580 ----
all decls
CALL_FROM_THUNK_P and
! CALL_ALLOCA_FOR_VAR_P in
CALL_EXPR
side_effects_flag:
*************** extern void omp_clause_range_check_faile
*** 1388,1394 ****
/* 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)
/* 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
--- 1388,1395 ----
/* 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 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
Index: builtins.c
===================================================================
*** builtins.c (revision 172431)
--- builtins.c (working copy)
*************** expand_builtin (tree exp, rtx target, rt
*** 6025,6031 ****
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));
if (target)
return target;
break;
--- 6025,6031 ----
case BUILT_IN_ALLOCA:
/* If the allocation stems from the declaration of a variable-sized
object, it cannot accumulate. */
! target = expand_builtin_alloca (exp, CALL_ALLOCA_FOR_VAR_P (exp));
if (target)
return target;
break;
Index: function.c
===================================================================
*** function.c (revision 172431)
--- function.c (working copy)
*************** gimplify_parameters (void)
*** 3652,3658 ****
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;
t = fold_convert (ptr_type, t);
t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
gimplify_and_add (t, &stmts);
--- 3652,3658 ----
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. */
! 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);
Index: gimplify.c
===================================================================
*** gimplify.c (revision 172431)
--- gimplify.c (working copy)
*************** gimplify_vla_decl (tree decl, gimple_seq
*** 1329,1335 ****
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;
t = fold_convert (ptr_type, t);
t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
--- 1329,1335 ----
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. */
! CALL_ALLOCA_FOR_VAR_P (t) = 1;
t = fold_convert (ptr_type, t);
t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
Index: cfgexpand.c
===================================================================
*** cfgexpand.c (revision 172431)
--- cfgexpand.c (working copy)
*************** expand_call_stmt (gimple stmt)
*** 1873,1879 ****
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);
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));
--- 1873,1884 ----
CALL_EXPR_TAILCALL (exp) = gimple_call_tail_p (stmt);
CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_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));
Index: tree-inline.c
===================================================================
*** tree-inline.c (revision 172431)
--- tree-inline.c (working copy)
*************** inline_forbidden_p_stmt (gimple_stmt_ite
*** 2997,3004 ****
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 (gimple_alloca_call_p (stmt)
&& !lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
{
inline_forbidden_reason
--- 2997,3007 ----
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. 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
Index: gimple.c
===================================================================
*** gimple.c (revision 172431)
--- gimple.c (working copy)
*************** gimple_build_call_from_tree (tree t)
*** 303,309 ****
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));
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));
--- 303,314 ----
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));
! 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));
Index: gimple.h
===================================================================
*** gimple.h (revision 172431)
--- gimple.h (working copy)
*************** enum gf_mask {
*** 102,107 ****
--- 102,108 ----
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
*************** gimple_call_nothrow_p (gimple s)
*** 2329,2334 ****
--- 2330,2358 ----
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. */
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Remember/restore ALLOCA_FOR_VAR_P over tuples
2011-04-15 20:25 ` Michael Matz
@ 2011-04-16 12:53 ` Eric Botcazou
2011-05-11 9:08 ` H.J. Lu
1 sibling, 0 replies; 7+ messages in thread
From: Eric Botcazou @ 2011-04-16 12:53 UTC (permalink / raw)
To: Michael Matz; +Cc: gcc-patches
> r172516, for reference also below. I later saw that my patch causes
> cxg2001 to fail. I've analyzed it enough to be sure that it's only
> exposed by this patch (due to inlining now happening), in fact it's a
> problem in IRA that is reproducible with a C++ testcase even without the
> patch. I've filed PR48633 for this.
Thanks for debugging the problem. I was expecting some fallouts in Ada because
this will shake a little the compiler, but the results of our internal testing
don't show other problems than this ACATS failure, so that's great.
--
Eric Botcazou
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Remember/restore ALLOCA_FOR_VAR_P over tuples
2011-04-15 20:25 ` Michael Matz
2011-04-16 12:53 ` Eric Botcazou
@ 2011-05-11 9:08 ` H.J. Lu
1 sibling, 0 replies; 7+ messages in thread
From: H.J. Lu @ 2011-05-11 9:08 UTC (permalink / raw)
To: Michael Matz; +Cc: Eric Botcazou, gcc-patches
On Fri, Apr 15, 2011 at 1:20 PM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Thu, 14 Apr 2011, Michael Matz wrote:
>
>> > Btw, I don't remember why I chose ALLOCA_FOR_VAR_P over
>> > CALL_ALLOCA_FOR_VAR_P but, given the name of the GIMPLE flag and
>> > predicate, it's probably time to change it.
>>
>> Good idea, I'll rename it before checking in.
>
> r172516, for reference also below. I later saw that my patch causes
> cxg2001 to fail. I've analyzed it enough to be sure that it's only
> exposed by this patch (due to inlining now happening), in fact it's a
> problem in IRA that is reproducible with a C++ testcase even without the
> patch. I've filed PR48633 for this.
>
>
> Ciao,
> Michael.
>
> * 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.
>
This caused:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48953
--
H.J.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-05-11 4:03 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-14 15:18 Remember/restore ALLOCA_FOR_VAR_P over tuples Michael Matz
2011-04-14 15:24 ` Richard Guenther
2011-04-14 15:49 ` Eric Botcazou
2011-04-14 16:07 ` Michael Matz
2011-04-15 20:25 ` Michael Matz
2011-04-16 12:53 ` Eric Botcazou
2011-05-11 9:08 ` H.J. Lu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).