summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvries <vries@138bc75d-0d04-0410-961f-82ee72b054a4>2015-05-12 09:46:47 +0000
committervries <vries@138bc75d-0d04-0410-961f-82ee72b054a4>2015-05-12 09:46:47 +0000
commitc37be9ecc6e11ef0908ecdea3667a6a68c5ef7ca (patch)
treec10f8ac5291a1a6a12e7472c1ad1acd14764ffef
parent2b108e183a487a8e3ab7ca4002637137aac69818 (diff)
downloadgcc-c37be9ecc6e11ef0908ecdea3667a6a68c5ef7ca.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223054 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c-common.c22
-rw-r--r--gcc/gimplify.c53
-rw-r--r--gcc/gimplify.h3
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c11
-rw-r--r--gcc/tree-stdarg.c17
8 files changed, 91 insertions, 38 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index da57c959524..d05b31363f9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 6169e521eda..8a19bc119b2 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 93b30602078..2b3ee0c64cf 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -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);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 623d33dee77..322d0ba6ba1 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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. */
diff --git a/gcc/gimplify.h b/gcc/gimplify.h
index bad8e0ffd00..83bf52572bd 100644
--- a/gcc/gimplify.h
+++ b/gcc/gimplify.h
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 37d18532017..5d17561a3f9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c
index f09b5dea3e1..93a9e8da0d9 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c
@@ -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* } } } */
diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c
index 1356374ba14..3bede7efd6e 100644
--- a/gcc/tree-stdarg.c
+++ b/gcc/tree-stdarg.c
@@ -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);
}