public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* 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).