diff options
author | Richard Biener <rguenther@suse.de> | 2018-08-17 08:48:58 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2018-08-17 08:48:58 +0000 |
commit | 36a072b429a9501946cb1fafdc9b1af7c574594d (patch) | |
tree | 40d0364573f5c9199c9b1b3c41447cf007c38188 | |
parent | bbcbd744b80c2cd40d7ef41d32dbd6ee7400701f (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr86505.c | 32 | ||||
-rw-r--r-- | gcc/tree-inline.c | 23 |
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 (©_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 (©_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 (©_gsi, new_stmt, GSI_NEW_STMT); + } } else if (call_stmt && id->call_stmt |