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.

Reply via email to