Skip to content

Commit c310143

Browse files
committed
TLS loads opimization (hoist)
Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D120000
1 parent fcd9fa4 commit c310143

21 files changed

+1136
-0
lines changed

llvm/docs/LangRef.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2114,6 +2114,11 @@ example:
21142114
function with a tail call. The prototype of a thunk should not be used for
21152115
optimization purposes. The caller is expected to cast the thunk prototype to
21162116
match the thunk target prototype.
2117+
2118+
``"tls-load-hoist"``
2119+
This attribute indicates that the function will try to reduce redundant
2120+
tls address caculation by hoisting tls variable.
2121+
21172122
``uwtable[(sync|async)]``
21182123
This attribute indicates that the ABI being targeted requires that
21192124
an unwind table entry be produced for this function even if we can

llvm/include/llvm/CodeGen/MachinePassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ FUNCTION_PASS("expand-reductions", ExpandReductionsPass, ())
4747
FUNCTION_PASS("expandvp", ExpandVectorPredicationPass, ())
4848
FUNCTION_PASS("lowerinvoke", LowerInvokePass, ())
4949
FUNCTION_PASS("scalarize-masked-mem-intrin", ScalarizeMaskedMemIntrinPass, ())
50+
FUNCTION_PASS("tlshoist", TLSVariableHoistPass, ())
5051
FUNCTION_PASS("verify", VerifierPass, ())
5152
#undef FUNCTION_PASS
5253

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&);
445445
void initializeTargetPassConfigPass(PassRegistry&);
446446
void initializeTargetTransformInfoWrapperPassPass(PassRegistry&);
447447
void initializeThreadSanitizerLegacyPassPass(PassRegistry&);
448+
void initializeTLSVariableHoistLegacyPassPass(PassRegistry &);
448449
void initializeTwoAddressInstructionPassPass(PassRegistry&);
449450
void initializeTypeBasedAAWrapperPassPass(PassRegistry&);
450451
void initializeTypePromotionPass(PassRegistry&);

