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
69namespace llvm {
70
71class BasicBlock;
72class DominatorTree;
73class Function;
74class GlobalVariable;
75class 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.
80namespace tlshoist {
81
82/// Keeps track of the user of a TLS variable and the operand index
83/// where the variable is used.
84struct 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.
92struct 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(Elt: TLSUser(Inst, Idx));
98 }
99};
100
101} // end namespace tlshoist
102
103class TLSVariableHoistPass : public PassInfoMixin<TLSVariableHoistPass> {
104public:
105 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
106
107 // Glue for old PM.
108 bool runImpl(Function &F, DominatorTree &DT, LoopInfo &LI);
109
110private:
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
132

source code of llvm/include/llvm/Transforms/Scalar/TLSVariableHoist.h