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

--- Comment #12 from Jan Hubicka <hubicka at gcc dot gnu.org> ---
I think with my patch to basic_string we should have at least arrived to
something comparable with clang.
With -O2 it is optimized away,
with -O2 -D_GLIBCXX_USE_CXX11_ABI=0 I get:

int sain ()
{
  struct allocator_type D.37493;
  struct allocator D.33221;
  struct _Rep * _18;
  _Atomic_word * _29;
  char __libc_single_threaded.11_30;
  unsigned int _33;
  int _34;

  <bb 2> [local count: 1073741824]:
  _18 = std::basic_string<char>::_Rep::_S_create (1, 0, &D.33221);
  MEM[(char_type &)_18 + 24] = 97;
  if (_18 != &_S_empty_rep_storage)
    goto <bb 3>; [10.00%]
  else
    goto <bb 8>; [90.00%]

  <bb 3> [local count: 107374184]:
  _18->D.33079._M_refcount = 0;
  _18->D.33079._M_length = 1;
  MEM[(char_type &)_18 + 25] = 0;
  D.33221 ={v} {CLOBBER(eos)};
  __libc_single_threaded.11_30 = __libc_single_threaded;
  if (__libc_single_threaded.11_30 != 0)
    goto <bb 4>; [67.00%]
  else
    goto <bb 5>; [33.00%]

  <bb 4> [local count: 71940704]:
  MEM[(_Atomic_word *)_18 + 16B] = -1;
  goto <bb 6>; [100.00%]

  <bb 5> [local count: 35433481]:
  _29 = &_18->D.33079._M_refcount;
  _33 = __atomic_fetch_add_4 (_29, 4294967295, 4);
  _34 = (int) _33;
  if (_34 <= 0)
    goto <bb 6>; [7.88%]
  else
    goto <bb 7>; [92.12%]

  <bb 6> [local count: 27380417]:
  std::basic_string<char>::_Rep::_M_destroy (_18, &D.37493);

  <bb 7> [local count: 1073741824]:
  D.37493 ={v} {CLOBBER(eos)};
  return 0;

  <bb 8> [local count: 966367640]:
  D.33221 ={v} {CLOBBER(eos)};
  goto <bb 7>; [100.00%]

}

this is not optimized since _M_create and M_destroy are not inlined. Those
seems to be invisible to compiler, so even if modref was extended to propagate
removable allocations inter-proceduraly, we have problem.

With longer string also both clang and GCC will not optimize the code
completely. We get:

int sain ()
{
  size_type __dnew;
  const struct string s;
  char * _7;
  long unsigned int _9;
  long unsigned int _10;
  char * _17;
  long unsigned int __dnew.1_18;
  long unsigned int __dnew.2_20;
  char * _21;
  char * _22;

  <bb 2> [local count: 1073741824]:
  MEM[(struct basic_string *)&s] ={v} {CLOBBER(bob)};
  MEM[(struct _Alloc_hider *)&s] ={v} {CLOBBER(bob)};
  MEM[(struct _Alloc_hider *)&s]._M_p = &s.D.25525._M_local_buf;
  __dnew = 40;
  _17 = std::__cxx11::basic_string<char>::_M_create (&s, &__dnew, 0);
  s._M_dataplus._M_p = _17;
  __dnew.1_18 = __dnew;
  s.D.25525._M_allocated_capacity = __dnew.1_18;
  __builtin_memcpy (_17, "this string is longer than 15 characters", 40);
  __dnew.2_20 = __dnew;
  _21 = s._M_dataplus._M_p;
  _22 = _21 + __dnew.2_20;
  MEM[(char_type &)_22] = 0;
  __dnew ={v} {CLOBBER(eos)};
  _7 = s._M_dataplus._M_p;
  if (&s.D.25525._M_local_buf == _7)
    goto <bb 4>; [18.09%]
  else
    goto <bb 3>; [81.91%]

  <bb 3> [local count: 879501928]:
  _9 = s.D.25525._M_allocated_capacity;
  _10 = _9 + 1;
  operator delete (_7, _10);

  <bb 4> [local count: 1073741824]:
  s ={v} {CLOBBER(eob)};
  s ={v} {CLOBBER(eos)};
  return 0;

}

Call to _M_create is problem here. Again it is not seen by modref.
With -std=c++23 we optimize out the code, while clang doesn't

Reply via email to