diff options
Diffstat (limited to 'lib/Target/XCore/XCoreLowerThreadLocal.cpp')
-rw-r--r-- | lib/Target/XCore/XCoreLowerThreadLocal.cpp | 114 |
1 files changed, 105 insertions, 9 deletions
diff --git a/lib/Target/XCore/XCoreLowerThreadLocal.cpp b/lib/Target/XCore/XCoreLowerThreadLocal.cpp index 2e328b4e3441a..afce753dec5c9 100644 --- a/lib/Target/XCore/XCoreLowerThreadLocal.cpp +++ b/lib/Target/XCore/XCoreLowerThreadLocal.cpp @@ -22,6 +22,9 @@ #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/NoFolder.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" #define DEBUG_TYPE "xcore-lower-thread-local" @@ -71,13 +74,104 @@ createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer) { return ConstantArray::get(NewType, Elements); } -static bool hasNonInstructionUse(GlobalVariable *GV) { - for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); UI != E; - ++UI) - if (!isa<Instruction>(*UI)) - return true; +static Instruction * +createReplacementInstr(ConstantExpr *CE, Instruction *Instr) { + IRBuilder<true,NoFolder> Builder(Instr); + unsigned OpCode = CE->getOpcode(); + switch (OpCode) { + case Instruction::GetElementPtr: { + SmallVector<Value *,4> CEOpVec(CE->op_begin(), CE->op_end()); + ArrayRef<Value *> CEOps(CEOpVec); + return dyn_cast<Instruction>(Builder.CreateInBoundsGEP(CEOps[0], + CEOps.slice(1))); + } + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::FDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + return dyn_cast<Instruction>( + Builder.CreateBinOp((Instruction::BinaryOps)OpCode, + CE->getOperand(0), CE->getOperand(1), + CE->getName())); + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::PtrToInt: + case Instruction::IntToPtr: + case Instruction::BitCast: + return dyn_cast<Instruction>( + Builder.CreateCast((Instruction::CastOps)OpCode, + CE->getOperand(0), CE->getType(), + CE->getName())); + default: + llvm_unreachable("Unhandled constant expression!\n"); + } +} + +static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P) { + do { + SmallVector<WeakVH,8> WUsers; + for (Value::use_iterator I = CE->use_begin(), E = CE->use_end(); + I != E; ++I) + WUsers.push_back(WeakVH(*I)); + std::sort(WUsers.begin(), WUsers.end()); + WUsers.erase(std::unique(WUsers.begin(), WUsers.end()), WUsers.end()); + while (!WUsers.empty()) + if (WeakVH WU = WUsers.pop_back_val()) { + if (PHINode *PN = dyn_cast<PHINode>(WU)) { + for (int I = 0, E = PN->getNumIncomingValues(); I < E; ++I) + if (PN->getIncomingValue(I) == CE) { + BasicBlock *PredBB = PN->getIncomingBlock(I); + if (PredBB->getTerminator()->getNumSuccessors() > 1) + PredBB = SplitEdge(PredBB, PN->getParent(), P); + Instruction *InsertPos = PredBB->getTerminator(); + Instruction *NewInst = createReplacementInstr(CE, InsertPos); + PN->setOperand(I, NewInst); + } + } else if (Instruction *Instr = dyn_cast<Instruction>(WU)) { + Instruction *NewInst = createReplacementInstr(CE, Instr); + Instr->replaceUsesOfWith(CE, NewInst); + } else { + ConstantExpr *CExpr = dyn_cast<ConstantExpr>(WU); + if (!CExpr || !replaceConstantExprOp(CExpr, P)) + return false; + } + } + } while (CE->hasNUsesOrMore(1)); // We need to check becasue a recursive + // sibbling may have used 'CE' when createReplacementInstr was called. + CE->destroyConstant(); + return true; +} - return false; +static bool rewriteNonInstructionUses(GlobalVariable *GV, Pass *P) { + SmallVector<WeakVH,8> WUsers; + for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I) + if (!isa<Instruction>(*I)) + WUsers.push_back(WeakVH(*I)); + while (!WUsers.empty()) + if (WeakVH WU = WUsers.pop_back_val()) { + ConstantExpr *CE = dyn_cast<ConstantExpr>(WU); + if (!CE || !replaceConstantExprOp(CE, P)) + return false; + } + return true; } static bool isZeroLengthArray(Type *Ty) { @@ -92,14 +186,16 @@ bool XCoreLowerThreadLocal::lowerGlobal(GlobalVariable *GV) { return false; // Skip globals that we can't lower and leave it for the backend to error. - if (hasNonInstructionUse(GV) || + if (!rewriteNonInstructionUses(GV, this) || !GV->getType()->isSized() || isZeroLengthArray(GV->getType())) return false; // Create replacement global. ArrayType *NewType = createLoweredType(GV->getType()->getElementType()); - Constant *NewInitializer = createLoweredInitializer(NewType, - GV->getInitializer()); + Constant *NewInitializer = 0; + if (GV->hasInitializer()) + NewInitializer = createLoweredInitializer(NewType, + GV->getInitializer()); GlobalVariable *NewGV = new GlobalVariable(*M, NewType, GV->isConstant(), GV->getLinkage(), NewInitializer, "", 0, GlobalVariable::NotThreadLocal, |