LLVM  9.0.0svn
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/Module.h"
22 #include "llvm/IR/NoFolder.h"
23 #include "llvm/IR/ValueHandle.h"
24 #include "llvm/Pass.h"
27 
28 #define DEBUG_TYPE "xcore-lower-thread-local"
29 
30 using namespace llvm;
31 
33  "xcore-max-threads", cl::Optional,
34  cl::desc("Maximum number of threads (for emulation thread-local storage)"),
35  cl::Hidden, cl::value_desc("number"), cl::init(8));
36 
37 namespace {
38  /// Lowers thread local variables on the XCore. Each thread local variable is
39  /// expanded to an array of n elements indexed by the thread ID where n is the
40  /// fixed number hardware threads supported by the device.
41  struct XCoreLowerThreadLocal : public ModulePass {
42  static char ID;
43 
44  XCoreLowerThreadLocal() : ModulePass(ID) {
46  }
47 
48  bool lowerGlobal(GlobalVariable *GV);
49 
50  bool runOnModule(Module &M) override;
51  };
52 }
53 
55 
56 INITIALIZE_PASS(XCoreLowerThreadLocal, "xcore-lower-thread-local",
57  "Lower thread local variables", false, false)
58 
60  return new XCoreLowerThreadLocal();
61 }
62 
63 static ArrayType *createLoweredType(Type *OriginalType) {
64  return ArrayType::get(OriginalType, MaxThreads);
65 }
66 
67 static Constant *
68 createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer) {
70  for (unsigned i = 0; i != MaxThreads; ++i) {
71  Elements[i] = OriginalInitializer;
72  }
73  return ConstantArray::get(NewType, Elements);
74 }
75 
76 static Instruction *
78  IRBuilder<NoFolder> Builder(Instr);
79  unsigned OpCode = CE->getOpcode();
80  switch (OpCode) {
81  case Instruction::GetElementPtr: {
82  SmallVector<Value *,4> CEOpVec(CE->op_begin(), CE->op_end());
83  ArrayRef<Value *> CEOps(CEOpVec);
84  return dyn_cast<Instruction>(Builder.CreateInBoundsGEP(
85  cast<GEPOperator>(CE)->getSourceElementType(), CEOps[0],
86  CEOps.slice(1)));
87  }
88  case Instruction::Add:
89  case Instruction::Sub:
90  case Instruction::Mul:
91  case Instruction::UDiv:
92  case Instruction::SDiv:
93  case Instruction::FDiv:
94  case Instruction::URem:
95  case Instruction::SRem:
96  case Instruction::FRem:
97  case Instruction::Shl:
98  case Instruction::LShr:
99  case Instruction::AShr:
100  case Instruction::And:
101  case Instruction::Or:
102  case Instruction::Xor:
103  return dyn_cast<Instruction>(
104  Builder.CreateBinOp((Instruction::BinaryOps)OpCode,
105  CE->getOperand(0), CE->getOperand(1),
106  CE->getName()));
107  case Instruction::Trunc:
108  case Instruction::ZExt:
109  case Instruction::SExt:
110  case Instruction::FPToUI:
111  case Instruction::FPToSI:
112  case Instruction::UIToFP:
113  case Instruction::SIToFP:
114  case Instruction::FPTrunc:
115  case Instruction::FPExt:
116  case Instruction::PtrToInt:
117  case Instruction::IntToPtr:
118  case Instruction::BitCast:
119  return dyn_cast<Instruction>(
120  Builder.CreateCast((Instruction::CastOps)OpCode,
121  CE->getOperand(0), CE->getType(),
122  CE->getName()));
123  default:
124  llvm_unreachable("Unhandled constant expression!\n");
125  }
126 }
127 
129  do {
131  llvm::sort(WUsers);
132  WUsers.erase(std::unique(WUsers.begin(), WUsers.end()), WUsers.end());
133  while (!WUsers.empty())
134  if (WeakTrackingVH WU = WUsers.pop_back_val()) {
135  if (PHINode *PN = dyn_cast<PHINode>(WU)) {
136  for (int I = 0, E = PN->getNumIncomingValues(); I < E; ++I)
137  if (PN->getIncomingValue(I) == CE) {
138  BasicBlock *PredBB = PN->getIncomingBlock(I);
139  if (PredBB->getTerminator()->getNumSuccessors() > 1)
140  PredBB = SplitEdge(PredBB, PN->getParent());
141  Instruction *InsertPos = PredBB->getTerminator();
142  Instruction *NewInst = createReplacementInstr(CE, InsertPos);
143  PN->setOperand(I, NewInst);
144  }
145  } else if (Instruction *Instr = dyn_cast<Instruction>(WU)) {
146  Instruction *NewInst = createReplacementInstr(CE, Instr);
147  Instr->replaceUsesOfWith(CE, NewInst);
148  } else {
149  ConstantExpr *CExpr = dyn_cast<ConstantExpr>(WU);
150  if (!CExpr || !replaceConstantExprOp(CExpr, P))
151  return false;
152  }
153  }
154  } while (CE->hasNUsesOrMore(1)); // We need to check because a recursive
155  // sibling may have used 'CE' when createReplacementInstr was called.
156  CE->destroyConstant();
157  return true;
158 }
159 
162  for (User *U : GV->users())
163  if (!isa<Instruction>(U))
164  WUsers.push_back(WeakTrackingVH(U));
165  while (!WUsers.empty())
166  if (WeakTrackingVH WU = WUsers.pop_back_val()) {
168  if (!CE || !replaceConstantExprOp(CE, P))
169  return false;
170  }
171  return true;
172 }
173 
174 static bool isZeroLengthArray(Type *Ty) {
175  ArrayType *AT = dyn_cast<ArrayType>(Ty);
176  return AT && (AT->getNumElements() == 0);
177 }
178 
179 bool XCoreLowerThreadLocal::lowerGlobal(GlobalVariable *GV) {
180  Module *M = GV->getParent();
181  if (!GV->isThreadLocal())
182  return false;
183 
184  // Skip globals that we can't lower and leave it for the backend to error.
185  if (!rewriteNonInstructionUses(GV, this) ||
186  !GV->getType()->isSized() || isZeroLengthArray(GV->getType()))
187  return false;
188 
189  // Create replacement global.
190  ArrayType *NewType = createLoweredType(GV->getValueType());
191  Constant *NewInitializer = nullptr;
192  if (GV->hasInitializer())
193  NewInitializer = createLoweredInitializer(NewType,
194  GV->getInitializer());
195  GlobalVariable *NewGV =
196  new GlobalVariable(*M, NewType, GV->isConstant(), GV->getLinkage(),
197  NewInitializer, "", nullptr,
199  GV->getType()->getAddressSpace(),
201 
202  // Update uses.
204  for (unsigned I = 0, E = Users.size(); I != E; ++I) {
205  User *U = Users[I];
206  Instruction *Inst = cast<Instruction>(U);
207  IRBuilder<> Builder(Inst);
209  Intrinsic::xcore_getid);
210  Value *ThreadID = Builder.CreateCall(GetID, {});
211  Value *Addr = Builder.CreateInBoundsGEP(NewGV->getValueType(), NewGV,
212  {Builder.getInt64(0), ThreadID});
213  U->replaceUsesOfWith(GV, Addr);
214  }
215 
216  // Remove old global.
217  NewGV->takeName(GV);
218  GV->eraseFromParent();
219  return true;
220 }
221 
222 bool XCoreLowerThreadLocal::runOnModule(Module &M) {
223  // Find thread local globals.
224  bool MadeChange = false;
225  SmallVector<GlobalVariable *, 16> ThreadLocalGlobals;
226  for (GlobalVariable &GV : M.globals())
227  if (GV.isThreadLocal())
228  ThreadLocalGlobals.push_back(&GV);
229  for (unsigned I = 0, E = ThreadLocalGlobals.size(); I != E; ++I) {
230  MadeChange |= lowerGlobal(ThreadLocalGlobals[I]);
231  }
232  return MadeChange;
233 }
Pass interface - Implemented by all &#39;passes&#39;.
Definition: Pass.h:80
Value * CreateInBoundsGEP(Value *Ptr, ArrayRef< Value *> IdxList, const Twine &Name="")
Definition: IRBuilder.h:1512
unsigned getOpcode() const
Return the opcode at the root of this constant expression.
Definition: Constants.h:1209
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:1333
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
bool isSized(SmallPtrSetImpl< Type *> *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition: Type.h:264
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:137
iv Induction Variable Users
Definition: IVUsers.cpp:51
void initializeXCoreLowerThreadLocalPass(PassRegistry &p)
op_iterator op_begin()
Definition: User.h:229
static Constant * get(ArrayType *T, ArrayRef< Constant *> V)
Definition: Constants.cpp:992
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Split the edge connecting specified block.
ModulePass * createXCoreLowerThreadLocalPass()
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:742
uint64_t getNumElements() const
Definition: DerivedTypes.h:390
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:888
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:244
Value handle that is nullable, but tries to track the Value.
Definition: ValueHandle.h:181
Class to represent array types.
Definition: DerivedTypes.h:400
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
LinkageTypes getLinkage() const
Definition: GlobalValue.h:450
INITIALIZE_PASS(XCoreLowerThreadLocal, "xcore-lower-thread-local", "Lower thread local variables", false, false) ModulePass *llvm
void takeName(Value *V)
Transfer the name from V to this value.
Definition: Value.cpp:291
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:1022
unsigned getNumSuccessors() const
Return the number of successors that this instruction has.
Value * getOperand(unsigned i) const
Definition: User.h:169
void replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Definition: User.cpp:20
#define P(N)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:432
bool hasNUsesOrMore(unsigned N) const
Return true if this value has N users or more.
Definition: Value.cpp:135
LLVM Basic Block Representation.
Definition: BasicBlock.h:57
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
static bool isZeroLengthArray(Type *Ty)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
Definition: Constant.h:41
This file contains the declarations for the subclasses of Constant, which represent the different fla...
void eraseFromParent()
eraseFromParent - This method unlinks &#39;this&#39; from the containing module and deletes it...
Definition: Globals.cpp:358
op_iterator op_end()
Definition: User.h:231
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:526
static Instruction * createReplacementInstr(ConstantExpr *CE, Instruction *Instr)
size_t size() const
Definition: SmallVector.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static ArrayType * createLoweredType(Type *OriginalType)
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1115
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:841
Module.h This file contains the declarations for the Module class.
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:374
static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P)
iterator_range< user_iterator > users()
Definition: Value.h:399
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:55
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:214
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:106
#define I(x, y, z)
Definition: MD5.cpp:58
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:224
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:580
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:332
static Constant * createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer)
Type * getValueType() const
Definition: GlobalValue.h:275
void destroyConstant()
Called if some element of this constant is no longer valid.
Definition: Constants.cpp:371
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:1804
user_iterator user_begin()
Definition: Value.h:375
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))
static bool rewriteNonInstructionUses(GlobalVariable *GV, Pass *P)
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:565
LLVM Value Representation.
Definition: Value.h:72
bool hasInitializer() const
Definitions have initializers, declarations don&#39;t.
bool isThreadLocal() const
If the value is "Thread Local", its value isn&#39;t shared by the threads.
Definition: GlobalValue.h:246
iterator_range< global_iterator > globals()
Definition: Module.h:587
bool isExternallyInitialized() const
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:273
user_iterator user_end()
Definition: Value.h:383