Optimize string constructor
this patch improves code generation on string constructors. We currently have _M_construct which takes as a parameter two iterators (begin/end pointers to other string) and produces new string. This patch adds special case of constructor where instead of begining/end pointers we readily know the string size and also special case when we know that source is 0 terminated. This happens commonly when producing stirng copies. Moreover currently ipa-prop is not able to propagate information that beg-end is known constant (copied string size) which makes it impossible for inliner to spot the common case where string size is known to be shorter than 15 bytes and fits in local buffer. Finally I made new constructor inline. Because it is explicitely instantiated without C++20 constexpr we do not produce implicit instantiation (as required by standard) which prevents inlining, ipa-modref and any other IPA analysis to happen. I think we need to make many of the other functions inline, since optimization accross string manipulation is quite important. There is PR94960 to track this issue. Bootstrapped/regtested x86_64-linux, OK? libstdc++-v3/ChangeLog: PR tree-optimization/103827 PR tree-optimization/80331 PR tree-optimization/87502 * config/abi/pre/gnu.ver: Add version for _M_construct<bool> * include/bits/basic_string.h: (basic_string::_M_construct<bool>): Declare. (basic_string constructors): Use it. * include/bits/basic_string.tcc: (basic_string::_M_construct<bool>): New template. * src/c++11/string-inst.cc: Instantated S::_M_construct<bool>. gcc/testsuite/ChangeLog: * g++.dg/tree-ssa/pr80331.C: New test. * g++.dg/tree-ssa/pr87502.C: New test.
This commit is contained in:
parent
37f35ebc7c
commit
9c5505a35d
6 changed files with 67 additions and 2 deletions
8
gcc/testsuite/g++.dg/tree-ssa/pr80331.C
Normal file
8
gcc/testsuite/g++.dg/tree-ssa/pr80331.C
Normal file
|
@ -0,0 +1,8 @@
|
|||
// { dg-do compile }
|
||||
// { dg-additional-options "-O2 -fdump-tree-optimized" }
|
||||
#include<string>
|
||||
int sain() {
|
||||
const std::string remove_me("remove_me");
|
||||
return 0;
|
||||
}
|
||||
// { dg-final { scan-tree-dump-not "remove_me" "optimized" } }
|
15
gcc/testsuite/g++.dg/tree-ssa/pr87502.C
Normal file
15
gcc/testsuite/g++.dg/tree-ssa/pr87502.C
Normal file
|
@ -0,0 +1,15 @@
|
|||
// { dg-do compile }
|
||||
// { dg-additional-options "-O2 -fdump-tree-optimized" }
|
||||
#include <string>
|
||||
|
||||
|
||||
__attribute__ ((pure))
|
||||
extern int foo (const std::string &);
|
||||
|
||||
int
|
||||
bar ()
|
||||
{
|
||||
return foo ("abc") + foo (std::string("abc"));
|
||||
}
|
||||
// We used to add terminating zero explicitely instead of using fact
|
||||
// that memcpy source is already 0 terminated.
|
|
@ -2540,6 +2540,9 @@ GLIBCXX_3.4.34 {
|
|||
_ZNSt8__format25__locale_encoding_to_utf8ERKSt6localeSt17basic_string_viewIcSt11char_traitsIcEEPv;
|
||||
# __sso_string constructor and destructor
|
||||
_ZNSt12__sso_string[CD][12]Ev;
|
||||
# void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<bool>(char const*, unsigned long)
|
||||
# and wide char version
|
||||
_ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE12_M_constructILb[01]EEEvPK[cw]m;
|
||||
} GLIBCXX_3.4.33;
|
||||
|
||||
# Symbols in the support library (libsupc++) have their own tag.
|
||||
|
|
|
@ -341,6 +341,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
void
|
||||
_M_construct(size_type __req, _CharT __c);
|
||||
|
||||
// Construct using block of memory of known size.
|
||||
// If _Terminated is true assume that source is already 0 terminated.
|
||||
template<bool _Terminated>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
_M_construct(const _CharT *__c, size_type __n);
|
||||
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
allocator_type&
|
||||
_M_get_allocator()
|
||||
|
@ -561,8 +568,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
: _M_dataplus(_M_local_data(),
|
||||
_Alloc_traits::_S_select_on_copy(__str._M_get_allocator()))
|
||||
{
|
||||
_M_construct(__str._M_data(), __str._M_data() + __str.length(),
|
||||
std::forward_iterator_tag());
|
||||
_M_construct<true>(__str._M_data(), __str.length());
|
||||
}
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
|
|
|
@ -276,6 +276,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
_M_set_length(__n);
|
||||
}
|
||||
|
||||
// Length of string constructed is easier to propagate inter-procedurally
|
||||
// than difference between iterators.
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
template<bool _Terminated>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_construct(const _CharT *__str, size_type __n)
|
||||
{
|
||||
if (__n > size_type(_S_local_capacity))
|
||||
{
|
||||
_M_data(_M_create(__n, size_type(0)));
|
||||
_M_capacity(__n);
|
||||
}
|
||||
else
|
||||
_M_init_local_buf();
|
||||
|
||||
if (__n || _Terminated)
|
||||
this->_S_copy(_M_data(), __str, __n + _Terminated);
|
||||
|
||||
_M_length(__n);
|
||||
if (!_Terminated)
|
||||
traits_type::assign(_M_data()[__n], _CharT());
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
|
|
|
@ -91,6 +91,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
void
|
||||
S::_M_construct(const C*, const C*, forward_iterator_tag);
|
||||
|
||||
template
|
||||
void
|
||||
S::_M_construct<false>(const C*, size_t);
|
||||
|
||||
template
|
||||
void
|
||||
S::_M_construct<true>(const C*, size_t);
|
||||
|
||||
#else // !_GLIBCXX_USE_CXX11_ABI
|
||||
|
||||
template
|
||||
|
|
Loading…
Add table
Reference in a new issue