re PR middle-end/50527 (inconsistent vla align)
authorTom de Vries <tom@codesourcery.com>
Fri, 7 Oct 2011 12:49:49 +0000 (12:49 +0000)
committerTom de Vries <vries@gcc.gnu.org>
Fri, 7 Oct 2011 12:49:49 +0000 (12:49 +0000)
2011-10-07  Tom de Vries  <tom@codesourcery.com>

PR middle-end/50527
* tree.c (build_common_builtin_nodes): Add local_define_builtin for
BUILT_IN_ALLOCA_WITH_ALIGN.  Mark that BUILT_IN_ALLOCA_WITH_ALIGN can
throw.
* builtins.c (expand_builtin_alloca): Handle BUILT_IN_ALLOCA_WITH_ALIGN
arglist.  Set align for BUILT_IN_ALLOCA_WITH_ALIGN.
(expand_builtin): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
(is_inexpensive_builtin): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
* tree-ssa-ccp.c (evaluate_stmt): Set align for
BUILT_IN_ALLOCA_WITH_ALIGN.
(fold_builtin_alloca_for_var): Rename to ...
(fold_builtin_alloca_with_align): Set DECL_ALIGN from 2nd
BUILT_IN_ALLOCA_WITH_ALIGN argument.
(ccp_fold_stmt): Try folding BUILT_IN_ALLOCA_WITH_ALIGN using
fold_builtin_alloca_with_align.
(optimize_stack_restore): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
* builtins.def (BUILT_IN_ALLOCA_WITH_ALIGN): Declare using
DEF_BUILTIN_STUB.
* ipa-pure-const.c (special_builtin_state): Handle
BUILT_IN_ALLOCA_WITH_ALIGN.
* tree-ssa-alias.c (ref_maybe_used_by_call_p_1)
(call_may_clobber_ref_p_1): Same.
* function.c (gimplify_parameters): Lower vla to
BUILT_IN_ALLOCA_WITH_ALIGN.
* gimplify.c (gimplify_vla_decl): Same.
* cfgexpand.c (expand_call_stmt): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
* tree-mudflap.c (mf_xform_statements): Same.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary)
(mark_all_reaching_defs_necessary_1, propagate_necessity): Same.
* varasm.c (incorporeal_function_p): Same.
* tree-object-size.c (alloc_object_size): Same.
* gimple.c (gimple_build_call_from_tree): Same.

From-SVN: r179655

15 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/builtins.def
gcc/cfgexpand.c
gcc/function.c
gcc/gimple.c
gcc/gimplify.c
gcc/ipa-pure-const.c
gcc/tree-mudflap.c
gcc/tree-object-size.c
gcc/tree-ssa-alias.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-dce.c
gcc/tree.c
gcc/varasm.c

index c5722341e198e9198842aface96901e5d29f5fb1..7658511a533651677a09b15c764643aa9bd248f0 100644 (file)
@@ -1,3 +1,21 @@
+2011-10-07  Tom de Vries  <tom@codesourcery.com>
+
+       PR middle-end/50527
+       * tree.c (build_common_builtin_nodes): Add local_define_builtin for
+       * builtins.c (expand_builtin_alloca): Handle BUILT_IN_ALLOCA_WITH_ALIGN
+       * tree-ssa-ccp.c (evaluate_stmt): Set align for
+       * builtins.def (BUILT_IN_ALLOCA_WITH_ALIGN): Declare using
+       * ipa-pure-const.c (special_builtin_state): Handle
+       * tree-ssa-alias.c (ref_maybe_used_by_call_p_1)
+       * function.c (gimplify_parameters): Lower vla to
+       * gimplify.c (gimplify_vla_decl): Same.
+       * cfgexpand.c (expand_call_stmt): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
+       * tree-mudflap.c (mf_xform_statements): Same.
+       * tree-ssa-dce.c (mark_stmt_if_obviously_necessary)
+       * varasm.c (incorporeal_function_p): Same.
+       * tree-object-size.c (alloc_object_size): Same.
+       * gimple.c (gimple_build_call_from_tree): Same.
+
 2011-10-07  Bernd Schmidt  <bernds@codesourcery.com>
 
        * function.c (frame_required_for_rtx): Remove function.
