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

--- Comment #14 from Jan Hubicka <hubicka at gcc dot gnu.org> ---
Declaring _S_create and _M_create inline indeed helps a little:

diff --git a/libstdc++-v3/include/bits/basic_string.h
b/libstdc++-v3/include/bits/basic_string.h
index 17b973c8b45..d73a61abe5b 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -278,7 +278,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       }

       // Create & Destroy
-      _GLIBCXX20_CONSTEXPR
+      _GLIBCXX20_CONSTEXPR inline
       pointer
       _M_create(size_type&, size_type);

diff --git a/libstdc++-v3/include/bits/cow_string.h
b/libstdc++-v3/include/bits/cow_string.h
index 087ddf81dd8..0bd75f0fcb1 100644
--- a/libstdc++-v3/include/bits/cow_string.h
+++ b/libstdc++-v3/include/bits/cow_string.h
@@ -259,7 +259,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }

        // Create & Destroy
-       static _Rep*
+       static inline _Rep*
        _S_create(size_type, size_type, const _Alloc&);

        void

Now I get:

int sain ()
{
  struct allocator_type D.27707;
  char * _45;
  _Atomic_word * _49;
  char __libc_single_threaded.12_50;
  unsigned int _53;
  int _54;

  <bb 2> [local count: 1073741824]:
  _45 = operator new (26);
  MEM[(struct _Rep *)_45].D.24285._M_capacity = 1;
  MEM[(struct _Rep *)_45].D.24285._M_refcount = 0;
  MEM[(char_type &)_45 + 24] = 97;
  if (_45 != &_S_empty_rep_storage)
    goto <bb 4>; [10.00%]
  else
    goto <bb 3>; [90.00%]

  <bb 3> [local count: 999008065]:
  goto <bb 8>; [100.00%]

  <bb 4> [local count: 107374184]:
  MEM[(struct _Rep *)_45].D.24285._M_length = 1;
  MEM[(char_type &)_45 + 25] = 0;
  __libc_single_threaded.12_50 = __libc_single_threaded;
  if (__libc_single_threaded.12_50 != 0)
    goto <bb 5>; [67.00%]
  else
    goto <bb 6>; [33.00%]

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

  <bb 6> [local count: 35433481]:
  _49 = &MEM[(struct _Rep *)_45].D.24285._M_refcount;
  _53 = __atomic_fetch_add_4 (_49, 4294967295, 4);
  _54 = (int) _53;
  if (_54 <= 0)
    goto <bb 7>; [7.88%]
  else
    goto <bb 3>; [92.12%]

  <bb 7> [local count: 27380417]:
  std::basic_string<char>::_Rep::_M_destroy (_45, &D.27707);

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

}

New memory is kept alive by:

  _45 = operator new (26);
...
  if (_45 != &_S_empty_rep_storage)
    goto <bb 4>; [10.00%]
  else
    goto <bb 3>; [90.00%]

I think we ought to be able to deduce from malloc attribute that _45 is
different from address of a decl.

Reply via email to