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);
58 "Lower thread local variables",
false,
false)
61 return new XCoreLowerThreadLocal();
72 Elements[i] = OriginalInitializer;
82 case Instruction::GetElementPtr: {
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:
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:
134 std::sort(WUsers.
begin(), WUsers.
end());
136 while (!WUsers.
empty())
138 if (
PHINode *PN = dyn_cast<PHINode>(WU)) {
139 for (
int I = 0, E = PN->getNumIncomingValues();
I < E; ++
I)
140 if (PN->getIncomingValue(
I) == CE) {
146 PN->setOperand(
I, NewInst);
148 }
else if (
Instruction *Instr = dyn_cast<Instruction>(WU)) {
150 Instr->replaceUsesOfWith(CE, NewInst);
166 if (!isa<Instruction>(*
I))
168 while (!WUsers.
empty())
207 for (
unsigned I = 0, E =
Users.size();
I != E; ++
I) {
213 Value *ThreadID = Builder.CreateCall(GetID);
217 Value *Addr = Builder.CreateInBoundsGEP(NewGV, Indices);
227 bool XCoreLowerThreadLocal::runOnModule(
Module &M) {
229 bool MadeChange =
false;
237 for (
unsigned I = 0, E = ThreadLocalGlobals.
size();
I != E; ++
I) {
238 MadeChange |= lowerGlobal(ThreadLocalGlobals[
I]);
void push_back(const T &Elt)
LinkageTypes getLinkage() const
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="")
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P)
static PassRegistry * getPassRegistry()
The main container class for the LLVM Intermediate Representation.
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
const Function * getParent() const
Return the enclosing method, or null if none.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
static IntegerType * getInt64Ty(LLVMContext &C)
iv Induction Variable Users
void initializeXCoreLowerThreadLocalPass(PassRegistry &p)
const Constant * getInitializer() const
unsigned getOpcode() const
getOpcode - Return the opcode at the root of this constant expression
static Constant * getNullValue(Type *Ty)
StringRef getName() const
ModulePass * createXCoreLowerThreadLocalPass()
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val()
#define llvm_unreachable(msg)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
ID
LLVM Calling Convention Representation.
global_iterator global_begin()
virtual void destroyConstant()
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Type * getElementType() const
void replaceUsesOfWith(Value *From, Value *To)
unsigned getNumSuccessors() const
initializer< Ty > init(const Ty &Val)
bool isExternallyInitialized() const
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="")
INITIALIZE_PASS(XCoreLowerThreadLocal,"xcore-lower-thread-local","Lower thread local variables", false, false) ModulePass *llvm
LLVM Basic Block Representation.
static bool isZeroLengthArray(Type *Ty)
LLVM Constant Representation.
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.
virtual void eraseFromParent()
uint64_t getNumElements() const
Value * getOperand(unsigned i) const
static Instruction * createReplacementInstr(ConstantExpr *CE, Instruction *Instr)
Value * CreateInBoundsGEP(Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
iterator erase(iterator I)
static ArrayType * createLoweredType(Type *OriginalType)
global_iterator global_end()
static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P)
bool hasInitializer() const
APInt And(const APInt &LHS, const APInt &RHS)
Bitwise AND function for APInt.
PointerType * getType() const
getType - 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...
static ArrayType * get(Type *ElementType, uint64_t NumElements)
static Constant * createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer)
bool hasNUsesOrMore(unsigned N) const
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)
LLVM Value Representation.
LLVMContext & getContext() const