summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorvries <vries@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-07 12:49:49 +0000
committervries <vries@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-07 12:49:49 +0000
commit581bf1c292d1521c3a805c39e6dcca54a9a86b6d (patch)
tree274fa9d31e31f79687aa8785b52bbd7532b95632 /gcc
parentf8e6666e4580a0fc0942b746f9242a5ef66170a5 (diff)
downloadgcc-581bf1c292d1521c3a805c39e6dcca54a9a86b6d.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@179655 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/builtins.c22
-rw-r--r--gcc/builtins.def1
-rw-r--r--gcc/cfgexpand.c3
-rw-r--r--gcc/function.c6
-rw-r--r--gcc/gimple.c3
-rw-r--r--gcc/gimplify.c5
-rw-r--r--gcc/ipa-pure-const.c1
-rw-r--r--gcc/tree-mudflap.c4
-rw-r--r--gcc/tree-object-size.c1
-rw-r--r--gcc/tree-ssa-alias.c2
-rw-r--r--gcc/tree-ssa-ccp.c39
-rw-r--r--gcc/tree-ssa-dce.c4
-rw-r--r--gcc/tree.c11
-rw-r--r--gcc/varasm.c3
15 files changed, 93 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c5722341e19..7658511a533 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 8476b0e6b8b..bf1766a56a6 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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:
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 424f0f1a085..59c082de983 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -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)
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 1495633840b..4089b40dc41 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -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);
diff --git a/gcc/function.c b/gcc/function.c
index 85a0bb7d252..ae9b535550d 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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);
diff --git a/gcc/gimple.c b/gcc/gimple.c
index e4dfd467d75..2c655cd3ef6 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -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));
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4c15f3a7c45..90de915852f 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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);
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 36212cda67b..82e24cf5a01 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -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:
diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c
index 102f2ff3075..9479aebfb34 100644
--- a/gcc/tree-mudflap.c
+++ b/gcc/tree-mudflap.c
@@ -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;
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 851bba914fa..2998fb59da0 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -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;
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index a89094467f1..506e778ee06 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -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
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index b5774040e32..e207e232e01 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -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)
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index f225030de68..b84b6f9a99e 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -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))
diff --git a/gcc/tree.c b/gcc/tree.c
index 3e9750383e1..03edb9c0324 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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,
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 9b4dfad5cbb..94e31115d1e 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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));