Don't take address of ap unless necessary

2015-05-12  Tom de Vries  <tom@codesourcery.com>

	PR tree-optimization/66010
	* gimplify.c (gimplify_modify_expr): Handle new do_deref argument of
	ifn_va_arg.
	* gimplify.h (gimplify_va_arg_internal): Remove loc parameter.
	(gimplify_va_arg_internal): Remove loc parameter.  Assert no array-typed
	va_lists are passed, and remove corresponding handling.
	(gimplify_va_arg_expr): Only take address of ap if necessary.  Add
	do_deref argument to ifn_va_arg.
	* tree-stdarg.c (expand_ifn_va_arg_1): Handle new do_deref argument of
	ifn_va_arg.

	* c-common.c (build_va_arg): Don't mark ap addressable unless necessary.

	* gcc.dg/tree-ssa/stdarg-2.c: Undo scan xfails for f15.

From-SVN: r223054
This commit is contained in:
Tom de Vries 2015-05-12 09:46:47 +00:00 committed by Tom de Vries
parent fed8bd87d5
commit c7b38fd545
8 changed files with 91 additions and 38 deletions

View File

@ -1,3 +1,16 @@
2015-05-12 Tom de Vries <tom@codesourcery.com>
PR tree-optimization/66010
* gimplify.c (gimplify_modify_expr): Handle new do_deref argument of
ifn_va_arg.
* gimplify.h (gimplify_va_arg_internal): Remove loc parameter.
(gimplify_va_arg_internal): Remove loc parameter. Assert no array-typed
va_lists are passed, and remove corresponding handling.
(gimplify_va_arg_expr): Only take address of ap if necessary. Add
do_deref argument to ifn_va_arg.
* tree-stdarg.c (expand_ifn_va_arg_1): Handle new do_deref argument of
ifn_va_arg.
2015-05-12 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR target/65955

View File

@ -1,3 +1,8 @@
2015-05-12 Tom de Vries <tom@codesourcery.com>
PR tree-optimization/66010
* c-common.c (build_va_arg): Don't mark ap addressable unless necessary.
2015-05-09 Jason Merrill <jason@redhat.com>
* c-opts.c (c_common_post_options): Also clear

View File

