編集をキャッシュされていない:確かにコンパイラのバグであると思われる:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82803結果は
私はstd::stringstream
バッファを保存するためにTLSを使用して書き込みログのラッパーを書いています。このコードは共有ライブラリによって使用されます。 godbolt.orgのコードを見ると、gccもclangもTLSルックアップの結果をキャッシュしていないように思えます(私はループを設計していると信じてループに繰り返し__tls_get_addr()を呼び出します)。
打ち鳴らす5.0.0:
xor ebx, ebx
.LBB0_3: # =>This Inner Loop Header: Depth=1
data16
lea rdi, [rip + LogStream::getBuffer[abi:cxx11]()::buffer[abi:cxx11]@TLSGD]
data16
data16
rex64
call [email protected] // Called on every loop iteration.
lea rdi, [rax + 16]
mov esi, ebx
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)@PLT
inc ebx
cmp ebx, 12345678
jne .LBB0_3
GCC 7.2:
アセンブリコードの出力を見てみる#include <sstream>
class LogStream
{
public:
LogStream()
: m_buffer(getBuffer())
{
}
LogStream(std::stringstream& buffer)
: m_buffer(buffer)
{
}
static std::stringstream& getBuffer()
{
thread_local std::stringstream buffer;
return buffer;
}
template <typename T>
inline LogStream& operator<<(const T& t)
{
m_buffer << t;
return *this;
}
private:
std::stringstream& m_buffer;
};
int main()
{
LogStream log{};
for (int i = 0; i < 12345678; ++i)
{
log << i;
}
}
両方GCCと打ち鳴らすはかなり似た出力を生成します
どのようにして両方のコンパイラにルックアップを繰り返し実行する必要はないのだろうか?
コンパイラオプション:-std=c++11 -O3 -fPIC
インラインしないようにgetbufferを強制的にまたは動的にされるLogStreamは私のために働くように思わ割り当て... dunnow ... –
は指定しません'-fPIC'はまた、奇妙なコードを生成しません。 –
@SebastianRedlはい、スタンドアロンアプリの世代は大丈夫です – James