29 #define DEBUG_TYPE "xcore-lower-thread-local"
35 cl::desc(
"Maximum number of threads (for emulation thread-local storage)"),
42 struct XCoreLowerThreadLocal :
public ModulePass {
51 bool runOnModule(
Module &M)
override;
58 "Lower thread local variables",
false,
false)
61 return new XCoreLowerThreadLocal();
72 Elements[
i] = OriginalInitializer;
82 case Instruction::GetElementPtr: {
86 cast<GEPOperator>(CE)->getSourceElementType(), CEOps[0],
90 case Instruction::Sub:
91 case Instruction::Mul:
92 case Instruction::UDiv:
93 case Instruction::SDiv:
94 case Instruction::FDiv:
95 case Instruction::URem:
96 case Instruction::SRem:
97 case Instruction::FRem:
98 case Instruction::Shl:
99 case Instruction::LShr:
100 case Instruction::AShr:
108 case Instruction::Trunc:
109 case Instruction::ZExt:
110 case Instruction::SExt:
111 case Instruction::FPToUI:
112 case Instruction::FPToSI:
113 case Instruction::UIToFP:
114 case Instruction::SIToFP:
115 case Instruction::FPTrunc:
116 case Instruction::FPExt:
117 case Instruction::PtrToInt:
118 case Instruction::IntToPtr:
119 case Instruction::BitCast:
132 std::sort(WUsers.begin(), WUsers.end());
133 WUsers.
erase(std::unique(WUsers.begin(), WUsers.end()), WUsers.end());
134 while (!WUsers.empty())
135 if (
WeakVH WU = WUsers.pop_back_val()) {
136 if (
PHINode *PN = dyn_cast<PHINode>(WU)) {
137 for (
int I = 0,
E = PN->getNumIncomingValues();
I <
E; ++
I)
138 if (PN->getIncomingValue(
I) == CE) {
144 PN->setOperand(
I, NewInst);
146 }
else if (
Instruction *Instr = dyn_cast<Instruction>(WU)) {
148 Instr->replaceUsesOfWith(CE, NewInst);
164 if (!isa<Instruction>(U))
166 while (!WUsers.
empty())
198 NewInitializer,
"",
nullptr,
205 for (
unsigned I = 0,
E =
Users.size();
I !=
E; ++
I) {
210 Intrinsic::xcore_getid);
211 Value *ThreadID = Builder.CreateCall(GetID, {});
213 {Builder.getInt64(0), ThreadID});
223 bool XCoreLowerThreadLocal::runOnModule(
Module &M) {
225 bool MadeChange =
false;
230 for (
unsigned I = 0,
E = ThreadLocalGlobals.
size();
I !=
E; ++
I) {
231 MadeChange |= lowerGlobal(ThreadLocalGlobals[
I]);
Pass interface - Implemented by all 'passes'.
void push_back(const T &Elt)
LinkageTypes getLinkage() const
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)
A Module instance is used to store all the information related to an LLVM module. ...
Type * getValueType() const
const Function * getParent() const
Return the enclosing method, or null if none.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
iv Induction Variable Users
void initializeXCoreLowerThreadLocalPass(PassRegistry &p)
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
unsigned getOpcode() const
Return the opcode at the root of this constant expression.
StringRef getName() const
Return a constant reference to the value's name.
ModulePass * createXCoreLowerThreadLocalPass()
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void eraseFromParent() override
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
LLVM_NODISCARD bool empty() const
A constant value that is initialized with an expression using other constant values.
Value handle that is nullable, but tries to track the Value.
Class to represent array types.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
void takeName(Value *V)
Transfer the name from V to this value.
Value * CreateInBoundsGEP(Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
void replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
unsigned getNumSuccessors() const
Return the number of successors that this terminator has.
initializer< Ty > init(const Ty &Val)
bool isExternallyInitialized() const
INITIALIZE_PASS(XCoreLowerThreadLocal,"xcore-lower-thread-local","Lower thread local variables", false, false) ModulePass *llvm
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
static bool isZeroLengthArray(Type *Ty)
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
APInt Or(const APInt &LHS, const APInt &RHS)
Bitwise OR function for APInt.
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
APInt Xor(const APInt &LHS, const APInt &RHS)
Bitwise XOR function for APInt.
uint64_t getNumElements() const
Value * getOperand(unsigned i) const
static Instruction * createReplacementInstr(ConstantExpr *CE, Instruction *Instr)
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
iterator erase(const_iterator CI)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static ArrayType * createLoweredType(Type *OriginalType)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
LLVM_NODISCARD T pop_back_val()
static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P)
bool hasInitializer() const
Definitions have initializers, declarations don't.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
iterator_range< user_iterator > users()
APInt And(const APInt &LHS, const APInt &RHS)
Bitwise AND function for APInt.
PointerType * getType() const
Global values are always pointers.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
static Constant * createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer)
void destroyConstant()
Called if some element of this constant is no longer valid.
bool hasNUsesOrMore(unsigned N) const
Return true if this value has N users or more.
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="")
user_iterator user_begin()
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...
LLVM Value Representation.
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr)
Split the edge connecting specified block.
iterator_range< global_iterator > globals()