[Bug tree-optimization/58483] missing optimization opportunity for const std::vector compared to std::array

rguenth at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Mon Jul 1 12:27:00 GMT 2019


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58483

--- Comment #12 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Marc Glisse from comment #11)
> (In reply to Richard Biener from comment #10)
> > Wit GCC 9 and trunk we are left with
> > 
> >   <bb 2> [local count: 118111600]:
> >   MEM[(int *)&D.30957] = 85899345930;
> >   D.30957[2] = 30;
> >   _33 = operator new (12);
> >   __builtin_memcpy (_33, &D.30957, 12);
> >   _41 = MEM[(const int &)_33];
> >   __init_42 = _41 + 100;
> >   _50 = MEM[(const int &)_33 + 4];
> >   __init_19 = __init_42 + _50;
> >   _14 = MEM[(const int &)_33 + 8];
> >   __init_16 = _14 + __init_19;
> >   operator delete (_33);
> >   D.30957 ={v} {CLOBBER};
> >   return __init_16;
> > 
> > here I think operator new clobbers D.30957 which escapes at the memcpy call.
> 
> I thought we had code saying that nothing can escape through memcpy?
> 
> > This prevents a late FRE from doing its job (not sure if a late one is
> > really needed).
> 
> With
> 
> #include <new>
> inline void* operator new(std::size_t n){return __builtin_malloc(n);}
> inline void operator delete(void*p)noexcept{__builtin_free(p);}
> inline void operator delete(void*p,std::size_t)noexcept{__builtin_free(p);}
> 
> I get
> 
>   _33 = __builtin_malloc (12);
>   MEM[(char * {ref-all})_33] = 85899345930;
>   MEM[(char * {ref-all})_33 + 8B] = 30;
>   _12 = MEM[(const int &)_33];
>   __init_49 = _12 + 100;
>   _38 = MEM[(const int &)_33 + 4];
>   __init_36 = _38 + __init_49;
>   _14 = MEM[(const int &)_33 + 8];
>   __init_16 = _14 + __init_36;
>   __builtin_free (_33);
>   return __init_16;
> 
> where FRE should work.

It does (late FRE is now in).  Even DOM could have handled the memory refs
but it fails to forward the pointer adjustment for the second load and
also seems to be confused about alias type differences.  IL before DOM:

  __BB(2,guessed_local(118111600)):
  _34 = __builtin_malloc (12ul);
  _32 = _34 + 12ul;
  __MEM <int, 64> ((char * {ref-all})_34) = 10;
  __MEM <int> ((char * {ref-all})_34 + _Literal (char * {ref-all}) 4) = 20;
  __MEM <int, 64> ((char * {ref-all})_34 + _Literal (char * {ref-all}) 8) = 30;
  __l ={v} {CLOBBER};
  __init_3 = 110;
  _2 = _34 + 4ul;
  _19 = 2ul;
  _35 = __MEM <const int> ((const int &)_34 + _Literal (const int &) 4);
  __init_26 = __init_3 + _35;
  _45 = _2 + 4ul;
  _22 = _19 + 18446744073709551615ul;
  _23 = __MEM <const int> ((const int &)_2 + _Literal (const int &) 4);
  __init_16 = _23 + __init_26;
  _17 = _45 + 4ul;
  _14 = _22 + 18446744073709551615ul;
  __builtin_free (_34);
  D_29464 ={v} {CLOBBER};
  D_29464 ={v} {CLOBBER};
  return __init_16;

and the reason why DOM doesn't handle the first load is equal_mem_array_ref_p
dispatches to operand_equal_p but that considers the refs non-equal
(that's correct - DOM should have used OEP_ADDRESS_OF here since we already
constrained the access otherwise).  For DOM this leaves the failed CSE
of the second load.


More information about the Gcc-bugs mailing list