Hi! As the following testcase shows, for thunks the expansion code sometimes requires that arguments with gimple reg type aren't addressable, thunk needs to be simple passing of arguments directly to another call, not having extra statements in between that.
In particular, for pass_by_reference arguments calls.c has if call_from_thunk_p: /* We may have turned the parameter value into an SSA name. Go back to the original parameter so we can take the address. */ if (TREE_CODE (args[i].tree_value) == SSA_NAME) { gcc_assert (SSA_NAME_IS_DEFAULT_DEF (args[i].tree_value)); args[i].tree_value = SSA_NAME_VAR (args[i].tree_value); gcc_assert (TREE_CODE (args[i].tree_value) == PARM_DECL); } which is not the case if the PARM_DECL is TREE_ADDRESSABLE, then the def stmt of the SSA_NAME is an assignment which loads the PARM_DECL value from "memory". TREE_ADDRESSABLE on the arguments is copied from the ctor from which it is cloned (and which will be called by the thunk). In this case the argument needs to be addressable because vector[idx] folding takes address of vector. In the thunk itself that doesn't matter though, it just passes the argument to another function, so the following patch clears the TREE_ADDRESSABLE bit there. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2019-02-05 Jakub Jelinek <ja...@redhat.com> PR c++/89187 * optimize.c (maybe_thunk_body): Clear TREE_ADDRESSABLE on non-aggregate PARM_DECLs of the thunk. * g++.dg/opt/pr89187.C: New test. --- gcc/cp/optimize.c.jj 2019-01-21 23:32:43.000000000 +0100 +++ gcc/cp/optimize.c 2019-02-04 16:40:21.354179933 +0100 @@ -417,6 +417,12 @@ maybe_thunk_body (tree fn, bool force) gcc_assert (clone_parm); DECL_ABSTRACT_ORIGIN (clone_parm) = NULL; args[parmno] = clone_parm; + /* Clear TREE_ADDRESSABLE on arguments with non-aggregate + types, the thunk will not take addresses of those + arguments, will just pass them through to another + call. */ + if (!AGGREGATE_TYPE_P (TREE_TYPE (clone_parm))) + TREE_ADDRESSABLE (clone_parm) = 0; clone_parm = TREE_CHAIN (clone_parm); } if (fn_parm_typelist) --- gcc/testsuite/g++.dg/opt/pr89187.C.jj 2019-02-04 17:34:13.973847193 +0100 +++ gcc/testsuite/g++.dg/opt/pr89187.C 2019-02-04 17:34:41.191396316 +0100 @@ -0,0 +1,23 @@ +// PR c++/89187 +// { dg-do compile { target c++11 } } +// { dg-options "-Os -fno-tree-ccp -fno-tree-sra -fno-inline" } + +template <typename T, int N> struct A { + typedef T __attribute__((vector_size (N))) type; +}; +template <typename T, int N> using B = typename A<T, N>::type; +template <typename T> using C = B<T, 4>; +struct D { + D (C<int> x) : d{x[3]} {} + D foo () { return d; } + C<int> d; +}; +extern D d; +struct { D bar () { return d; } } l; +struct E { void baz () const; }; + +void +E::baz () const +{ + l.bar ().foo (); +} Jakub