diff options
author | Matthias Braun <matze@braunis.de> | 2024-04-17 12:48:02 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-17 12:48:02 -0700 |
commit | 652bcf685c72447f3cc46d93d6c9c1948e8499f3 (patch) | |
tree | bcada6c64aee0c2ce4c93da6bf044857125df281 /llvm/lib/CodeGen/CodeGenPrepare.cpp | |
parent | db2f64ee1f743153f242ca92bf627458ba7f8000 (diff) | |
download | llvm-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.cpp | 29 |
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 |