@ -5918,9 +5918,25 @@ set_compound_literal_name (tree decl)
tree
build_va_arg (location_t loc, tree expr, tree type)
{
/* In gimplify_va_arg_expr we take the address of the ap argument, mark it
addressable now. */
mark_addressable (expr);
tree va_type = TREE_TYPE (expr);
tree canon_va_type = (va_type == error_mark_node
? NULL_TREE
: targetm.canonical_va_list_type (va_type));
if (canon_va_type != NULL)
{
/* When the va_arg ap argument is a parm decl with declared type va_list,
and the va_list type is an array, then grokdeclarator changes the type
of the parm decl to the corresponding pointer type. We know that that
pointer is constant, so there's no need to modify it, so there's no
need to pass it around using an address operator, so there's no need to
mark it addressable. */
if (!(TREE_CODE (canon_va_type) == ARRAY_TYPE
&& TREE_CODE (va_type) != ARRAY_TYPE))
/* In gimplify_va_arg_expr we take the address of the ap argument, mark
it addressable now. */
mark_addressable (expr);
}
expr = build1 (VA_ARG_EXPR, type, expr);
SET_EXPR_LOCATION (expr, loc);

View File

@ -4658,9 +4658,11 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
tree type = TREE_TYPE (call);
tree ap = CALL_EXPR_ARG (call, 0);
tree tag = CALL_EXPR_ARG (call, 1);
tree do_deref = CALL_EXPR_ARG (call, 2);
tree newcall = build_call_expr_internal_loc (EXPR_LOCATION (call),
IFN_VA_ARG, type, 3, ap,
tag, vlasize);
IFN_VA_ARG, type, 4, ap,
tag, do_deref,
vlasize);
tree *call_p = &(TREE_OPERAND (*from_p, 0));
*call_p = newcall;
}
@ -9304,8 +9306,8 @@ dummy_object (tree type)
and TYPE. */
tree
gimplify_va_arg_internal (tree valist, tree type, location_t loc,
gimple_seq *pre_p, gimple_seq *post_p)
gimplify_va_arg_internal (tree valist, tree type, gimple_seq *pre_p,
gimple_seq *post_p)
{
tree have_va_type = TREE_TYPE (valist);
tree cano_type = targetm.canonical_va_list_type (have_va_type);
@ -9317,17 +9319,7 @@ gimplify_va_arg_internal (tree valist, tree type, location_t loc,
from multiple evaluations. */
if (TREE_CODE (have_va_type) == ARRAY_TYPE)
{
/* For this case, the backends will be expecting a pointer to
TREE_TYPE (abi), but it's possible we've
actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
So fix it. */
if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
{
tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
valist = fold_convert_loc (loc, p1,
build_fold_addr_expr_loc (loc, valist));
}
gcc_assert (TREE_CODE (TREE_TYPE (valist)) != ARRAY_TYPE);
gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
}
else
@ -9346,7 +9338,7 @@ gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
tree promoted_type, have_va_type;
tree valist = TREE_OPERAND (*expr_p, 0);
tree type = TREE_TYPE (*expr_p);
tree t, tag, ap;
tree t, tag, ap, do_deref;
location_t loc = EXPR_LOCATION (*expr_p);
/* Verify that valist is of the proper type. */
@ -9400,9 +9392,34 @@ gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
}
/* Transform a VA_ARG_EXPR into an VA_ARG internal function. */
ap = build_fold_addr_expr_loc (loc, valist);
if (TREE_CODE (have_va_type) == ARRAY_TYPE)
{
if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
{
/* Take the address, but don't strip it. Gimplify_va_arg_internal
expects a pointer to array element type. */
ap = build_fold_addr_expr_loc (loc, valist);
do_deref = integer_zero_node;
}
else
{
/* Don't take the address. Gimplify_va_arg_internal expects a pointer
to array element type, and we already have that.
See also comment in build_va_arg. */
ap = valist;
do_deref = integer_zero_node;
}
}
else
{
/* No special handling. Take the address here, note that it needs to be
stripped before calling gimplify_va_arg_internal. */
ap = build_fold_addr_expr_loc (loc, valist);
do_deref = integer_one_node;
}
tag = build_int_cst (build_pointer_type (type), 0);
*expr_p = build_call_expr_internal_loc (loc, IFN_VA_ARG, type, 2, ap, tag);
*expr_p = build_call_expr_internal_loc (loc, IFN_VA_ARG, type, 3, ap, tag,
do_deref);
/* Clear the tentatively set PROP_gimple_lva, to indicate that IFN_VA_ARG
needs to be expanded. */

View File

@ -82,8 +82,7 @@ extern void gimplify_function_tree (tree);
extern enum gimplify_status gimplify_va_arg_expr (tree *, gimple_seq *,
gimple_seq *);
gimple gimplify_assign (tree, tree, gimple_seq *);
extern tree gimplify_va_arg_internal (tree, tree, location_t, gimple_seq *,
gimple_seq *);
extern tree gimplify_va_arg_internal (tree, tree, gimple_seq *, gimple_seq *);
/* Return true if gimplify_one_sizepos doesn't need to gimplify
expr (when in TYPE_SIZE{,_UNIT} and similar type/decl size/bitsize

View File

@ -1,3 +1,8 @@
2015-05-12 Tom de Vries <tom@codesourcery.com>
PR tree-optimization/66010
* gcc.dg/tree-ssa/stdarg-2.c: Undo scan xfails for f15.
2015-05-12 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/65133

View File

@ -288,14 +288,9 @@ f15 (int i, ...)
f15_1 (ap);
va_end (ap);
}
/* Following three dg-finals are marked as xfail due to PR66010/PR66013. */
/* Was: { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } }. */
/* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { xfail *-*-* } } } */
/* Was: { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } }. */
/* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { xfail *-*-* } } } */
/* Was: { target s390*-*-linux* }. */
/* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save 1 GPR units and 2 FPR units" "stdarg" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } } } } */
/* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */
/* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save 1 GPR units and 2 FPR units" "stdarg" { target s390*-*-linux* } } } */
/* We may be able to improve upon this after fixing PR66010/PR66013. */
/* { dg-final { scan-tree-dump "f15: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */

View File

@ -1042,7 +1042,7 @@ expand_ifn_va_arg_1 (function *fun)
for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
{
gimple stmt = gsi_stmt (i);
tree ap, expr, lhs, type;
tree ap, expr, lhs, type, do_deref;
gimple_seq pre = NULL, post = NULL;
if (!gimple_call_ifn_va_arg_p (stmt))
@ -1052,24 +1052,27 @@ expand_ifn_va_arg_1 (function *fun)
type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 1)));
ap = gimple_call_arg (stmt, 0);
ap = build_fold_indirect_ref (ap);
do_deref = gimple_call_arg (stmt, 2);
if (do_deref == integer_one_node)
ap = build_fold_indirect_ref (ap);
push_gimplify_context (false);
expr = gimplify_va_arg_internal (ap, type, gimple_location (stmt),
&pre, &post);
expr = gimplify_va_arg_internal (ap, type, &pre, &post);
lhs = gimple_call_lhs (stmt);
if (lhs != NULL_TREE)
{
unsigned int nargs = gimple_call_num_args (stmt);
gcc_assert (useless_type_conversion_p (TREE_TYPE (lhs), type));
if (gimple_call_num_args (stmt) == 3)
if (nargs == 4)
{
/* We've transported the size of with WITH_SIZE_EXPR here as
the 3rd argument of the internal fn call. Now reinstate
the last argument of the internal fn call. Now reinstate
it. */
tree size = gimple_call_arg (stmt, 2);
tree size = gimple_call_arg (stmt, nargs - 1);
expr = build2 (WITH_SIZE_EXPR, TREE_TYPE (expr), expr, size);
}