Don't take address of ap unless necessary
authorTom de Vries <tom@codesourcery.com>
Tue, 12 May 2015 09:46:47 +0000 (09:46 +0000)
committerTom de Vries <vries@gcc.gnu.org>
Tue, 12 May 2015 09:46:47 +0000 (09:46 +0000)
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

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/gimplify.c
gcc/gimplify.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c
gcc/tree-stdarg.c

index da57c95..d05b313 100644 (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
index 6169e52..8a19bc1 100644 (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
index 93b3060..2b3ee0c 100644 (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);
index 623d33d..322d0ba 100644 (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.  */
index bad8e0f..83bf525 100644 (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
index 37d1853..5d17561 100644 (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
index f09b5de..93a9e8d 100644 (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* } } } */
index 1356374..3bede7e 100644 (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);
              }