- //==- TLSVariableHoist.h ------ Remove Redundant TLS Loads -------*- C++ -*-==// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This pass identifies/eliminates Redundant TLS Loads if related option is set. 
- // For example: 
- // static __thread int x; 
- // int g(); 
- // int f(int c) { 
- //   int *px = &x; 
- //   while (c--) 
- //     *px += g(); 
- //   return *px; 
- // } 
- // 
- // will generate Redundant TLS Loads by compiling it with 
- // clang++ -fPIC -ftls-model=global-dynamic -O2 -S 
- // 
- // .LBB0_2:                                # %while.body 
- //                                         # =>This Inner Loop Header: Depth=1 
- //         callq   _Z1gv@PLT 
- //         movl    %eax, %ebp 
- //         leaq    _ZL1x@TLSLD(%rip), %rdi 
- //         callq   __tls_get_addr@PLT 
- //         addl    _ZL1x@DTPOFF(%rax), %ebp 
- //         movl    %ebp, _ZL1x@DTPOFF(%rax) 
- //         addl    $-1, %ebx 
- //         jne     .LBB0_2 
- //         jmp     .LBB0_3 
- // .LBB0_4:                                # %entry.while.end_crit_edge 
- //         leaq    _ZL1x@TLSLD(%rip), %rdi 
- //         callq   __tls_get_addr@PLT 
- //         movl    _ZL1x@DTPOFF(%rax), %ebp 
- // 
- // The Redundant TLS Loads will hurt the performance, especially in loops. 
- // So we try to eliminate/move them if required by customers, let it be: 
- // 
- // # %bb.0:                                # %entry 
- //         ... 
- //         movl    %edi, %ebx 
- //         leaq    _ZL1x@TLSLD(%rip), %rdi 
- //         callq   __tls_get_addr@PLT 
- //         leaq    _ZL1x@DTPOFF(%rax), %r14 
- //         testl   %ebx, %ebx 
- //         je      .LBB0_1 
- // .LBB0_2:                                # %while.body 
- //                                         # =>This Inner Loop Header: Depth=1 
- //         callq   _Z1gv@PLT 
- //         addl    (%r14), %eax 
- //         movl    %eax, (%r14) 
- //         addl    $-1, %ebx 
- //         jne     .LBB0_2 
- //         jmp     .LBB0_3 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_TRANSFORMS_SCALAR_TLSVARIABLEHOIST_H 
- #define LLVM_TRANSFORMS_SCALAR_TLSVARIABLEHOIST_H 
-   
- #include "llvm/ADT/MapVector.h" 
- #include "llvm/ADT/SmallVector.h" 
- #include "llvm/Analysis/LoopInfo.h" 
- #include "llvm/IR/PassManager.h" 
-   
- namespace llvm { 
-   
- class BasicBlock; 
- class DominatorTree; 
- class Function; 
- class GlobalVariable; 
- class Instruction; 
-   
- /// A private "module" namespace for types and utilities used by 
- /// TLSVariableHoist. These are implementation details and should 
- /// not be used by clients. 
- namespace tlshoist { 
-   
- /// Keeps track of the user of a TLS variable and the operand index 
- /// where the variable is used. 
- struct TLSUser { 
-   Instruction *Inst; 
-   unsigned OpndIdx; 
-   
-   TLSUser(Instruction *Inst, unsigned Idx) : Inst(Inst), OpndIdx(Idx) {} 
- }; 
-   
- /// Keeps track of a TLS variable candidate and its users. 
- struct TLSCandidate { 
-   SmallVector<TLSUser, 8> Users; 
-   
-   /// Add the user to the use list and update the cost. 
-   void addUser(Instruction *Inst, unsigned Idx) { 
-     Users.push_back(TLSUser(Inst, Idx)); 
-   } 
- }; 
-   
- } // end namespace tlshoist 
-   
- class TLSVariableHoistPass : public PassInfoMixin<TLSVariableHoistPass> { 
- public: 
-   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 
-   
-   // Glue for old PM. 
-   bool runImpl(Function &F, DominatorTree &DT, LoopInfo &LI); 
-   
- private: 
-   DominatorTree *DT; 
-   LoopInfo *LI; 
-   
-   /// Keeps track of TLS variable candidates found in the function. 
-   using TLSCandMapType = MapVector<GlobalVariable *, tlshoist::TLSCandidate>; 
-   TLSCandMapType TLSCandMap; 
-   
-   void collectTLSCandidates(Function &Fn); 
-   void collectTLSCandidate(Instruction *Inst); 
-   Instruction *getNearestLoopDomInst(BasicBlock *BB, Loop *L); 
-   Instruction *getDomInst(Instruction *I1, Instruction *I2); 
-   BasicBlock::iterator findInsertPos(Function &Fn, GlobalVariable *GV, 
-                                      BasicBlock *&PosBB); 
-   Instruction *genBitCastInst(Function &Fn, GlobalVariable *GV); 
-   bool tryReplaceTLSCandidates(Function &Fn); 
-   bool tryReplaceTLSCandidate(Function &Fn, GlobalVariable *GV); 
- }; 
-   
- } // end namespace llvm 
-   
- #endif // LLVM_TRANSFORMS_SCALAR_TLSVARIABLEHOIST_H 
-