summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2018-08-17 08:48:58 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2018-08-17 08:48:58 +0000
commit36a072b429a9501946cb1fafdc9b1af7c574594d (patch)
tree40d0364573f5c9199c9b1b3c41447cf007c38188
parentbbcbd744b80c2cd40d7ef41d32dbd6ee7400701f (diff)
downloadgcc-36a072b429a9501946cb1fafdc9b1af7c574594d.tar.gz
re PR middle-end/86505 (__builtin_va_arg_pack_len() computes the number of arguments wrongly)
2018-08-17 Richard Biener <rguenther@suse.de> PR middle-end/86505 * tree-inline.c (copy_bb): When inlining __builtin_va_arg_pack_len () across a va-arg-pack using call adjust its return value accordingly. * gcc.dg/torture/pr86505.c: New testcase. From-SVN: r263613
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr86505.c32
-rw-r--r--gcc/tree-inline.c23
4 files changed, 60 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9af07fc3a2f..a6a8fffc422 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2018-08-17 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/86505
+ * tree-inline.c (copy_bb): When inlining __builtin_va_arg_pack_len ()
+ across a va-arg-pack using call adjust its return value accordingly.
+
2018-08-16 Martin Sebor <msebor@redhat.com>
PR tree-optimization/86853
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index abe919ebbb3..99e44a63a37 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-08-17 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/86505
+ * gcc.dg/torture/pr86505.c: New testcase.
+
2018-08-16 Martin Sebor <msebor@redhat.com>
PR tree-optimization/86853
diff --git a/gcc/testsuite/gcc.dg/torture/pr86505.c b/gcc/testsuite/gcc.dg/torture/pr86505.c
new file mode 100644
index 00000000000..db102d308e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr86505.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+
+static inline __attribute__(( __always_inline__)) int
+funA(unsigned int param, ...)
+{
+ return __builtin_va_arg_pack_len();
+}
+
+static inline __attribute__(( __always_inline__)) int
+funB(unsigned int param, ...)
+{
+ return funA(param, 2, 4, __builtin_va_arg_pack());
+}
+
+int
+testBuiltin(void)
+{
+ int rc = funB(0,1,2);
+ if (rc != 4)
+ return 1;
+ return 0;
+}
+
+int
+main()
+{
+ int rc = testBuiltin();
+ if (rc == 1)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 6a16ce546cb..21464d6e28f 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1940,8 +1940,7 @@ copy_bb (copy_body_data *id, basic_block bb,
&& id->call_stmt
&& (decl = gimple_call_fndecl (stmt))
&& DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_ARG_PACK_LEN
- && ! gimple_call_va_arg_pack_p (id->call_stmt))
+ && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_ARG_PACK_LEN)
{
/* __builtin_va_arg_pack_len () should be replaced by
the number of anonymous arguments. */
@@ -1952,10 +1951,22 @@ copy_bb (copy_body_data *id, basic_block bb,
for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p))
nargs--;
- count = build_int_cst (integer_type_node, nargs);
- new_stmt = gimple_build_assign (gimple_call_lhs (stmt), count);
- gsi_replace (&copy_gsi, new_stmt, false);
- stmt = new_stmt;
+ if (!gimple_call_va_arg_pack_p (id->call_stmt))
+ {
+ count = build_int_cst (integer_type_node, nargs);
+ new_stmt = gimple_build_assign (gimple_call_lhs (stmt), count);
+ gsi_replace (&copy_gsi, new_stmt, false);
+ stmt = new_stmt;
+ }
+ else if (nargs != 0)
+ {
+ tree newlhs = create_tmp_reg_or_ssa_name (integer_type_node);
+ count = build_int_cst (integer_type_node, nargs);
+ new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
+ PLUS_EXPR, newlhs, count);
+ gimple_call_set_lhs (stmt, newlhs);
+ gsi_insert_after (&copy_gsi, new_stmt, GSI_NEW_STMT);
+ }
}
else if (call_stmt
&& id->call_stmt