Skip to content

Commit 2d30203

Browse files
authored
Merge pull request #17800 from JuliaLang/yyc/codegen/deopt-tls
Deoptimize TLS access
2 parents f9fb4da + f90eab3 commit 2d30203

File tree

2 files changed

+35
-12
lines changed

2 files changed

+35
-12
lines changed

src/llvm-ptls.cpp

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "llvm-version.h"
99
#include "support/dtypes.h"
10+
#include <sstream>
1011

1112
#include <llvm/Pass.h>
1213
#include <llvm/IR/Module.h>
@@ -99,23 +100,41 @@ void LowerPTLS::runOnFunction(LLVMContext &ctx, Module &M, Function *F,
99100
ptlsStates->addAttribute(AttributeSet::FunctionIndex,
100101
Attribute::NoUnwind);
101102
}
102-
else if (jl_tls_offset != -1) {
103103
#ifdef LLVM37
104+
else if (jl_tls_offset != -1) {
104105
auto T_int8 = Type::getInt8Ty(ctx);
105106
auto T_pint8 = PointerType::get(T_int8, 0);
106-
auto T_size = (sizeof(size_t) == 8 ? Type::getInt64Ty(ctx) :
107-
Type::getInt32Ty(ctx));
108107
// Replace the function call with inline assembly if we know
109108
// how to generate it.
110-
const char *asm_str = nullptr;
109+
# if defined(_CPU_X86_64_) || defined(_CPU_X86_)
110+
// Workaround LLVM bug by hiding the offset computation
111+
// (and therefore the optimization opportunity) from LLVM.
112+
static const std::string asm_str = [&] () {
113+
std::stringstream stm;
111114
# if defined(_CPU_X86_64_)
112-
asm_str = "movq %fs:0, $0";
113-
# elif defined(_CPU_X86_)
114-
asm_str = "movl %gs:0, $0";
115-
# elif defined(_CPU_AARCH64_)
116-
asm_str = "mrs $0, tpidr_el0";
115+
stm << "movq %fs:0, $0;\naddq $$" << jl_tls_offset << ", $0";
116+
# else
117+
stm << "movl %gs:0, $0;\naddl $$" << jl_tls_offset << ", $0";
117118
# endif
118-
assert(asm_str && "Cannot emit thread pointer for this architecture.");
119+
return stm.str();
120+
}();
121+
// The add instruction clobbers flags
122+
auto tp = InlineAsm::get(FunctionType::get(T_pint8, false),
123+
asm_str.c_str(),
124+
"=r,~{dirflag},~{fpsr},~{flags}", false);
125+
Value *tls = CallInst::Create(tp, "ptls_i8", ptlsStates);
126+
tls = new BitCastInst(tls, PointerType::get(T_ppjlvalue, 0),
127+
"ptls", ptlsStates);
128+
# elif defined(_CPU_AARCH64_)
129+
// AArch64 doesn't seem to have this issue.
130+
// (Possibly because there are many more registers and the offset is
131+
// positive and small)
132+
// It's also harder to emit the offset in a generic way on AArch64
133+
// (need to generate one or two `add` with shift) so let llvm emit
134+
// the add for now.
135+
auto T_size = (sizeof(size_t) == 8 ? Type::getInt64Ty(ctx) :
136+
Type::getInt32Ty(ctx));
137+
const char *asm_str = "mrs $0, tpidr_el0";
119138
auto offset = ConstantInt::getSigned(T_size, jl_tls_offset);
120139
auto tp = InlineAsm::get(FunctionType::get(T_pint8, false),
121140
asm_str, "=r", false);
@@ -124,10 +143,14 @@ void LowerPTLS::runOnFunction(LLVMContext &ctx, Module &M, Function *F,
124143
"ptls_i8", ptlsStates);
125144
tls = new BitCastInst(tls, PointerType::get(T_ppjlvalue, 0),
126145
"ptls", ptlsStates);
146+
# else
147+
Value *tls = nullptr;
148+
assert(0 && "Cannot emit thread pointer for this architecture.");
149+
# endif
127150
ptlsStates->replaceAllUsesWith(tls);
128151
ptlsStates->eraseFromParent();
129-
#endif
130152
}
153+
#endif
131154
else {
132155
ptlsStates->addAttribute(AttributeSet::FunctionIndex,
133156
Attribute::ReadNone);

src/threading.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ jl_get_ptls_states_func jl_get_ptls_states_getter(void)
147147
#if defined(__GLIBC__) && (defined(_CPU_X86_64_) || defined(_CPU_X86_) || \
148148
((defined(_CPU_AARCH64_) || defined(_CPU_ARM_) || \
149149
defined(_CPU_PPC64_) || defined(_CPU_PPC_)) && \
150-
__GNUC__ >= 5))
150+
__GNUC__ >= 6))
151151
// Only enable this on architectures that are tested.
152152
// For example, GCC doesn't seem to support the `ifunc` attribute on power yet.
153153
# if __GLIBC_PREREQ(2, 12)

0 commit comments

Comments
 (0)