index 8476b0e6b8b7d254d85f6c43b9ccba6b964d44b9..bf1766a56a61a1a0064d6d92349fa8d5b189dc13 100644 (file)
@@ -4516,20 +4516,33 @@ expand_builtin_alloca (tree exp, bool cannot_accumulate)
 {
   rtx op0;
   rtx result;
+  bool valid_arglist;
+  unsigned int align;
+  bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp))
+                           == BUILT_IN_ALLOCA_WITH_ALIGN);
 
   /* Emit normal call if marked not-inlineable.  */
   if (CALL_CANNOT_INLINE_P (exp))
     return NULL_RTX;
 
-  if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
+  valid_arglist
+    = (alloca_with_align
+       ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
+       : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
+
+  if (!valid_arglist)
     return NULL_RTX;
 
   /* Compute the argument.  */
   op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
 
+  /* Compute the alignment.  */
+  align = (alloca_with_align
+          ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1))
+          : BIGGEST_ALIGNMENT);
+
   /* Allocate the desired space.  */
-  result = allocate_dynamic_stack_space (op0, 0, BIGGEST_ALIGNMENT,
-                                        cannot_accumulate);
+  result = allocate_dynamic_stack_space (op0, 0, align, cannot_accumulate);
   result = convert_memory_address (ptr_mode, result);
 
   return result;
@@ -5304,6 +5317,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       && !called_as_built_in (fndecl)
       && DECL_ASSEMBLER_NAME_SET_P (fndecl)
       && fcode != BUILT_IN_ALLOCA
+      && fcode != BUILT_IN_ALLOCA_WITH_ALIGN
       && fcode != BUILT_IN_FREE)
     return expand_call (exp, target, ignore);
 
@@ -5559,6 +5573,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
 
     case BUILT_IN_ALLOCA:
+    case BUILT_IN_ALLOCA_WITH_ALIGN:
       /* 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));
@@ -13568,6 +13583,7 @@ is_inexpensive_builtin (tree decl)
       {
       case BUILT_IN_ABS:
       case BUILT_IN_ALLOCA:
+      case BUILT_IN_ALLOCA_WITH_ALIGN:
       case BUILT_IN_BSWAP32:
       case BUILT_IN_BSWAP64:
       case BUILT_IN_CLZ:
index 424f0f1a0853366277367a8606c7f65fa9d6becc..59c082de983ebe05fbd9e50d0f098f187fd0570a 100644 (file)
@@ -738,6 +738,7 @@ DEF_BUILTIN_STUB (BUILT_IN_SETJMP_RECEIVER, "__builtin_setjmp_receiver")
 /* Implementing variable sized local variables.  */
 DEF_BUILTIN_STUB (BUILT_IN_STACK_SAVE, "__builtin_stack_save")
 DEF_BUILTIN_STUB (BUILT_IN_STACK_RESTORE, "__builtin_stack_restore")
+DEF_BUILTIN_STUB (BUILT_IN_ALLOCA_WITH_ALIGN, "__builtin_alloca_with_align")
 
 /* Object size checking builtins.  */
 DEF_GCC_BUILTIN               (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
index 1495633840bb11f73d497c8e28d36da9698f9826..4089b40dc415c847a9c445cf44e9ae695312a0d3 100644 (file)
@@ -1858,7 +1858,8 @@ expand_call_stmt (gimple 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)
+      && (DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA
+         || DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA_WITH_ALIGN))
     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);
index 85a0bb7d2526a2a903c55b08433ad6b944beb001..ae9b535550de744c95f64cf5e8c2890ae2c3c1a2 100644 (file)
@@ -3635,8 +3635,10 @@ gimplify_parameters (void)
                  DECL_IGNORED_P (addr) = 0;
                  local = build_fold_indirect_ref (addr);
 
