The following fixes handling of __builtin_va_start handling and
implements .VA_ARG handling in PTA constraint generation to
improve precision around variadic calls.  I've added a testcase
for IPA PTA involving an indirect variadic call verifying precision.

The pr99679-1.C no longer emits an expected error that was triggered
by PTA calling aggregate_value_p on the .VA_ARG call which we no
longer do.

Bootstrapped and tested on x86_64-unknown-linux-gnu, LTO bootstrapped
with IPA PTA enabled and no testsuite differences when testing with
IPA PTA enabled.

Pushed.

        * gimple-ssa-pta-constraints.cc (find_func_aliases_for_builtin_call):
        Correctly use SCALAR rhs from the variadic argument part of
        the function info or from NONLOCAL in case of intra-PTA.
        (find_func_aliases_for_call): Handle .VA_ARG.

        * gcc.dg/ipa/ipa-pta-20.c: New testcase.
        * g++.dg/target/pr99679-1.C: Remove expected error.
        * g++.dg/target/pr99679-2.C: Likewise.
---
 gcc/gimple-ssa-pta-constraints.cc         | 19 +++++++++++--
 gcc/testsuite/g++.target/i386/pr99679-1.C |  2 +-
 gcc/testsuite/g++.target/i386/pr99679-2.C |  2 +-
 gcc/testsuite/gcc.dg/ipa/ipa-pta-20.c     | 33 +++++++++++++++++++++++
 4 files changed, 52 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-pta-20.c

diff --git a/gcc/gimple-ssa-pta-constraints.cc 
b/gcc/gimple-ssa-pta-constraints.cc
index dec3b2f6f14..a377b891d80 100644
--- a/gcc/gimple-ssa-pta-constraints.cc
+++ b/gcc/gimple-ssa-pta-constraints.cc
@@ -2010,12 +2010,12 @@ find_func_aliases_for_builtin_call (struct function 
*fn, gcall *t)
            {
              fi = lookup_vi_for_tree (fn->decl);
              rhs = get_function_part_constraint (fi, ~0);
-             rhs.type = ADDRESSOF;
+             rhs.type = SCALAR;
            }
          else
            {
              rhs.var = nonlocal_id;
-             rhs.type = ADDRESSOF;
+             rhs.type = SCALAR;
              rhs.offset = 0;
            }
          FOR_EACH_VEC_ELT (lhsc, i, lhsp)
@@ -2108,6 +2108,21 @@ find_func_aliases_for_call (struct function *fn, gcall 
*t)
       && find_func_aliases_for_builtin_call (fn, t))
     return;
 
+  if (gimple_call_internal_p (t, IFN_VA_ARG)
+      && gimple_call_lhs (t))
+    {
+      tree valist = gimple_call_arg (t, 0);
+      auto_vec<ce_s, 1> rhsc, lhsc;
+      get_constraint_for_rhs (valist, &rhsc);
+      do_deref (&rhsc);
+      get_constraint_for (gimple_call_lhs (t), &lhsc);
+      process_all_all_constraints (lhsc, rhsc);
+      /* va_list is used and clobbered.  */
+      make_constraint_to (get_call_use_vi (t)->id, valist);
+      make_constraint_to (get_call_clobber_vi (t)->id, valist);
+      return;
+    }
+
   if (gimple_call_internal_p (t, IFN_DEFERRED_INIT))
     return;
 
diff --git a/gcc/testsuite/g++.target/i386/pr99679-1.C 
b/gcc/testsuite/g++.target/i386/pr99679-1.C
index 36640a4e0a1..d3cd45b5d55 100644
--- a/gcc/testsuite/g++.target/i386/pr99679-1.C
+++ b/gcc/testsuite/g++.target/i386/pr99679-1.C
@@ -14,4 +14,4 @@ foo (int x, ...)
   ld = va_arg (ap, long double);
   if (ld)
     abort ();
-} // { dg-error "x87 register return with x87 disabled" "" { target { ! ia32 } 
} }
+}
diff --git a/gcc/testsuite/g++.target/i386/pr99679-2.C 
b/gcc/testsuite/g++.target/i386/pr99679-2.C
index cbd3c4958db..2773b29470a 100644
--- a/gcc/testsuite/g++.target/i386/pr99679-2.C
+++ b/gcc/testsuite/g++.target/i386/pr99679-2.C
@@ -14,4 +14,4 @@ foo (int x, ...)
   ld = va_arg (ap, double); // { dg-error "SSE register argument with SSE 
disabled" "" { target { ! ia32 } } }
   if (ld)
     abort ();
-} // { dg-error "SSE register return with SSE disabled" "" { target { ! ia32 } 
} }
+}
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-pta-20.c 
b/gcc/testsuite/gcc.dg/ipa/ipa-pta-20.c
new file mode 100644
index 00000000000..694a7c3b53a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-pta-20.c
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fipa-pta -fdump-ipa-pta2-details" } */
+
+#include <stdarg.h>
+
+static int __attribute__((noinline, noclone)) q (int n, ...)
+{
+  va_list va;
+  va_start (va, n);
+  int *a = va_arg (va, int *);
+  int *b = va_arg (va, int *);
+  va_end (va);
+  return *a + *b;
+}
+
+static int __attribute__((noinline, noclone)) foo (int (*p)(int, ...))
+{
+  int i = 1, j = 3;
+  return p(2, &i, &j);
+}
+
+int main()
+{
+  if (foo (q) != 4)
+    __builtin_abort ();
+  return 0;
+}
+
+/* Verify we properly handle variadic arguments for indirect calls and
+   .VA_ARG properly accesses only the variadic part.  */
+
+/* { dg-final { scan-ipa-dump "a_\[0-9\]\+ = { i j }" "pta2" } } */
+/* { dg-final { scan-ipa-dump "b_\[0-9\]\+ = { i j }" "pta2" } } */
-- 
2.51.0

Reply via email to