From 71537c178303c9d3f44aa0b9e0de167a7d670c77 Mon Sep 17 00:00:00 2001 From: Robert Lytton Date: Mon, 9 Sep 2013 10:42:11 +0000 Subject: XCore handling of thread local lowering Fix XCoreLowerThreadLocal trying to initialise globals which have no initializer. Add handling of const expressions containing thread local variables. These need to be replaced with instructions, as the thread ID is used to access the thread local variable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190300 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/XCore/XCoreLowerThreadLocal.cpp | 103 ++++++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 9 deletions(-) (limited to 'lib/Target/XCore') diff --git a/lib/Target/XCore/XCoreLowerThreadLocal.cpp b/lib/Target/XCore/XCoreLowerThreadLocal.cpp index 2e328b4e34..5a83282514 100644 --- a/lib/Target/XCore/XCoreLowerThreadLocal.cpp +++ b/lib/Target/XCore/XCoreLowerThreadLocal.cpp @@ -22,6 +22,8 @@ #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/NoFolder.h" +#include "llvm/Support/ValueHandle.h" #define DEBUG_TYPE "xcore-lower-thread-local" @@ -71,13 +73,94 @@ 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(*UI)) - return true; +static Instruction * +createReplacementInstr(ConstantExpr *CE, Instruction *Instr) { + IRBuilder Builder(Instr); + unsigned OpCode = CE->getOpcode(); + switch (OpCode) { + case Instruction::GetElementPtr: { + SmallVector CEOpVec(CE->op_begin(), CE->op_end()); + ArrayRef CEOps(CEOpVec); + return dyn_cast(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( + 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( + Builder.CreateCast((Instruction::CastOps)OpCode, + CE->getOperand(0), CE->getType(), + CE->getName())); + default: + assert(0 && "Unhandled constant expression!\n"); + } +} + +static bool replaceConstantExprOp(ConstantExpr *CE) { + do { + SmallVector WUsers; + for (Value::use_iterator I = CE->use_begin(), E = CE->use_end(); + I != E; ++I) + WUsers.push_back(WeakVH(*I)); + while (!WUsers.empty()) + if (WeakVH WU = WUsers.pop_back_val()) { + if (Instruction *Instr = dyn_cast(WU)) { + Instruction *NewInst = createReplacementInstr(CE, Instr); + assert(NewInst && "Must build an instruction\n"); + // If NewInst uses a CE being handled in an earlier recursion the + // earlier recursion's do-while-hasNUsesOrMore(1) will run again. + Instr->replaceUsesOfWith(CE, NewInst); + } else { + ConstantExpr *CExpr = dyn_cast(WU); + if (!CExpr || !replaceConstantExprOp(CExpr)) + return false; + } + } + } while (CE->hasNUsesOrMore(1)); // Does a recursion's NewInst use CE? + CE->destroyConstant(); + return true; +} - return false; +static bool rewriteNonInstructionUses(GlobalVariable *GV) { + SmallVector WUsers; + for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I) + if (!isa(*I)) + WUsers.push_back(WeakVH(*I)); + while (!WUsers.empty()) + if (WeakVH WU = WUsers.pop_back_val()) { + ConstantExpr *CE = dyn_cast(WU); + if (!CE || !replaceConstantExprOp(CE)) + return false; + } + return true; } static bool isZeroLengthArray(Type *Ty) { @@ -92,14 +175,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) || !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, -- cgit v1.2.3