re PR middle-end/50527 (inconsistent vla align)

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
This commit is contained in:
Tom de Vries 2011-10-07 12:49:49 +00:00 committed by Tom de Vries
parent 764a2546bb
commit 13e49da934
15 changed files with 93 additions and 30 deletions

View 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.

View 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:

View 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)

View 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);

View 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);

View 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));

View 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);

View 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:

View 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;

View 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;

View 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

View 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)

View 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))

View 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,

View 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));