aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/CodeGenPrepare.cpp
diff options
context:
space:
mode:
authorMatthias Braun <matze@braunis.de>2024-04-17 12:48:02 -0700
committerGitHub <noreply@github.com>2024-04-17 12:48:02 -0700
commit652bcf685c72447f3cc46d93d6c9c1948e8499f3 (patch)
treebcada6c64aee0c2ce4c93da6bf044857125df281 /llvm/lib/CodeGen/CodeGenPrepare.cpp
parentdb2f64ee1f743153f242ca92bf627458ba7f8000 (diff)
downloadllvm-652bcf685c72447f3cc46d93d6c9c1948e8499f3.zip
llvm-652bcf685c72447f3cc46d93d6c9c1948e8499f3.tar.gz
llvm-652bcf685c72447f3cc46d93d6c9c1948e8499f3.tar.bz2
CodeGenPrepare: Add support for llvm.threadlocal.address address-mode sinking (#87844)
Depending on the TLSMode many thread-local accesses on x86 can be expressed by adding a %fs: segment register to an addressing mode. Even if there are mutliple users of a `llvm.threadlocal.address` intrinsic it is generally not worth sharing the value in a register but instead fold the %fs access into multiple addressing modes. Hence this changes CodeGenPrepare to duplicate the `llvm.threadlocal.address` intrinsic as necessary. Introduces a new `TargetLowering::addressingModeSupportsTLS` callback that allows targets to indicate whether TLS accesses can be part of an addressing mode. This is fixing a performance problem, as this folding of TLS-accesses into multiple addressing modes happened naturally before the introduction of the `llvm.threadlocal.address` intrinsic, but regressed due to `SelectionDAG` keeping things in registers when accessed across basic blocks, so CodeGenPrepare needs to duplicate to mitigate this. We see a ~0.5% recovery in a codebase with heavy TLS usage (HHVM). This fixes most of #87437
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenPrepare.cpp')
-rw-r--r--llvm/lib/CodeGen/CodeGenPrepare.cpp29
1 files changed, 25 insertions, 4 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index e657872..22a766f 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -5082,6 +5082,15 @@ bool AddressingModeMatcher::matchOperationAddr(User *AddrInst, unsigned Opcode,
}
return true;
}
+ case Instruction::Call:
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(AddrInst)) {
+ if (II->getIntrinsicID() == Intrinsic::threadlocal_address) {
+ GlobalValue &GV = cast<GlobalValue>(*II->getArgOperand(0));
+ if (TLI.addressingModeSupportsTLS(GV))
+ return matchAddr(AddrInst->getOperand(0), Depth);
+ }
+ }
+ break;
}
return false;
}
@@ -5620,11 +5629,16 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
return Modified;
}
- if (AddrMode.BaseGV) {
+ GlobalValue *BaseGV = AddrMode.BaseGV;
+ if (BaseGV != nullptr) {
if (ResultPtr)
return Modified;
- ResultPtr = AddrMode.BaseGV;
+ if (BaseGV->isThreadLocal()) {
+ ResultPtr = Builder.CreateThreadLocalAddress(BaseGV);
+ } else {
+ ResultPtr = BaseGV;
+ }
}
// If the real base value actually came from an inttoptr, then the matcher
@@ -5789,8 +5803,15 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
}
// Add in the BaseGV if present.
- if (AddrMode.BaseGV) {
- Value *V = Builder.CreatePtrToInt(AddrMode.BaseGV, IntPtrTy, "sunkaddr");
+ GlobalValue *BaseGV = AddrMode.BaseGV;
+ if (BaseGV != nullptr) {
+ Value *BaseGVPtr;
+ if (BaseGV->isThreadLocal()) {
+ BaseGVPtr = Builder.CreateThreadLocalAddress(BaseGV);
+ } else {
+ BaseGVPtr = BaseGV;
+ }
+ Value *V = Builder.CreatePtrToInt(BaseGVPtr, IntPtrTy, "sunkaddr");
if (Result)
Result = Builder.CreateAdd(Result, V, "sunkaddr");
else