-                 t = built_in_decls[BUILT_IN_ALLOCA];
-                 t = build_call_expr (t, 1, DECL_SIZE_UNIT (parm));
+                 t = built_in_decls[BUILT_IN_ALLOCA_WITH_ALIGN];
+                 t = build_call_expr (t, 1, DECL_SIZE_UNIT (parm),
+                                      size_int (DECL_ALIGN (parm)));
+
                  /* The call has been built for a variable-sized object.  */
                  CALL_ALLOCA_FOR_VAR_P (t) = 1;
                  t = fold_convert (ptr_type, t);
index e4dfd467d755a3572ace88d4d53cfc7c0ec47e83..2c655cd3ef61babb7ef8571f179986e7422abdee 100644 (file)
@@ -374,7 +374,8 @@ gimple_build_call_from_tree (tree 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)
+      && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA
+         || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA_WITH_ALIGN))
     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));
index 4c15f3a7c456745347ec45251632b6c25e3ee147..90de915852f8e5415911fa240575b5de9ff3546b 100644 (file)
@@ -1329,8 +1329,9 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
   SET_DECL_VALUE_EXPR (decl, t);
   DECL_HAS_VALUE_EXPR_P (decl) = 1;
 
-  t = built_in_decls[BUILT_IN_ALLOCA];
-  t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl));
+  t = built_in_decls[BUILT_IN_ALLOCA_WITH_ALIGN];
+  t = build_call_expr (t, 2, DECL_SIZE_UNIT (decl),
+                      size_int (DECL_ALIGN (decl)));
   /* The call has been built for a variable-sized object.  */
   CALL_ALLOCA_FOR_VAR_P (t) = 1;
   t = fold_convert (ptr_type, t);
index 36212cda67b5708107ae66e577cc633a8e2eddd0..82e24cf5a015a2dc426839c01caa3a2ea9bc559d 100644 (file)
@@ -437,6 +437,7 @@ special_builtin_state (enum pure_const_state_e *state, bool *looping,
        case BUILT_IN_RETURN:
        case BUILT_IN_UNREACHABLE:
        case BUILT_IN_ALLOCA:
+       case BUILT_IN_ALLOCA_WITH_ALIGN:
        case BUILT_IN_STACK_SAVE:
        case BUILT_IN_STACK_RESTORE:
        case BUILT_IN_EH_POINTER:
index 102f2ff30759a7803a4f8ac25206f6536f0f876d..9479aebfb342153eec60ec74f9d37b6d556331f9 100644 (file)
@@ -973,7 +973,9 @@ mf_xform_statements (void)
             case GIMPLE_CALL:
               {
                 tree fndecl = gimple_call_fndecl (s);
-                if (fndecl && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA))
+                if (fndecl && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA
+                              || (DECL_FUNCTION_CODE (fndecl)
+                                  == BUILT_IN_ALLOCA_WITH_ALIGN)))
                   gimple_call_set_cannot_inline (s, true);
               }
               break;
index 851bba914fab1814c2073d360988bd8271fe836e..2998fb59da05edf6f56f64b2a11c24c5ee2904ea 100644 (file)
@@ -411,6 +411,7 @@ alloc_object_size (const_gimple call, int object_size_type)
        /* fall through */
       case BUILT_IN_MALLOC:
       case BUILT_IN_ALLOCA:
+      case BUILT_IN_ALLOCA_WITH_ALIGN:
        arg1 = 0;
       default:
        break;
index a89094467f1ba58672942013d8e0281ea3a30773..506e778ee062dd3e185e6cc46e4aa39aa41a9b44 100644 (file)
@@ -1260,6 +1260,7 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
        case BUILT_IN_MALLOC:
        case BUILT_IN_CALLOC:
        case BUILT_IN_ALLOCA:
