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:
parent
fed8bd87d5
commit
c7b38fd545
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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* } } } */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue