tree.h (ALLOCA_FOR_VAR_P): Rename to CALL_ALLOCA_FOR_VAR_P.
authorMichael Matz <matz@suse.de>
Fri, 15 Apr 2011 19:48:25 +0000 (19:48 +0000)
committerMichael Matz <matz@gcc.gnu.org>
Fri, 15 Apr 2011 19:48:25 +0000 (19:48 +0000)
* 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.

From-SVN: r172516

gcc/ChangeLog
gcc/builtins.c
gcc/cfgexpand.c
gcc/function.c
gcc/gimple.c
gcc/gimple.h
gcc/gimplify.c
gcc/tree-inline.c
gcc/tree.h

index 41877aa1687d9e3dd42e42ef4e3cd045e3273114..8fe8856be8d9a2b947bc4d8df3fee86fe9858187 100644 (file)
@@ -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
index 81f7ec6bdc194de80bdb4bcf072966e28294c0be..b2534ce5850d678d81489dd6b1757546d9cf67c6 100644 (file)
@@ -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;
index c2d71f43bad974a6af29c0b6d36b707309f1e0be..365f0611f72ce216f6018a4b88798df4d88a5039 100644 (file)
@@ -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));
index dd42fba6692178eac2f30f82015089c43eb94641..c14a33967456481e201fed1cd397768dc9ce94d0 100644 (file)
@@ -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);
index 5dc62ea999253fad8ba7e88bef96153880108893..f19b219be5fcf5179210c951cecad0121b332966 100644 (file)
@@ -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));
index 840e149fde8a41dc968cb2cea5b8bc99d14cdc65..788ffe6d487726d9ba316fd6621d519b37b8d126 100644 (file)
@@ -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.  */
 
index 34bdabfa650d5b183210412b10141308fdf7d908..f24bea2cb14dd9722beef71da3715aee4721cf7c 100644 (file)
@@ -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);
 
index 84307ac3429fbc385cba581fa4f4222163215e00..79c9538dbaf8f0cade9e9ef73a3fe29ee1f844d3 100644 (file)
@@ -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
index 99a55f0bfbad4e7346a79e919e4b7bada0dbb4fa..0bc98cd01b46691ae9fdab162326e3c65adb74e6 100644 (file)
@@ -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