+       case BUILT_IN_ALLOCA_WITH_ALIGN:
        case BUILT_IN_STACK_SAVE:
        case BUILT_IN_STACK_RESTORE:
        case BUILT_IN_MEMSET:
@@ -1554,6 +1555,7 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
          return false;
        case BUILT_IN_STACK_SAVE:
        case BUILT_IN_ALLOCA:
+       case BUILT_IN_ALLOCA_WITH_ALIGN:
        case BUILT_IN_ASSUME_ALIGNED:
          return false;
        /* Freeing memory kills the pointed-to memory.  More importantly
index b5774040e320b255cc434e797a244c0fd93537b2..e207e232e01728f2fb9c8c2bb2465a8dd9b8396a 100644 (file)
@@ -1492,6 +1492,7 @@ evaluate_stmt (gimple stmt)
   tree simplified = NULL_TREE;
   ccp_lattice_t likelyvalue = likely_value (stmt);
   bool is_constant = false;
+  unsigned int align;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -1632,10 +1633,14 @@ evaluate_stmt (gimple stmt)
              break;
 
            case BUILT_IN_ALLOCA:
+           case BUILT_IN_ALLOCA_WITH_ALIGN:
+             align = (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA_WITH_ALIGN
+                      ? TREE_INT_CST_LOW (gimple_call_arg (stmt, 1))
+                      : BIGGEST_ALIGNMENT);
              val.lattice_val = CONSTANT;
              val.value = build_int_cst (TREE_TYPE (gimple_get_lhs (stmt)), 0);
              val.mask = shwi_to_double_int
-                          (~(((HOST_WIDE_INT) BIGGEST_ALIGNMENT)
+                          (~(((HOST_WIDE_INT) align)
                              / BITS_PER_UNIT - 1));
              break;
 
@@ -1685,15 +1690,15 @@ evaluate_stmt (gimple stmt)
   return val;
 }
 
-/* Detects a vla-related alloca with a constant argument.  Declares fixed-size
-   array and return the address, if found, otherwise returns NULL_TREE.  */
+/* Detects a __builtin_alloca_with_align with constant size argument.  Declares
+   fixed-size array and returns the address, if found, otherwise returns
+   NULL_TREE.  */
 
 static tree
