llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.54k stars 11.8k forks source link

Missed optimization std::atomic with 64bit struct #44400

Open JVApen opened 4 years ago

JVApen commented 4 years ago
Bugzilla Link 45055
Version trunk
OS Linux
CC @zygoloid

Extended Description

Logging for https://stackoverflow.com/questions/60445848/clang-doesnt-inline-stdatomicload-for-loading-64-bit-structs

Code:

include

struct A { int32_t x, y; };

A f(std::atomic& a) { return a.load(std::memory_order_relaxed); }

Expected assembly (by GCC): f(std::atomic&): mov rax, QWORD PTR [rdi] ret

Assembly by Clang: f(std::atomic&): # @​f(std::atomic&) push rax mov rsi, rdi mov rdx, rsp mov edi, 8 xor ecx, ecx call __atomic_load mov rax, qword ptr [rsp] pop rcx ret mov rdi, rax call clang_call_terminate clang_call_terminate: # @​clang_call_terminate push rax call cxa_begin_catch call std::terminate()

This clang missed optimization only happens with libstdc++; clang on Godbolt inlines as we expect for -stdlib=libc++. https://godbolt.org/z/Tt8XTX.

More details, see the stack overflow post

llvmbot commented 4 years ago

The problem can also be worked around for libstdc++ by making the struct 8-byte aligned, e.g. struct { alignas (8) int32_t x; int32_t y; }

So my guess is that clang is somehow seeing what it thinks is an under-aligned __atomic operation. Even though libstdc++ does align the atomic object to guarantee correctness for GCC.