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 132