-fold_builtin_alloca_for_var (gimple stmt)
+fold_builtin_alloca_with_align (gimple stmt)
 {
   unsigned HOST_WIDE_INT size, threshold, n_elem;
   tree lhs, arg, block, var, elem_type, array_type;
-  unsigned int align;
 
   /* Get lhs.  */
   lhs = gimple_call_lhs (stmt);
@@ -1709,10 +1714,10 @@ fold_builtin_alloca_for_var (gimple stmt)
 
   size = TREE_INT_CST_LOW (arg);
 
-  /* Heuristic: don't fold large vlas.  */
+  /* Heuristic: don't fold large allocas.  */
   threshold = (unsigned HOST_WIDE_INT)PARAM_VALUE (PARAM_LARGE_STACK_FRAME);
-  /* In case a vla is declared at function scope, it has the same lifetime as a
-     declared array, so we allow a larger size.  */
+  /* In case the alloca is located at function entry, it has the same lifetime
+     as a declared array, so we allow a larger size.  */
   block = gimple_block (stmt);
   if (!(cfun->after_inlining
         && TREE_CODE (BLOCK_SUPERCONTEXT (block)) == FUNCTION_DECL))
@@ -1723,12 +1728,9 @@ fold_builtin_alloca_for_var (gimple stmt)
   /* Declare array.  */
   elem_type = build_nonstandard_integer_type (BITS_PER_UNIT, 1);
   n_elem = size * 8 / BITS_PER_UNIT;
-  align = MIN (size * 8, BIGGEST_ALIGNMENT);
-  if (align < BITS_PER_UNIT)
-    align = BITS_PER_UNIT;
   array_type = build_array_type_nelts (elem_type, n_elem);
   var = create_tmp_var (array_type, NULL);
-  DECL_ALIGN (var) = align;
+  DECL_ALIGN (var) = TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
   {
     struct ptr_info_def *pi = SSA_NAME_PTR_INFO (lhs);
     if (pi != NULL && !pi->pt.anything)
@@ -1813,12 +1815,12 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
        if (gimple_call_internal_p (stmt))
          return false;
 
-        /* The heuristic of fold_builtin_alloca_for_var differs before and after
-           inlining, so we don't require the arg to be changed into a constant
-           for folding, but just to be constant.  */
-        if (gimple_call_alloca_for_var_p (stmt))
+        /* The heuristic of fold_builtin_alloca_with_align differs before and
+          after inlining, so we don't require the arg to be changed into a
+          constant for folding, but just to be constant.  */
+        if (gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
           {
-            tree new_rhs = fold_builtin_alloca_for_var (stmt);
+            tree new_rhs = fold_builtin_alloca_with_align (stmt);
             if (new_rhs)
              {
                bool res = update_call_from_tree (gsi, new_rhs);
@@ -2093,7 +2095,8 @@ optimize_stack_restore (gimple_stmt_iterator i)
       if (!callee
          || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
          /* All regular builtins are ok, just obviously not alloca.  */
-         || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA)
+         || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
+         || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA_WITH_ALIGN)
        return NULL_TREE;
 
       if (DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE)
index f225030de681ac7d1622995e97189db15ce710b4..b84b6f9a99e64e838a1c183a7c4db8463860f86f 100644 (file)
@@ -308,6 +308,7 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
            case BUILT_IN_MALLOC:
            case BUILT_IN_CALLOC:
            case BUILT_IN_ALLOCA:
+           case BUILT_IN_ALLOCA_WITH_ALIGN:
              return;
 
            default:;
@@ -639,6 +640,7 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED,
          case BUILT_IN_MALLOC:
          case BUILT_IN_CALLOC:
          case BUILT_IN_ALLOCA:
+         case BUILT_IN_ALLOCA_WITH_ALIGN:
          case BUILT_IN_FREE:
            return false;
 
@@ -890,6 +892,8 @@ propagate_necessity (struct edge_list *el)
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_FREE
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_VA_END
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
+                     || (DECL_FUNCTION_CODE (callee)
+                         == BUILT_IN_ALLOCA_WITH_ALIGN)
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_SAVE
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_ASSUME_ALIGNED))
index 3e9750383e19da4cf3f281e26a4e3874dc7878ad..03edb9c03246c616410b667e3852202a6b8df99a 100644 (file)
@@ -9483,9 +9483,18 @@ build_common_builtin_nodes (void)
                            "alloca", ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
     }
 
+  ftype = build_function_type_list (ptr_type_node, size_type_node,
+                                   size_type_node, NULL_TREE);
+  local_define_builtin ("__builtin_alloca_with_align", ftype,
+                       BUILT_IN_ALLOCA_WITH_ALIGN, "alloca",
+                       ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
+
   /* If we're checking the stack, `alloca' can throw.  */
   if (flag_stack_check)
-    TREE_NOTHROW (built_in_decls[BUILT_IN_ALLOCA]) = 0;
+    {
+      TREE_NOTHROW (built_in_decls[BUILT_IN_ALLOCA]) = 0;
+      TREE_NOTHROW (built_in_decls[BUILT_IN_ALLOCA_WITH_ALIGN]) = 0;
+    }
 
   ftype = build_function_type_list (void_type_node,
                                    ptr_type_node, ptr_type_node,
index 9b4dfad5cbb35dc162f315ee9954b48e37fb957e..94e31115d1e3e2e2da4741387cea76e587f81ffd 100644 (file)
@@ -2104,7 +2104,8 @@ incorporeal_function_p (tree decl)
       const char *name;
 
       if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
-         && DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA)
+         && (DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA
+             || DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA_WITH_ALIGN))
        return true;
 
       name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));