On Mon, 28 Jan 2019, Jakub Jelinek wrote: > On Mon, Jan 28, 2019 at 01:18:43PM +0100, Richard Biener wrote: > > Eww :/ That means they are not semantically the same which IMHO is > > bad. If you make buf1 volatile does it trip over > > maybe_canonicalize_mem_ref_addr and miscompile? Or are we somehow > > If buf1 is volatile, then no clobbers are added for it for when it goes out > of scope: > if (VAR_P (t) > && !is_global_var (t) > && DECL_CONTEXT (t) == current_function_decl) > { > if (!DECL_HARD_REGISTER (t) > && !TREE_THIS_VOLATILE (t) > && !DECL_HAS_VALUE_EXPR_P (t) > /* Only care for variables that have to be in memory. Others > will be rewritten into SSA names, hence moved to the > top-level. */ > && !is_gimple_reg (t) > && flag_stack_reuse != SR_NONE) > { > tree clobber = build_clobber (TREE_TYPE (t)); > The clobbers from ctors and dtors are still there, but nothing folds them to > non-MEM_REF anyway: > volatile char buf2[128]; > volatile char buf1[128]; > > <bb 2> [local count: 1073741824]: > foo (&buf1); > MEM[(struct &)&buf1] ={v} {CLOBBER}; > memset (&MEM[(void *)&buf1], 32, 128); > bar (&buf1); > MEM[(struct &)&buf1] ={v} {CLOBBER}; > baz (&buf2); > return; > in *.optimized.
Ah, OK. The clobber has record type, not array type. And we don't mark the LHS of clobbers TREE_THIS_VOLATILE but the RHS CONSTRUCTOR. So to have it folded you need to in-place dtor the declared type, not some other. The only reason I cannot get it folded it seems to be the if (/* Same volatile qualification. */ TREE_THIS_VOLATILE (*t) == TREE_THIS_VOLATILE (decl) /* Same TBAA behavior with -fstrict-aliasing. */ && !TYPE_REF_CAN_ALIAS_ALL (alias_type) && (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (TREE_TYPE (alias_type))) /* Same alignment. */ && TYPE_ALIGN (TREE_TYPE (decl)) == TYPE_ALIGN (TREE_TYPE (*t)) /* We have to look out here to not drop a required conversion from the rhs to the lhs if *t appears on the lhs or vice-versa if it appears on the rhs. Thus require strict type compatibility. */ && types_compatible_p (TREE_TYPE (*t), TREE_TYPE (decl))) check where TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (TREE_TYPE (alias_type) fails. Oddly the two different main variants _do_ share their TYPE_FIELDs... So I guess in the end we're being lucky. Somehow. I've played with __attribute__((noipa)) void qux () { S buf1; foo ((char *)&buf1); S *p = new (&buf1) (S); bar (p); p->~S (); { char buf2[128]; baz (buf2); } } Richard.