llvm/include/llvm/LinkAllPasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ namespace {
177177
(void) llvm::createStripDeadDebugInfoPass();
178178
(void) llvm::createStripDeadPrototypesPass();
179179
(void) llvm::createTailCallEliminationPass();
180+
(void)llvm::createTLSVariableHoistPass();
180181
(void) llvm::createJumpThreadingPass();
181182
(void) llvm::createDFAJumpThreadingPass();
182183
(void) llvm::createUnifyFunctionExitNodesPass();

llvm/include/llvm/Transforms/Scalar.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,12 @@ extern char &InferAddressSpacesID;
427427
// "block_weights" metadata.
428428
FunctionPass *createLowerExpectIntrinsicPass();
429429

430+
//===----------------------------------------------------------------------===//
431+
//
432+
// TLSVariableHoist - This pass reduce duplicated TLS address call.
433+
//
434+
FunctionPass *createTLSVariableHoistPass();
435+
430436
//===----------------------------------------------------------------------===//
431437
//
432438
// LowerConstantIntrinsicss - Expand any remaining llvm.objectsize and
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
//==- TLSVariableHoist.h ------ Remove Redundant TLS Loads -------*- C++ -*-==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This pass identifies/eliminates Redundant TLS Loads if related option is set.
10+
// For example:
11+
// static __thread int x;
12+
// int g();
13+
// int f(int c) {
14+
// int *px = &x;
15+
// while (c--)
16+
// *px += g();
17+
// return *px;
18+
// }
19+
//
20+
// will generate Redundant TLS Loads by compiling it with
21+
// clang++ -fPIC -ftls-model=global-dynamic -O2 -S
22+
//
23+
// .LBB0_2: # %while.body
24+
// # =>This Inner Loop Header: Depth=1
25+
// callq _Z1gv@PLT
26+
// movl %eax, %ebp
27+
// leaq _ZL1x@TLSLD(%rip), %rdi
28+
// callq __tls_get_addr@PLT
29+
// addl _ZL1x@DTPOFF(%rax), %ebp
30+
// movl %ebp, _ZL1x@DTPOFF(%rax)
31+
// addl $-1, %ebx
32+
// jne .LBB0_2
33+
// jmp .LBB0_3
34+
// .LBB0_4: # %entry.while.end_crit_edge
35+
// leaq _ZL1x@TLSLD(%rip), %rdi
36+
// callq __tls_get_addr@PLT
37+
// movl _ZL1x@DTPOFF(%rax), %ebp
38+
//
39+
// The Redundant TLS Loads will hurt the performance, especially in loops.
40+
// So we try to eliminate/move them if required by customers, let it be:
41+
//
42+
// # %bb.0: # %entry
43+
// ...
44+
// movl %edi, %ebx
45+
// leaq _ZL1x@TLSLD(%rip), %rdi
46+
// callq __tls_get_addr@PLT
47+
// leaq _ZL1x@DTPOFF(%rax), %r14
48+
// testl %ebx, %ebx
49+
// je .LBB0_1
50+
// .LBB0_2: # %while.body
51+
// # =>This Inner Loop Header: Depth=1
52+
// callq _Z1gv@PLT
53+
// addl (%r14), %eax
54+
// movl %eax, (%r14)
55+
// addl $-1, %ebx
56+
// jne .LBB0_2
57+
// jmp .LBB0_3
58+
//
59+
//===----------------------------------------------------------------------===//
60+
61+
#ifndef LLVM_TRANSFORMS_SCALAR_TLSVARIABLEHOIST_H
62+
#define LLVM_TRANSFORMS_SCALAR_TLSVARIABLEHOIST_H
63+
64+
#include "llvm/ADT/MapVector.h"
65+
#include "llvm/ADT/SmallVector.h"
66+
#include "llvm/Analysis/LoopInfo.h"
67+
#include "llvm/IR/PassManager.h"
68+
69+
namespace llvm {
70+
71+
class BasicBlock;
72+
class DominatorTree;
73+
class Function;
74+
class GlobalVariable;
75+
class Instruction;
76+
77+
/// A private "module" namespace for types and utilities used by
78+
/// TLSVariableHoist. These are implementation details and should
79+
/// not be used by clients.
80+
namespace tlshoist {
81+
82+
/// Keeps track of the user of a TLS variable and the operand index
83+
/// where the variable is used.
84+
struct TLSUser {
85+
Instruction *Inst;
86+
unsigned OpndIdx;
87+
88+
TLSUser(Instruction *Inst, unsigned Idx) : Inst(Inst), OpndIdx(Idx) {}
89+
};
90+
91+
/// Keeps track of a TLS variable candidate and its users.
92+
struct TLSCandidate {
93+
SmallVector<TLSUser, 8> Users;
94+
95+
/// Add the user to the use list and update the cost.
96+
void addUser(Instruction *Inst, unsigned Idx) {
97+
Users.push_back(TLSUser(Inst, Idx));
98+
}
99+
};
100+
101+
} // end namespace tlshoist
102+
103+
class TLSVariableHoistPass : public PassInfoMixin<TLSVariableHoistPass> {
104+
public:
105+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
106+
107+
// Glue for old PM.
108+
bool runImpl(Function &F, DominatorTree &DT, LoopInfo &LI);
109+
110+
private:
111+
DominatorTree *DT;
112+
LoopInfo *LI;
113+
114+
/// Keeps track of TLS variable candidates found in the function.
115+
using TLSCandMapType = MapVector<GlobalVariable *, tlshoist::TLSCandidate>;
116+
TLSCandMapType TLSCandMap;
117+
118+
void collectTLSCandidates(Function &Fn);
119+
void collectTLSCandidate(Instruction *Inst);
120+
Instruction *getNearestLoopDomInst(BasicBlock *BB, Loop *L);
121+
Instruction *getDomInst(Instruction *I1, Instruction *I2);
122+
BasicBlock::iterator findInsertPos(Function &Fn, GlobalVariable *GV,
123+
BasicBlock *&PosBB);
124+
Instruction *genBitCastInst(Function &Fn, GlobalVariable *GV);
125+
bool tryReplaceTLSCandidates(Function &Fn);
126+
bool tryReplaceTLSCandidate(Function &Fn, GlobalVariable *GV);
127+
};
128+
129+
} // end namespace llvm
130+
131+
#endif // LLVM_TRANSFORMS_SCALAR_TLSVARIABLEHOIST_H

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,9 @@ void TargetPassConfig::addIRPasses() {
922922
// Allow disabling it for testing purposes.
923923
if (!DisableExpandReductions)
924924
addPass(createExpandReductionsPass());
925+
926+
if (getOptLevel() != CodeGenOpt::None)
927+
addPass(createTLSVariableHoistPass());
925928
}
926929

927930
/// Turn exception handling constructs into something the code generators can

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@
212212
#include "llvm/Transforms/Scalar/SpeculativeExecution.h"
213213
#include "llvm/Transforms/Scalar/StraightLineStrengthReduce.h"
214214
#include "llvm/Transforms/Scalar/StructurizeCFG.h"
215+
#include "llvm/Transforms/Scalar/TLSVariableHoist.h"
215216
#include "llvm/Transforms/Scalar/TailRecursionElimination.h"
216217
#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
217218
#include "llvm/Transforms/Utils/AddDiscriminators.h"

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ FUNCTION_PASS("verify<safepoint-ir>", SafepointIRVerifierPass())
361361
FUNCTION_PASS("verify<scalar-evolution>", ScalarEvolutionVerifierPass())
362362
FUNCTION_PASS("view-cfg", CFGViewerPass())
363363
FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass())
364+
FUNCTION_PASS("tlshoist", TLSVariableHoistPass())
364365
FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
365366
FUNCTION_PASS("tsan", ThreadSanitizerPass())
366367
FUNCTION_PASS("memprof", MemProfilerPass())

llvm/lib/Transforms/Scalar/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ add_llvm_component_library(LLVMScalarOpts
7777
StraightLineStrengthReduce.cpp
7878
StructurizeCFG.cpp
7979
TailRecursionElimination.cpp
80+
TLSVariableHoist.cpp
8081
WarnMissedTransforms.cpp
8182

8283
ADDITIONAL_HEADER_DIRS

llvm/lib/Transforms/Scalar/Scalar.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) {
101101
initializeSimpleLoopUnswitchLegacyPassPass(Registry);
102102
initializeSinkingLegacyPassPass(Registry);
103103
initializeTailCallElimPass(Registry);
104+
initializeTLSVariableHoistLegacyPassPass(Registry);
104105
initializeSeparateConstOffsetFromGEPLegacyPassPass(Registry);
105106
initializeSpeculativeExecutionLegacyPassPass(Registry);
106107
initializeStraightLineStrengthReduceLegacyPassPass(Registry);

0 commit comments

Comments
 (0)