LLVM  14.0.0git
XCoreLowerThreadLocal.cpp
Go to the documentation of this file.
1 //===-- XCoreLowerThreadLocal - Lower thread local variables --------------===//
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 /// \file
10 /// This file contains a pass that lowers thread local variables on the
11 /// XCore.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "XCore.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/DerivedTypes.h"
18 #include "llvm/IR/GlobalVariable.h"
19 #include "llvm/IR/IRBuilder.h"
20 #include "llvm/IR/Intrinsics.h"
21 #include "llvm/IR/IntrinsicsXCore.h"
22 #include "llvm/IR/Module.h"
23 #include "llvm/IR/NoFolder.h"
24 #include "llvm/IR/ValueHandle.h"
25 #include "llvm/Pass.h"
28 
29 #define DEBUG_TYPE "xcore-lower-thread-local"
30 
31 using namespace llvm;
32 
34  "xcore-max-threads", cl::Optional,
35  cl::desc("Maximum number of threads (for emulation thread-local storage)"),
36  cl::Hidden, cl::value_desc("number"), cl::init(8));
37 
38 namespace {
39  /// Lowers thread local variables on the XCore. Each thread local variable is
40  /// expanded to an array of n elements indexed by the thread ID where n is the
41  /// fixed number hardware threads supported by the device.
42  struct XCoreLowerThreadLocal : public ModulePass {
43  static char ID;
44 
45  XCoreLowerThreadLocal() : ModulePass(ID) {
47  }
48 
49  bool lowerGlobal(GlobalVariable *GV);
50 
51  bool runOnModule(Module &M) override;
52  };
53 }
54 
56 
57 INITIALIZE_PASS(XCoreLowerThreadLocal, "xcore-lower-thread-local",
58  "Lower thread local variables", false, false)
59 
61  return new XCoreLowerThreadLocal();
62 }
63 
64 static ArrayType *createLoweredType(Type *OriginalType) {
65  return ArrayType::get(OriginalType, MaxThreads);
66 }
67 
68 static Constant *
69 createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer) {
71  for (unsigned i = 0; i != MaxThreads; ++i) {
72  Elements[i] = OriginalInitializer;
73  }
74  return ConstantArray::get(NewType, Elements);
75 }
76 
77 
79  do {
80  SmallVector<WeakTrackingVH, 8> WUsers(CE->users());
81  llvm::sort(WUsers);
82  WUsers.erase(std::unique(WUsers.begin(), WUsers.end()), WUsers.end());
83  while (!WUsers.empty())
84  if (WeakTrackingVH WU = WUsers.pop_back_val()) {
85  if (PHINode *PN = dyn_cast<PHINode>(WU)) {
86  for (int I = 0, E = PN->getNumIncomingValues(); I < E; ++I)
87  if (PN->getIncomingValue(I) == CE) {
88  BasicBlock *PredBB = PN->getIncomingBlock(I);
89  if (PredBB->getTerminator()->getNumSuccessors() > 1)
90  PredBB = SplitEdge(PredBB, PN->getParent());
91  Instruction *InsertPos = PredBB->getTerminator();
92  Instruction *NewInst = CE->getAsInstruction(InsertPos);
93  PN->setOperand(I, NewInst);
94  }
95  } else if (Instruction *Instr = dyn_cast<Instruction>(WU)) {
96  Instruction *NewInst = CE->getAsInstruction(Instr);
97  Instr->replaceUsesOfWith(CE, NewInst);
98  } else {
99  ConstantExpr *CExpr = dyn_cast<ConstantExpr>(WU);
100  if (!CExpr || !replaceConstantExprOp(CExpr, P))
101  return false;
102  }
103  }
104  } while (CE->hasNUsesOrMore(1)); // We need to check because a recursive
105  // sibling may have used 'CE' when getAsInstruction was called.
106  CE->destroyConstant();
107  return true;
108 }
109 
112  for (User *U : GV->users())
113  if (!isa<Instruction>(U))
114  WUsers.push_back(WeakTrackingVH(U));
115  while (!WUsers.empty())
116  if (WeakTrackingVH WU = WUsers.pop_back_val()) {
117  ConstantExpr *CE = dyn_cast<ConstantExpr>(WU);
118  if (!CE || !replaceConstantExprOp(CE, P))
119  return false;
120  }
121  return true;
122 }
123 
124 static bool isZeroLengthArray(Type *Ty) {
125  ArrayType *AT = dyn_cast<ArrayType>(Ty);
126  return AT && (AT->getNumElements() == 0);
127 }
128 
129 bool XCoreLowerThreadLocal::lowerGlobal(GlobalVariable *GV) {
130  Module *M = GV->getParent();
131  if (!GV->isThreadLocal())
132  return false;
133 
134  // Skip globals that we can't lower and leave it for the backend to error.
135  if (!rewriteNonInstructionUses(GV, this) ||
136  !GV->getType()->isSized() || isZeroLengthArray(GV->getType()))
137  return false;
138 
139  // Create replacement global.
140  ArrayType *NewType = createLoweredType(GV->getValueType());
141  Constant *NewInitializer = nullptr;
142  if (GV->hasInitializer())
143  NewInitializer = createLoweredInitializer(NewType,
144  GV->getInitializer());
145  GlobalVariable *NewGV =
146  new GlobalVariable(*M, NewType, GV->isConstant(), GV->getLinkage(),
147  NewInitializer, "", nullptr,
149  GV->getType()->getAddressSpace(),
151 
152  // Update uses.
154  for (unsigned I = 0, E = Users.size(); I != E; ++I) {
155  User *U = Users[I];
156  Instruction *Inst = cast<Instruction>(U);
157  IRBuilder<> Builder(Inst);
159  Intrinsic::xcore_getid);
160  Value *ThreadID = Builder.CreateCall(GetID, {});
161  Value *Addr = Builder.CreateInBoundsGEP(NewGV->getValueType(), NewGV,
162  {Builder.getInt64(0), ThreadID});
163  U->replaceUsesOfWith(GV, Addr);
164  }
165 
166  // Remove old global.
167  NewGV->takeName(GV);
168  GV->eraseFromParent();
169  return true;
170 }
171 
172 bool XCoreLowerThreadLocal::runOnModule(Module &M) {
173  // Find thread local globals.
174  bool MadeChange = false;
175  SmallVector<GlobalVariable *, 16> ThreadLocalGlobals;
176  for (GlobalVariable &GV : M.globals())
177  if (GV.isThreadLocal())
178  ThreadLocalGlobals.push_back(&GV);
179  for (unsigned I = 0, E = ThreadLocalGlobals.size(); I != E; ++I) {
180  MadeChange |= lowerGlobal(ThreadLocalGlobals[I]);
181  }
182  return MadeChange;
183 }
i
i
Definition: README.txt:29
llvm::GlobalVariable::eraseFromParent
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition: Globals.cpp:430
llvm::Type::isSized
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition: Type.h:263
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::SmallVectorImpl::erase
iterator erase(const_iterator CI)
Definition: SmallVector.h:714
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
NoFolder.h
llvm::WeakTrackingVH
Value handle that is nullable, but tries to track the Value.
Definition: ValueHandle.h:204
llvm::Intrinsic::getDeclaration
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
Definition: Function.cpp:1399
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:238
llvm::BasicBlock::getParent
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:107
llvm::GlobalValue::getLinkage
LinkageTypes getLinkage() const
Definition: GlobalValue.h:467
llvm::Function
Definition: Function.h:62
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
Pass.h
XCore.h
rewriteNonInstructionUses
static bool rewriteNonInstructionUses(GlobalVariable *GV, Pass *P)
Definition: XCoreLowerThreadLocal.cpp:110
llvm::GlobalValue::NotThreadLocal
@ NotThreadLocal
Definition: GlobalValue.h:179
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1177
llvm::GlobalVariable::isExternallyInitialized
bool isExternallyInitialized() const
Definition: GlobalVariable.h:155
llvm::IRBuilder<>
llvm::GlobalVariable
Definition: GlobalVariable.h:39
llvm::PointerType::getAddressSpace
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:687
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
createLoweredType
static ArrayType * createLoweredType(Type *OriginalType)
Definition: XCoreLowerThreadLocal.cpp:64
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Module.h
llvm::SmallVectorImpl::pop_back_val
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:644
llvm::ArrayType
Class to represent array types.
Definition: DerivedTypes.h:357
llvm::GlobalVariable::hasInitializer
bool hasInitializer() const
Definitions have initializers, declarations don't.
Definition: GlobalVariable.h:91
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
CommandLine.h
llvm::Instruction::getNumSuccessors
unsigned getNumSuccessors() const
Return the number of successors that this instruction has.
Definition: Instruction.cpp:775
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
llvm::ArrayType::getNumElements
uint64_t getNumElements() const
Definition: DerivedTypes.h:369
Constants.h
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::User
Definition: User.h:44
Intrinsics.h
llvm::Instruction
Definition: Instruction.h:45
llvm::cl::opt
Definition: CommandLine.h:1432
llvm::GlobalVariable::getInitializer
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Definition: GlobalVariable.h:135
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
llvm::GlobalValue::getParent
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:578
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:79
replaceConstantExprOp
static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P)
Definition: XCoreLowerThreadLocal.cpp:78
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:441
IRBuilder.h
llvm::User::replaceUsesOfWith
void replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Definition: User.cpp:21
llvm::GlobalValue::isThreadLocal
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
Definition: GlobalValue.h:244
llvm::initializeXCoreLowerThreadLocalPass
void initializeXCoreLowerThreadLocalPass(PassRegistry &p)
llvm::ArrayType::get
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:640
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:650
MaxThreads
static cl::opt< unsigned > MaxThreads("xcore-max-threads", cl::Optional, cl::desc("Maximum number of threads (for emulation thread-local storage)"), cl::Hidden, cl::value_desc("number"), cl::init(8))
isZeroLengthArray
static bool isZeroLengthArray(Type *Ty)
Definition: XCoreLowerThreadLocal.cpp:124
ValueHandle.h
llvm::BasicBlock::getTerminator
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition: BasicBlock.cpp:152
llvm::cl::Optional
@ Optional
Definition: CommandLine.h:119
llvm::SplitEdge
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the edge connecting the specified blocks, and return the newly created basic block between From...
Definition: BasicBlockUtils.cpp:518
llvm::ConstantExpr
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:971
GlobalVariable.h
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1590
llvm::ConstantArray::get
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1295
llvm::unique
auto unique(Range &&R, Predicate P)
Definition: STLExtras.h:1802
llvm::createXCoreLowerThreadLocalPass
ModulePass * createXCoreLowerThreadLocalPass()
llvm::cl::value_desc
Definition: CommandLine.h:422
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:91
createLoweredInitializer
static Constant * createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer)
Definition: XCoreLowerThreadLocal.cpp:69
llvm::GlobalVariable::isConstant
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
Definition: GlobalVariable.h:152
INITIALIZE_PASS
INITIALIZE_PASS(XCoreLowerThreadLocal, "xcore-lower-thread-local", "Lower thread local variables", false, false) ModulePass *llvm
Definition: XCoreLowerThreadLocal.cpp:57
Users
iv Induction Variable Users
Definition: IVUsers.cpp:52
llvm::PHINode
Definition: Instructions.h:2657
llvm::GlobalValue::getType
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:271
DerivedTypes.h
llvm::GlobalValue::getValueType
Type * getValueType() const
Definition: GlobalValue.h:273
llvm::Value::takeName
void takeName(Value *V)
Transfer the name from V to this value.
Definition: Value.cpp:382
llvm::cl::desc
Definition: CommandLine.h:412
BasicBlockUtils.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::Value::users
iterator_range< user_iterator > users()
Definition: Value.h:421
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38