LLVM  13.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"
25 #include "llvm/IR/ValueHandle.h"
26 #include "llvm/Pass.h"
29 
30 #define DEBUG_TYPE "xcore-lower-thread-local"
31 
32 using namespace llvm;
33 
35  "xcore-max-threads", cl::Optional,
36  cl::desc("Maximum number of threads (for emulation thread-local storage)"),
37  cl::Hidden, cl::value_desc("number"), cl::init(8));
38 
39 namespace {
40  /// Lowers thread local variables on the XCore. Each thread local variable is
41  /// expanded to an array of n elements indexed by the thread ID where n is the
42  /// fixed number hardware threads supported by the device.
43  struct XCoreLowerThreadLocal : public ModulePass {
44  static char ID;
45 
46  XCoreLowerThreadLocal() : ModulePass(ID) {
48  }
49 
50  bool lowerGlobal(GlobalVariable *GV);
51 
52  bool runOnModule(Module &M) override;
53  };
54 }
55 
57 
58 INITIALIZE_PASS(XCoreLowerThreadLocal, "xcore-lower-thread-local",
59  "Lower thread local variables", false, false)
60 
62  return new XCoreLowerThreadLocal();
63 }
64 
65 static ArrayType *createLoweredType(Type *OriginalType) {
66  return ArrayType::get(OriginalType, MaxThreads);
67 }
68 
69 static Constant *
70 createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer) {
72  for (unsigned i = 0; i != MaxThreads; ++i) {
73  Elements[i] = OriginalInitializer;
74  }
75  return ConstantArray::get(NewType, Elements);
76 }
77 
78 
80  do {
81  SmallVector<WeakTrackingVH, 8> WUsers(CE->users());
82  llvm::sort(WUsers);
83  WUsers.erase(std::unique(WUsers.begin(), WUsers.end()), WUsers.end());
84  while (!WUsers.empty())
85  if (WeakTrackingVH WU = WUsers.pop_back_val()) {
86  if (PHINode *PN = dyn_cast<PHINode>(WU)) {
87  for (int I = 0, E = PN->getNumIncomingValues(); I < E; ++I)
88  if (PN->getIncomingValue(I) == CE) {
89  BasicBlock *PredBB = PN->getIncomingBlock(I);
90  if (PredBB->getTerminator()->getNumSuccessors() > 1)
91  PredBB = SplitEdge(PredBB, PN->getParent());
92  Instruction *InsertPos = PredBB->getTerminator();
93  Instruction *NewInst = createReplacementInstr(CE, InsertPos);
94  PN->setOperand(I, NewInst);
95  }
96  } else if (Instruction *Instr = dyn_cast<Instruction>(WU)) {
97  Instruction *NewInst = createReplacementInstr(CE, Instr);
98  Instr->replaceUsesOfWith(CE, NewInst);
99  } else {
100  ConstantExpr *CExpr = dyn_cast<ConstantExpr>(WU);
101  if (!CExpr || !replaceConstantExprOp(CExpr, P))
102  return false;
103  }
104  }
105  } while (CE->hasNUsesOrMore(1)); // We need to check because a recursive
106  // sibling may have used 'CE' when createReplacementInstr was called.
107  CE->destroyConstant();
108  return true;
109 }
110 
113  for (User *U : GV->users())
114  if (!isa<Instruction>(U))
115  WUsers.push_back(WeakTrackingVH(U));
116  while (!WUsers.empty())
117  if (WeakTrackingVH WU = WUsers.pop_back_val()) {
118  ConstantExpr *CE = dyn_cast<ConstantExpr>(WU);
119  if (!CE || !replaceConstantExprOp(CE, P))
120  return false;
121  }
122  return true;
123 }
124 
125 static bool isZeroLengthArray(Type *Ty) {
126  ArrayType *AT = dyn_cast<ArrayType>(Ty);
127  return AT && (AT->getNumElements() == 0);
128 }
129 
130 bool XCoreLowerThreadLocal::lowerGlobal(GlobalVariable *GV) {
131  Module *M = GV->getParent();
132  if (!GV->isThreadLocal())
133  return false;
134 
135  // Skip globals that we can't lower and leave it for the backend to error.
136  if (!rewriteNonInstructionUses(GV, this) ||
137  !GV->getType()->isSized() || isZeroLengthArray(GV->getType()))
138  return false;
139 
140  // Create replacement global.
141  ArrayType *NewType = createLoweredType(GV->getValueType());
142  Constant *NewInitializer = nullptr;
143  if (GV->hasInitializer())
144  NewInitializer = createLoweredInitializer(NewType,
145  GV->getInitializer());
146  GlobalVariable *NewGV =
147  new GlobalVariable(*M, NewType, GV->isConstant(), GV->getLinkage(),
148  NewInitializer, "", nullptr,
150  GV->getType()->getAddressSpace(),
152 
153  // Update uses.
155  for (unsigned I = 0, E = Users.size(); I != E; ++I) {
156  User *U = Users[I];
157  Instruction *Inst = cast<Instruction>(U);
158  IRBuilder<> Builder(Inst);
160  Intrinsic::xcore_getid);
161  Value *ThreadID = Builder.CreateCall(GetID, {});
162  Value *Addr = Builder.CreateInBoundsGEP(NewGV->getValueType(), NewGV,
163  {Builder.getInt64(0), ThreadID});
164  U->replaceUsesOfWith(GV, Addr);
165  }
166 
167  // Remove old global.
168  NewGV->takeName(GV);
169  GV->eraseFromParent();
170  return true;
171 }
172 
173 bool XCoreLowerThreadLocal::runOnModule(Module &M) {
174  // Find thread local globals.
175  bool MadeChange = false;
176  SmallVector<GlobalVariable *, 16> ThreadLocalGlobals;
177  for (GlobalVariable &GV : M.globals())
178  if (GV.isThreadLocal())
179  ThreadLocalGlobals.push_back(&GV);
180  for (unsigned I = 0, E = ThreadLocalGlobals.size(); I != E; ++I) {
181  MadeChange |= lowerGlobal(ThreadLocalGlobals[I]);
182  }
183  return MadeChange;
184 }
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:385
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:272
llvm
Definition: AllocatorList.h:23
llvm::SmallVectorImpl::erase
iterator erase(const_iterator CI)
Definition: SmallVector.h:704
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:1329
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:461
llvm::Function
Definition: Function.h:61
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:111
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:1167
llvm::GlobalVariable::isExternallyInitialized
bool isExternallyInitialized() const
Definition: GlobalVariable.h:156
llvm::IRBuilder<>
llvm::GlobalVariable
Definition: GlobalVariable.h:40
llvm::PointerType::getAddressSpace
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:689
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
createLoweredType
static ArrayType * createLoweredType(Type *OriginalType)
Definition: XCoreLowerThreadLocal.cpp:65
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:46
Module.h
llvm::SmallVectorImpl::pop_back_val
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:634
llvm::ArrayType
Class to represent array types.
Definition: DerivedTypes.h:359
llvm::GlobalVariable::hasInitializer
bool hasInitializer() const
Definitions have initializers, declarations don't.
Definition: GlobalVariable.h:92
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:740
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:371
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:1422
llvm::GlobalVariable::getInitializer
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Definition: GlobalVariable.h:136
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:572
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
replaceConstantExprOp
static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P)
Definition: XCoreLowerThreadLocal.cpp:79
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
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:598
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:651
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:125
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:148
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:495
llvm::ConstantExpr
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:931
GlobalVariable.h
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1423
llvm::ConstantArray::get
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1261
llvm::unique
auto unique(Range &&R, Predicate P)
Definition: STLExtras.h:1635
llvm::createXCoreLowerThreadLocalPass
ModulePass * createXCoreLowerThreadLocalPass()
llvm::cl::value_desc
Definition: CommandLine.h:424
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:91
createLoweredInitializer
static Constant * createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer)
Definition: XCoreLowerThreadLocal.cpp:70
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:153
ReplaceConstant.h
INITIALIZE_PASS
INITIALIZE_PASS(XCoreLowerThreadLocal, "xcore-lower-thread-local", "Lower thread local variables", false, false) ModulePass *llvm
Definition: XCoreLowerThreadLocal.cpp:58
Users
iv Induction Variable Users
Definition: IVUsers.cpp:52
llvm::PHINode
Definition: Instructions.h:2600
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:367
llvm::cl::desc
Definition: CommandLine.h:414
BasicBlockUtils.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::Value::users
iterator_range< user_iterator > users()
Definition: Value.h:422
llvm::createReplacementInstr
Instruction * createReplacementInstr(ConstantExpr *CE, Instruction *Instr)
Create a replacement instruction for constant expression CE and insert it before Instr.
Definition: ReplaceConstant.cpp:22
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38