Index: lib/Transforms/NaCl/ExpandI64.cpp |
diff --git a/lib/Transforms/NaCl/ExpandI64.cpp b/lib/Transforms/NaCl/ExpandI64.cpp |
deleted file mode 100644 |
index 63ed955cb4cc38aaec9af608c117bfaf4d1cd579..0000000000000000000000000000000000000000 |
--- a/lib/Transforms/NaCl/ExpandI64.cpp |
+++ /dev/null |
@@ -1,1161 +0,0 @@ |
-//===- ExpandI64.cpp - Expand i64 and wider integer types -------------===// |
-// |
-// The LLVM Compiler Infrastructure |
-// |
-// This file is distributed under the University of Illinois Open Source |
-// License. See LICENSE.TXT for details. |
-// |
-//===------------------------------------------------------------------===// |
-// |
-// This pass expands and lowers all operations on integers i64 and wider |
-// into 32-bit operations that can be handled by JS in a natural way. |
-// |
-// 64-bit variables become pairs of 2 32-bit variables, for the low and |
-// high 32 bit chunks. This happens for both registers and function |
-// arguments. Function return values become a return of the low 32 bits |
-// and a store of the high 32-bits in tempRet0, a global helper variable. |
-// Larger values become more chunks of 32 bits. Currently we require that |
-// types be a multiple of 32 bits. |
-// |
-// Many operations then become simple pairs of operations, for example |
-// bitwise AND becomes and AND of each 32-bit chunk. More complex operations |
-// like addition are lowered into calls into library support code in |
-// Emscripten (i64Add for example). |
-// |
-//===------------------------------------------------------------------===// |
- |
-#include "llvm/ADT/PostOrderIterator.h" |
-#include "llvm/ADT/SmallString.h" |
-#include "llvm/ADT/SmallVector.h" |
-#include "llvm/ADT/StringExtras.h" |
-#include "llvm/Analysis/ConstantFolding.h" |
-#include "llvm/Analysis/InstructionSimplify.h" |
-#include "llvm/IR/CFG.h" |
-#include "llvm/IR/DataLayout.h" |
-#include "llvm/IR/Function.h" |
-#include "llvm/IR/IRBuilder.h" |
-#include "llvm/IR/Instructions.h" |
-#include "llvm/IR/IntrinsicInst.h" |
-#include "llvm/IR/Module.h" |
-#include "llvm/Pass.h" |
-#include "llvm/Analysis/TargetLibraryInfo.h" |
-#include "llvm/Transforms/NaCl.h" |
-#include "llvm/Transforms/Utils/Local.h" |
-#include <map> |
-#include <vector> |
- |
-#include "llvm/Support/raw_ostream.h" |
- |
-#ifdef NDEBUG |
-#undef assert |
-#define assert(x) { if (!(x)) report_fatal_error(#x); } |
-#endif |
- |
-using namespace llvm; |
- |
-namespace { |
- |
- struct PhiBlockChange { |
- BasicBlock *DD, *SwitchBB, *NewBB; |
- }; |
- |
- typedef SmallVector<Value*, 2> ChunksVec; |
- typedef std::map<Value*, ChunksVec> SplitsMap; |
- |
- typedef SmallVector<PHINode *, 8> PHIVec; |
- typedef SmallVector<Instruction *, 8> DeadVec; |
- |
- // This is a ModulePass because the pass recreates functions in |
- // order to expand i64 arguments to pairs of i32s. |
- class ExpandI64 : public ModulePass { |
- bool Changed; |
- const DataLayout *DL; |
- Module *TheModule; |
- |
- SplitsMap Splits; // old illegal value to new insts |
- PHIVec Phis; |
- std::vector<PhiBlockChange> PhiBlockChanges; |
- |
- // If the function has an illegal return or argument, create a legal version |
- void ensureLegalFunc(Function *F); |
- |
- // If a function is illegal, remove it |
- void removeIllegalFunc(Function *F); |
- |
- // splits an illegal instruction into 32-bit chunks. We do |
- // not yet have the values yet, as they depend on other |
- // splits, so store the parts in Splits, for FinalizeInst. |
- bool splitInst(Instruction *I); |
- |
- // For an illegal value, returns the split out chunks |
- // representing the low and high parts, that splitInst |
- // generated. |
- // The value can also be a constant, in which case we just |
- // split it, or a function argument, in which case we |
- // map to the proper legalized new arguments |
- // |
- // @param AllowUnreachable It is possible for phi nodes |
- // to refer to unreachable blocks, |
- // which our traversal never |
- // reaches; this flag lets us |
- // ignore those - otherwise, |
- // not finding chunks is fatal |
- ChunksVec getChunks(Value *V, bool AllowUnreachable=false); |
- |
- Function *Add, *Sub, *Mul, *SDiv, *UDiv, *SRem, *URem, *LShr, *AShr, *Shl, *GetHigh, *SetHigh, *FtoILow, *FtoIHigh, *DtoILow, *DtoIHigh, *SItoF, *UItoF, *SItoD, *UItoD, *BItoD, *BDtoILow, *BDtoIHigh; |
- |
- void ensureFuncs(); |
- unsigned getNumChunks(Type *T); |
- |
- public: |
- static char ID; |
- ExpandI64() : ModulePass(ID) { |
- initializeExpandI64Pass(*PassRegistry::getPassRegistry()); |
- |
- Add = Sub = Mul = SDiv = UDiv = SRem = URem = LShr = AShr = Shl = GetHigh = SetHigh = NULL; |
- } |
- |
- virtual bool runOnModule(Module &M); |
- }; |
-} |
- |
-char ExpandI64::ID = 0; |
-INITIALIZE_PASS(ExpandI64, "expand-illegal-ints", |
- "Expand and lower illegal >i32 operations into 32-bit chunks", |
- false, false) |
- |
-// Utilities |
- |
-static Instruction *CopyDebug(Instruction *NewInst, Instruction *Original) { |
- NewInst->setDebugLoc(Original->getDebugLoc()); |
- return NewInst; |
-} |
- |
-static bool isIllegal(Type *T) { |
- return T->isIntegerTy() && T->getIntegerBitWidth() > 32; |
-} |
- |
-static FunctionType *getLegalizedFunctionType(FunctionType *FT) { |
- SmallVector<Type*, 0> ArgTypes; // XXX |
- int Num = FT->getNumParams(); |
- for (int i = 0; i < Num; i++) { |
- Type *T = FT->getParamType(i); |
- if (!isIllegal(T)) { |
- ArgTypes.push_back(T); |
- } else { |
- Type *i32 = Type::getInt32Ty(FT->getContext()); |
- ArgTypes.push_back(i32); |
- ArgTypes.push_back(i32); |
- } |
- } |
- Type *RT = FT->getReturnType(); |
- Type *NewRT; |
- if (!isIllegal(RT)) { |
- NewRT = RT; |
- } else { |
- NewRT = Type::getInt32Ty(FT->getContext()); |
- } |
- return FunctionType::get(NewRT, ArgTypes, false); |
-} |
- |
-// Implementation of ExpandI64 |
- |
-static bool okToRemainIllegal(Function *F) { |
- StringRef Name = F->getName(); |
- if (Name == "llvm.dbg.value") return true; |
- |
- // XXX EMSCRIPTEN: These take an i64 immediate argument; since they're not |
- // real instructions, we don't need to legalize them. |
- if (Name == "llvm.lifetime.start") return true; |
- if (Name == "llvm.lifetime.end") return true; |
- if (Name == "llvm.invariant.start") return true; |
- if (Name == "llvm.invariant.end") return true; |
- |
- return false; |
-} |
- |
-unsigned ExpandI64::getNumChunks(Type *T) { |
- unsigned Num = DL->getTypeSizeInBits(T); |
- return (Num + 31) / 32; |
-} |
- |
-static bool isLegalFunctionType(FunctionType *FT) { |
- if (isIllegal(FT->getReturnType())) { |
- return false; |
- } |
- |
- int Num = FT->getNumParams(); |
- for (int i = 0; i < Num; i++) { |
- if (isIllegal(FT->getParamType(i))) { |
- return false; |
- } |
- } |
- |
- return true; |
-} |
- |
-static bool isLegalInstruction(const Instruction *I) { |
- if (isIllegal(I->getType())) { |
- return false; |
- } |
- |
- for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { |
- if (isIllegal(I->getOperand(i)->getType())) { |
- return false; |
- } |
- } |
- |
- return true; |
-} |
- |
-// We can't use RecreateFunction because we need to handle |
-// function and argument attributes specially. |
-static Function *RecreateFunctionLegalized(Function *F, FunctionType *NewType) { |
- Function *NewFunc = Function::Create(NewType, F->getLinkage()); |
- |
- AttributeSet Attrs = F->getAttributes(); |
- AttributeSet FnAttrs = Attrs.getFnAttributes(); |
- |
- // Legalizing the return value is done by storing part of the value into |
- // static storage. Subsequent analysis will see this as a memory access, |
- // so we can no longer claim to be readonly or readnone. |
- if (isIllegal(F->getReturnType())) { |
- FnAttrs = FnAttrs.removeAttribute(F->getContext(), |
- AttributeSet::FunctionIndex, |
- Attribute::ReadOnly); |
- FnAttrs = FnAttrs.removeAttribute(F->getContext(), |
- AttributeSet::FunctionIndex, |
- Attribute::ReadNone); |
- } |
- |
- NewFunc->addAttributes(AttributeSet::FunctionIndex, FnAttrs); |
- NewFunc->addAttributes(AttributeSet::ReturnIndex, Attrs.getRetAttributes()); |
- Function::arg_iterator AI = F->arg_begin(); |
- |
- // We need to recreate the attribute set, with the right indexes |
- AttributeSet NewAttrs; |
- unsigned NumArgs = F->arg_size(); |
- for (unsigned i = 1, j = 1; i < NumArgs+1; i++, j++, AI++) { |
- if (isIllegal(AI->getType())) { |
- j++; |
- continue; |
- } |
- if (!Attrs.hasAttributes(i)) continue; |
- AttributeSet ParamAttrs = Attrs.getParamAttributes(i); |
- AttrBuilder AB; |
- unsigned NumSlots = ParamAttrs.getNumSlots(); |
- for (unsigned k = 0; k < NumSlots; k++) { |
- for (AttributeSet::iterator I = ParamAttrs.begin(k), E = ParamAttrs.end(k); I != E; I++) { |
- AB.addAttribute(*I); |
- } |
- } |
- NewFunc->addAttributes(j, AttributeSet::get(F->getContext(), j, AB)); |
- } |
- |
- F->getParent()->getFunctionList().insert(F, NewFunc); |
- NewFunc->takeName(F); |
- NewFunc->getBasicBlockList().splice(NewFunc->begin(), |
- F->getBasicBlockList()); |
- F->replaceAllUsesWith( |
- ConstantExpr::getBitCast(NewFunc, |
- F->getFunctionType()->getPointerTo())); |
- return NewFunc; |
-} |
- |
-void ExpandI64::ensureLegalFunc(Function *F) { |
- if (okToRemainIllegal(F)) return; |
- |
- FunctionType *FT = F->getFunctionType(); |
- if (isLegalFunctionType(FT)) return; |
- |
- Changed = true; |
- Function *NF = RecreateFunctionLegalized(F, getLegalizedFunctionType(FT)); |
- std::string Name = NF->getName(); |
- if (strncmp(Name.c_str(), "llvm.", 5) == 0) { |
- // this is an intrinsic, and we are changing its signature, which will annoy LLVM, so rename |
- const size_t len = Name.size(); |
- SmallString<256> NewName; |
- NewName.resize(len); |
- for (unsigned i = 0; i < len; i++) { |
- NewName[i] = Name[i] != '.' ? Name[i] : '_'; |
- } |
- NF->setName(Twine(NewName)); |
- } |
- |
- // Move and update arguments |
- for (Function::arg_iterator Arg = F->arg_begin(), E = F->arg_end(), NewArg = NF->arg_begin(); |
- Arg != E; ++Arg) { |
- if (Arg->getType() == NewArg->getType()) { |
- NewArg->takeName(Arg); |
- Arg->replaceAllUsesWith(NewArg); |
- NewArg++; |
- } else { |
- // This was legalized |
- ChunksVec &Chunks = Splits[&*Arg]; |
- int Num = getNumChunks(Arg->getType()); |
- assert(Num == 2); |
- for (int i = 0; i < Num; i++) { |
- Chunks.push_back(&*NewArg); |
- if (NewArg->hasName()) Chunks[i]->setName(NewArg->getName() + "$" + utostr(i)); |
- NewArg++; |
- } |
- } |
- } |
-} |
- |
-void ExpandI64::removeIllegalFunc(Function *F) { |
- if (okToRemainIllegal(F)) return; |
- |
- FunctionType *FT = F->getFunctionType(); |
- if (!isLegalFunctionType(FT)) { |
- F->eraseFromParent(); |
- } |
-} |
- |
-bool ExpandI64::splitInst(Instruction *I) { |
- Type *i32 = Type::getInt32Ty(I->getContext()); |
- Type *i32P = i32->getPointerTo(); |
- Type *i64 = Type::getInt64Ty(I->getContext()); |
- Value *Zero = Constant::getNullValue(i32); |
- |
- ChunksVec &Chunks = Splits[I]; |
- |
- switch (I->getOpcode()) { |
- case Instruction::GetElementPtr: { |
- GetElementPtrInst *GEP = cast<GetElementPtrInst>(I); |
- SmallVector<Value*, 2> NewOps; |
- for (unsigned i = 1, e = I->getNumOperands(); i != e; ++i) { |
- Value *Op = I->getOperand(i); |
- if (isIllegal(Op->getType())) { |
- // Truncate the operand down to one chunk. |
- NewOps.push_back(getChunks(Op)[0]); |
- } else { |
- NewOps.push_back(Op); |
- } |
- } |
- Value *NewGEP = CopyDebug(GetElementPtrInst::Create(GEP->getPointerOperand()->getType(), GEP->getPointerOperand(), NewOps, "", GEP), GEP); |
- Chunks.push_back(NewGEP); |
- I->replaceAllUsesWith(NewGEP); |
- break; |
- } |
- case Instruction::SExt: { |
- ChunksVec InputChunks; |
- Value *Op = I->getOperand(0); |
- if (isIllegal(Op->getType())) { |
- InputChunks = getChunks(Op); |
- } else { |
- InputChunks.push_back(Op); |
- } |
- |
- for (unsigned i = 0, e = InputChunks.size(); i != e; ++i) { |
- Value *Input = InputChunks[i]; |
- |
- Type *T = Input->getType(); |
- Value *Chunk; |
- if (T->getIntegerBitWidth() < 32) { |
- Chunk = CopyDebug(new SExtInst(Input, i32, "", I), I); |
- } else { |
- assert(T->getIntegerBitWidth() == 32); |
- Chunk = Input; |
- } |
- Chunks.push_back(Chunk); |
- } |
- |
- Instruction *Check = CopyDebug(new ICmpInst(I, ICmpInst::ICMP_SLT, Chunks.back(), Zero), I); |
- int Num = getNumChunks(I->getType()); |
- for (int i = Chunks.size(); i < Num; i++) { |
- Instruction *High = CopyDebug(new SExtInst(Check, i32, "", I), I); |
- Chunks.push_back(High); |
- } |
- break; |
- } |
- case Instruction::PtrToInt: |
- case Instruction::ZExt: { |
- Value *Op = I->getOperand(0); |
- ChunksVec InputChunks; |
- if (I->getOpcode() == Instruction::PtrToInt) { |
- InputChunks.push_back(CopyDebug(new PtrToIntInst(Op, i32, "", I), I)); |
- } else if (isIllegal(Op->getType())) { |
- InputChunks = getChunks(Op); |
- } else { |
- InputChunks.push_back(Op); |
- } |
- |
- for (unsigned i = 0, e = InputChunks.size(); i != e; ++i) { |
- Value *Input = InputChunks[i]; |
- Type *T = Input->getType(); |
- |
- Value *Chunk; |
- if (T->getIntegerBitWidth() < 32) { |
- Chunk = CopyDebug(new ZExtInst(Input, i32, "", I), I); |
- } else { |
- assert(T->getIntegerBitWidth() == 32); |
- Chunk = Input; |
- } |
- Chunks.push_back(Chunk); |
- } |
- |
- int Num = getNumChunks(I->getType()); |
- for (int i = Chunks.size(); i < Num; i++) { |
- Chunks.push_back(Zero); |
- } |
- break; |
- } |
- case Instruction::IntToPtr: |
- case Instruction::Trunc: { |
- unsigned Num = getNumChunks(I->getType()); |
- unsigned NumBits = DL->getTypeSizeInBits(I->getType()); |
- ChunksVec InputChunks = getChunks(I->getOperand(0)); |
- for (unsigned i = 0; i < Num; i++) { |
- Value *Input = InputChunks[i]; |
- |
- Value *Chunk; |
- if (NumBits < 32) { |
- Chunk = CopyDebug(new TruncInst(Input, IntegerType::get(I->getContext(), NumBits), "", I), I); |
- NumBits = 0; |
- } else { |
- Chunk = Input; |
- NumBits -= 32; |
- } |
- if (I->getOpcode() == Instruction::IntToPtr) { |
- assert(i == 0); |
- Chunk = CopyDebug(new IntToPtrInst(Chunk, I->getType(), "", I), I); |
- } |
- Chunks.push_back(Chunk); |
- } |
- if (!isIllegal(I->getType())) { |
- assert(Chunks.size() == 1); |
- I->replaceAllUsesWith(Chunks[0]); |
- } |
- break; |
- } |
- case Instruction::Load: { |
- LoadInst *LI = cast<LoadInst>(I); |
- Instruction *AI = CopyDebug(new PtrToIntInst(LI->getPointerOperand(), i32, "", I), I); |
- int Num = getNumChunks(I->getType()); |
- for (int i = 0; i < Num; i++) { |
- Instruction *Add = i == 0 ? AI : CopyDebug(BinaryOperator::Create(Instruction::Add, AI, ConstantInt::get(i32, 4*i), "", I), I); |
- Instruction *Ptr = CopyDebug(new IntToPtrInst(Add, i32P, "", I), I); |
- LoadInst *Chunk = new LoadInst(Ptr, "", I); CopyDebug(Chunk, I); |
- Chunk->setAlignment(MinAlign(LI->getAlignment() == 0 ? |
- DL->getABITypeAlignment(LI->getType()) : |
- LI->getAlignment(), |
- 4*i)); |
- Chunk->setVolatile(LI->isVolatile()); |
- Chunk->setOrdering(LI->getOrdering()); |
- Chunk->setSynchScope(LI->getSynchScope()); |
- Chunks.push_back(Chunk); |
- } |
- break; |
- } |
- case Instruction::Store: { |
- StoreInst *SI = cast<StoreInst>(I); |
- Instruction *AI = CopyDebug(new PtrToIntInst(SI->getPointerOperand(), i32, "", I), I); |
- ChunksVec InputChunks = getChunks(SI->getValueOperand()); |
- int Num = InputChunks.size(); |
- for (int i = 0; i < Num; i++) { |
- Instruction *Add = i == 0 ? AI : CopyDebug(BinaryOperator::Create(Instruction::Add, AI, ConstantInt::get(i32, 4*i), "", I), I); |
- Instruction *Ptr = CopyDebug(new IntToPtrInst(Add, i32P, "", I), I); |
- StoreInst *Chunk = new StoreInst(InputChunks[i], Ptr, I); |
- Chunk->setAlignment(MinAlign(SI->getAlignment() == 0 ? |
- DL->getABITypeAlignment(SI->getValueOperand()->getType()) : |
- SI->getAlignment(), |
- 4*i)); |
- Chunk->setVolatile(SI->isVolatile()); |
- Chunk->setOrdering(SI->getOrdering()); |
- Chunk->setSynchScope(SI->getSynchScope()); |
- CopyDebug(Chunk, I); |
- } |
- break; |
- } |
- case Instruction::Ret: { |
- assert(I->getOperand(0)->getType() == i64); |
- ChunksVec InputChunks = getChunks(I->getOperand(0)); |
- ensureFuncs(); |
- SmallVector<Value *, 1> Args; |
- Args.push_back(InputChunks[1]); |
- CopyDebug(CallInst::Create(SetHigh, Args, "", I), I); |
- CopyDebug(ReturnInst::Create(I->getContext(), InputChunks[0], I), I); |
- break; |
- } |
- case Instruction::Add: |
- case Instruction::Sub: |
- case Instruction::Mul: |
- case Instruction::SDiv: |
- case Instruction::UDiv: |
- case Instruction::SRem: |
- case Instruction::URem: |
- case Instruction::LShr: |
- case Instruction::AShr: |
- case Instruction::Shl: { |
- ChunksVec LeftChunks = getChunks(I->getOperand(0)); |
- ChunksVec RightChunks = getChunks(I->getOperand(1)); |
- unsigned Num = getNumChunks(I->getType()); |
- if (Num == 2) { |
- ensureFuncs(); |
- Value *Low = NULL, *High = NULL; |
- Function *F = NULL; |
- switch (I->getOpcode()) { |
- case Instruction::Add: F = Add; break; |
- case Instruction::Sub: F = Sub; break; |
- case Instruction::Mul: F = Mul; break; |
- case Instruction::SDiv: F = SDiv; break; |
- case Instruction::UDiv: F = UDiv; break; |
- case Instruction::SRem: F = SRem; break; |
- case Instruction::URem: F = URem; break; |
- case Instruction::AShr: F = AShr; break; |
- case Instruction::LShr: { |
- if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) { |
- unsigned Shifts = CI->getZExtValue(); |
- if (Shifts == 32) { |
- Low = LeftChunks[1]; |
- High = Zero; |
- break; |
- } |
- } |
- F = LShr; |
- break; |
- } |
- case Instruction::Shl: { |
- if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) { |
- const APInt &Shifts = CI->getValue(); |
- if (Shifts == 32) { |
- Low = Zero; |
- High = LeftChunks[0]; |
- break; |
- } |
- } |
- F = Shl; |
- break; |
- } |
- default: assert(0); |
- } |
- if (F) { |
- // use a library call, no special optimization was found |
- SmallVector<Value *, 4> Args; |
- Args.push_back(LeftChunks[0]); |
- Args.push_back(LeftChunks[1]); |
- Args.push_back(RightChunks[0]); |
- Args.push_back(RightChunks[1]); |
- Low = CopyDebug(CallInst::Create(F, Args, "", I), I); |
- High = CopyDebug(CallInst::Create(GetHigh, "", I), I); |
- } |
- Chunks.push_back(Low); |
- Chunks.push_back(High); |
- } else { |
- // more than 64 bits. handle simple shifts for lshr and shl |
- assert(I->getOpcode() == Instruction::LShr || I->getOpcode() == Instruction::AShr || I->getOpcode() == Instruction::Shl); |
- ConstantInt *CI = cast<ConstantInt>(I->getOperand(1)); |
- unsigned Shifts = CI->getZExtValue(); |
- unsigned Fraction = Shifts % 32; |
- Constant *Frac = ConstantInt::get(i32, Fraction); |
- Constant *Comp = ConstantInt::get(i32, 32 - Fraction); |
- Instruction::BinaryOps Opcode, Reverse; |
- unsigned ShiftChunks, Dir; |
- Value *TopFiller = Zero; |
- if (I->getOpcode() == Instruction::Shl) { |
- Opcode = Instruction::Shl; |
- Reverse = Instruction::LShr; |
- ShiftChunks = -(Shifts/32); |
- Dir = -1; |
- } else { |
- Opcode = Instruction::LShr; |
- Reverse = Instruction::Shl; |
- ShiftChunks = Shifts/32; |
- Dir = 1; |
- if (I->getOpcode() == Instruction::AShr) { |
- Value *Cond = CopyDebug(new ICmpInst(I, ICmpInst::ICMP_SLT, LeftChunks[LeftChunks.size()-1], Zero), I); |
- TopFiller = CopyDebug(SelectInst::Create(Cond, ConstantInt::get(i32, -1), Zero, "", I), I); |
- } |
- } |
- for (unsigned i = 0; i < Num; i++) { |
- Value *L; |
- if (i + ShiftChunks < LeftChunks.size()) { |
- L = LeftChunks[i + ShiftChunks]; |
- } else { |
- L = Zero; |
- } |
- |
- Value *H; |
- if (i + ShiftChunks + Dir < LeftChunks.size()) { |
- H = LeftChunks[i + ShiftChunks + Dir]; |
- } else { |
- H = TopFiller; |
- } |
- |
- // shifted the fractional amount |
- if (Frac != Zero && L != Zero) { |
- if (Fraction == 32) { |
- L = Zero; |
- } else { |
- L = CopyDebug(BinaryOperator::Create(Opcode, L, Frac, "", I), I); |
- } |
- } |
- // shifted the complement-fractional amount to the other side |
- if (Comp != Zero && H != Zero) { |
- if (Fraction == 0) { |
- H = TopFiller; |
- } else { |
- H = CopyDebug(BinaryOperator::Create(Reverse, H, Comp, "", I), I); |
- } |
- } |
- |
- // Or the parts together. Since we may have zero, try to fold it away. |
- if (Value *V = SimplifyBinOp(Instruction::Or, L, H, *DL)) { |
- Chunks.push_back(V); |
- } else { |
- Chunks.push_back(CopyDebug(BinaryOperator::Create(Instruction::Or, L, H, "", I), I)); |
- } |
- } |
- } |
- break; |
- } |
- case Instruction::ICmp: { |
- ICmpInst *CE = cast<ICmpInst>(I); |
- ICmpInst::Predicate Pred = CE->getPredicate(); |
- ChunksVec LeftChunks = getChunks(I->getOperand(0)); |
- ChunksVec RightChunks = getChunks(I->getOperand(1)); |
- switch (Pred) { |
- case ICmpInst::ICMP_EQ: |
- case ICmpInst::ICMP_NE: { |
- ICmpInst::Predicate PartPred; // the predicate to use on each of the parts |
- llvm::Instruction::BinaryOps CombineOp; // the predicate to use to combine the subcomparisons |
- int Num = LeftChunks.size(); |
- if (Pred == ICmpInst::ICMP_EQ) { |
- PartPred = ICmpInst::ICMP_EQ; |
- CombineOp = Instruction::And; |
- } else { |
- PartPred = ICmpInst::ICMP_NE; |
- CombineOp = Instruction::Or; |
- } |
- // first combine 0 and 1. then combine that with 2, etc. |
- Value *Combined = NULL; |
- for (int i = 0; i < Num; i++) { |
- Value *Cmp = CopyDebug(new ICmpInst(I, PartPred, LeftChunks[i], RightChunks[i]), I); |
- Combined = !Combined ? Cmp : CopyDebug(BinaryOperator::Create(CombineOp, Combined, Cmp, "", I), I); |
- } |
- I->replaceAllUsesWith(Combined); |
- break; |
- } |
- case ICmpInst::ICMP_ULT: |
- case ICmpInst::ICMP_SLT: |
- case ICmpInst::ICMP_UGT: |
- case ICmpInst::ICMP_SGT: |
- case ICmpInst::ICMP_ULE: |
- case ICmpInst::ICMP_SLE: |
- case ICmpInst::ICMP_UGE: |
- case ICmpInst::ICMP_SGE: { |
- if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) { |
- if (CI->getZExtValue() == 0 && Pred == ICmpInst::ICMP_SLT) { |
- // strict < 0 is easy to do, even on non-i64, just the sign bit matters |
- Instruction *NewInst = new ICmpInst(I, ICmpInst::ICMP_SLT, LeftChunks[LeftChunks.size()-1], Zero); |
- CopyDebug(NewInst, I); |
- I->replaceAllUsesWith(NewInst); |
- return true; |
- } |
- } |
- Type *T = I->getOperand(0)->getType(); |
- assert(T->isIntegerTy() && T->getIntegerBitWidth() % 32 == 0); |
- int NumChunks = getNumChunks(T); |
- assert(NumChunks >= 2); |
- ICmpInst::Predicate StrictPred = Pred; |
- ICmpInst::Predicate UnsignedPred = Pred; |
- switch (Pred) { |
- case ICmpInst::ICMP_ULE: StrictPred = ICmpInst::ICMP_ULT; break; |
- case ICmpInst::ICMP_UGE: StrictPred = ICmpInst::ICMP_UGT; break; |
- case ICmpInst::ICMP_SLE: StrictPred = ICmpInst::ICMP_SLT; UnsignedPred = ICmpInst::ICMP_ULE; break; |
- case ICmpInst::ICMP_SGE: StrictPred = ICmpInst::ICMP_SGT; UnsignedPred = ICmpInst::ICMP_UGE; break; |
- case ICmpInst::ICMP_SLT: UnsignedPred = ICmpInst::ICMP_ULT; break; |
- case ICmpInst::ICMP_SGT: UnsignedPred = ICmpInst::ICMP_UGT; break; |
- case ICmpInst::ICMP_ULT: break; |
- case ICmpInst::ICMP_UGT: break; |
- default: assert(0); |
- } |
- // general pattern is |
- // a,b,c < A,B,C => c < C || (c == C && b < B) || (c == C && b == B && a < A) |
- Instruction *Final = CopyDebug(new ICmpInst(I, StrictPred, LeftChunks[NumChunks-1], RightChunks[NumChunks-1]), I); |
- for (int i = NumChunks-2; i >= 0; i--) { |
- Instruction *Curr = CopyDebug(new ICmpInst(I, UnsignedPred, LeftChunks[i], RightChunks[i]), I); |
- for (int j = NumChunks-1; j > i; j--) { |
- Instruction *Temp = CopyDebug(new ICmpInst(I, ICmpInst::ICMP_EQ, LeftChunks[j], RightChunks[j]), I); |
- Curr = CopyDebug(BinaryOperator::Create(Instruction::And, Temp, Curr, "", I), I); |
- } |
- Final = CopyDebug(BinaryOperator::Create(Instruction::Or, Final, Curr, "", I), I); |
- } |
- I->replaceAllUsesWith(Final); |
- break; |
- } |
- default: assert(0); |
- } |
- break; |
- } |
- case Instruction::Select: { |
- SelectInst *SI = cast<SelectInst>(I); |
- Value *Cond = SI->getCondition(); |
- ChunksVec TrueChunks = getChunks(SI->getTrueValue()); |
- ChunksVec FalseChunks = getChunks(SI->getFalseValue()); |
- unsigned Num = getNumChunks(I->getType()); |
- for (unsigned i = 0; i < Num; i++) { |
- Instruction *Part = CopyDebug(SelectInst::Create(Cond, TrueChunks[i], FalseChunks[i], "", I), I); |
- Chunks.push_back(Part); |
- } |
- break; |
- } |
- case Instruction::PHI: { |
- PHINode *Parent = cast<PHINode>(I); |
- int Num = getNumChunks(I->getType()); |
- int PhiNum = Parent->getNumIncomingValues(); |
- for (int i = 0; i < Num; i++) { |
- Instruction *P = CopyDebug(PHINode::Create(i32, PhiNum, "", I), I); |
- Chunks.push_back(P); |
- } |
- // PHI node operands may not be translated yet; we'll handle them at the end. |
- Phis.push_back(Parent); |
- break; |
- } |
- case Instruction::And: |
- case Instruction::Or: |
- case Instruction::Xor: { |
- BinaryOperator *BO = cast<BinaryOperator>(I); |
- ChunksVec LeftChunks = getChunks(BO->getOperand(0)); |
- ChunksVec RightChunks = getChunks(BO->getOperand(1)); |
- int Num = getNumChunks(BO->getType()); |
- for (int i = 0; i < Num; i++) { |
- // If there's a constant operand, it's likely enough that one of the |
- // chunks will be a trivial operation, so it's worth calling |
- // SimplifyBinOp here. |
- if (Value *V = SimplifyBinOp(BO->getOpcode(), LeftChunks[i], RightChunks[i], *DL)) { |
- Chunks.push_back(V); |
- } else { |
- Chunks.push_back(CopyDebug(BinaryOperator::Create(BO->getOpcode(), LeftChunks[i], RightChunks[i], "", BO), BO)); |
- } |
- } |
- break; |
- } |
- case Instruction::Call: { |
- CallInst *CI = cast<CallInst>(I); |
- Function *F = CI->getCalledFunction(); |
- if (F) { |
- assert(okToRemainIllegal(F)); |
- return false; |
- } |
- Value *CV = CI->getCalledValue(); |
- FunctionType *OFT = NULL; |
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { |
- assert(CE); |
- assert(CE->getOpcode() == Instruction::BitCast); |
- OFT = cast<FunctionType>(cast<PointerType>(CE->getType())->getElementType()); |
- Constant *C = CE->getOperand(0); |
- CV = ConstantExpr::getBitCast(C, getLegalizedFunctionType(OFT)->getPointerTo()); |
- } else { |
- // this is a function pointer call |
- OFT = cast<FunctionType>(cast<PointerType>(CV->getType())->getElementType()); |
- // we need to add a bitcast |
- CV = new BitCastInst(CV, getLegalizedFunctionType(OFT)->getPointerTo(), "", I); |
- } |
- // create a call with space for legal args |
- SmallVector<Value *, 0> Args; // XXX |
- int Num = OFT->getNumParams(); |
- for (int i = 0; i < Num; i++) { |
- Type *T = OFT->getParamType(i); |
- if (!isIllegal(T)) { |
- Args.push_back(CI->getArgOperand(i)); |
- } else { |
- assert(T == i64); |
- ChunksVec ArgChunks = getChunks(CI->getArgOperand(i)); |
- Args.push_back(ArgChunks[0]); |
- Args.push_back(ArgChunks[1]); |
- } |
- } |
- Instruction *L = CopyDebug(CallInst::Create(CV, Args, "", I), I); |
- Instruction *H = NULL; |
- // legalize return value as well, if necessary |
- if (isIllegal(I->getType())) { |
- assert(I->getType() == i64); |
- ensureFuncs(); |
- H = CopyDebug(CallInst::Create(GetHigh, "", I), I); |
- Chunks.push_back(L); |
- Chunks.push_back(H); |
- } else { |
- I->replaceAllUsesWith(L); |
- } |
- break; |
- } |
- case Instruction::FPToUI: |
- case Instruction::FPToSI: { |
- assert(I->getType() == i64); |
- ensureFuncs(); |
- SmallVector<Value *, 1> Args; |
- Value *Input = I->getOperand(0); |
- Args.push_back(Input); |
- Instruction *L, *H; |
- if (Input->getType()->isFloatTy()) { |
- L = CopyDebug(CallInst::Create(FtoILow, Args, "", I), I); |
- H = CopyDebug(CallInst::Create(FtoIHigh, Args, "", I), I); |
- } else { |
- L = CopyDebug(CallInst::Create(DtoILow, Args, "", I), I); |
- H = CopyDebug(CallInst::Create(DtoIHigh, Args, "", I), I); |
- } |
- Chunks.push_back(L); |
- Chunks.push_back(H); |
- break; |
- } |
- case Instruction::BitCast: { |
- if (I->getType() == Type::getDoubleTy(TheModule->getContext())) { |
- // fall through to itofp |
- } else if (I->getOperand(0)->getType() == Type::getDoubleTy(TheModule->getContext())) { |
- // double to i64 |
- assert(I->getType() == i64); |
- ensureFuncs(); |
- SmallVector<Value *, 1> Args; |
- Args.push_back(I->getOperand(0)); |
- Instruction *L = CopyDebug(CallInst::Create(BDtoILow, Args, "", I), I); |
- Instruction *H = CopyDebug(CallInst::Create(BDtoIHigh, Args, "", I), I); |
- Chunks.push_back(L); |
- Chunks.push_back(H); |
- break; |
- } else if (isa<VectorType>(I->getOperand(0)->getType()) && !isa<VectorType>(I->getType())) { |
- unsigned NumElts = getNumChunks(I->getType()); |
- VectorType *IVTy = VectorType::get(i32, NumElts); |
- Instruction *B = CopyDebug(new BitCastInst(I->getOperand(0), IVTy, "", I), I); |
- for (unsigned i = 0; i < NumElts; ++i) { |
- Constant *Idx = ConstantInt::get(i32, i); |
- Instruction *Ext = CopyDebug(ExtractElementInst::Create(B, Idx, "", I), I); |
- Chunks.push_back(Ext); |
- } |
- break; |
- } else { |
- // no-op bitcast |
- assert(I->getType() == I->getOperand(0)->getType()); |
- Chunks = getChunks(I->getOperand(0)); |
- break; |
- } |
- } |
- case Instruction::SIToFP: |
- case Instruction::UIToFP: { |
- assert(I->getOperand(0)->getType() == i64); |
- ensureFuncs(); |
- ChunksVec InputChunks = getChunks(I->getOperand(0)); |
- Function *F; |
- switch (I->getOpcode()) { |
- case Instruction::SIToFP: F = I->getType() == Type::getDoubleTy(TheModule->getContext()) ? SItoD : SItoF; break; |
- case Instruction::UIToFP: F = I->getType() == Type::getDoubleTy(TheModule->getContext()) ? UItoD : UItoF; break; |
- case Instruction::BitCast: { |
- assert(I->getType() == Type::getDoubleTy(TheModule->getContext())); |
- F = BItoD; |
- break; |
- } |
- default: assert(0); |
- } |
- Instruction *D = CopyDebug(CallInst::Create(F, InputChunks, "", I), I); |
- I->replaceAllUsesWith(D); |
- break; |
- } |
- case Instruction::Switch: { |
- assert(I->getOperand(0)->getType() == i64); |
- ChunksVec InputChunks = getChunks(I->getOperand(0)); |
- |
- // do a switch on the lower 32 bits, into a different basic block for each target, then do a branch in each of those on the high 32 bits |
- SwitchInst* SI = cast<SwitchInst>(I); |
- BasicBlock *DD = SI->getDefaultDest(); |
- BasicBlock *SwitchBB = I->getParent(); |
- Function *F = SwitchBB->getParent(); |
- |
- unsigned NumItems = SI->getNumCases(); |
- SwitchInst *LowSI = SwitchInst::Create(InputChunks[0], DD, NumItems, I); // same default destination: if lower bits do not match, go straight to default |
- CopyDebug(LowSI, I); |
- |
- typedef std::pair<uint32_t, BasicBlock*> Pair; |
- typedef std::vector<Pair> Vec; // vector of pairs of high 32 bits, basic block |
- typedef std::map<uint32_t, Vec> Map; // maps low 32 bits to their Vec info |
- Map Groups; // (as two 64-bit values in the switch may share their lower bits) |
- |
- for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i) { |
- BasicBlock *BB = i.getCaseSuccessor(); |
- uint64_t Bits = i.getCaseValue()->getZExtValue(); |
- uint32_t LowBits = (uint32_t)Bits; |
- uint32_t HighBits = (uint32_t)(Bits >> 32); |
- Vec& V = Groups[LowBits]; |
- V.push_back(Pair(HighBits, BB)); |
- } |
- |
- unsigned Counter = 0; |
- BasicBlock *InsertPoint = SwitchBB; |
- |
- for (Map::iterator GI = Groups.begin(); GI != Groups.end(); GI++) { |
- uint32_t LowBits = GI->first; |
- Vec &V = GI->second; |
- |
- BasicBlock *NewBB = BasicBlock::Create(F->getContext(), "switch64_" + utostr(Counter++), F); |
- NewBB->moveAfter(InsertPoint); |
- InsertPoint = NewBB; |
- LowSI->addCase(cast<ConstantInt>(ConstantInt::get(i32, LowBits)), NewBB); |
- |
- /*if (V.size() == 1) { |
- // just one option, create a branch |
- Instruction *CheckHigh = CopyDebug(new ICmpInst(*NewBB, ICmpInst::ICMP_EQ, InputChunks[1], ConstantInt::get(i32, V[0]->first)), I); |
- Split.ToFix.push_back(CheckHigh); |
- CopyDebug(BranchInst::Create(V[0]->second, DD, CheckHigh, NewBB), I); |
- } else {*/ |
- |
- // multiple options, create a switch - we could also optimize and make an icmp/branch if just one, as in commented code above |
- SwitchInst *HighSI = SwitchInst::Create(InputChunks[1], DD, V.size(), NewBB); // same default destination: if lower bits do not match, go straight to default |
- for (unsigned i = 0; i < V.size(); i++) { |
- BasicBlock *BB = V[i].second; |
- HighSI->addCase(cast<ConstantInt>(ConstantInt::get(i32, V[i].first)), BB); |
- // fix phis, we used to go SwitchBB->BB, but now go SwitchBB->NewBB->BB, so we look like we arrived from NewBB. Replace the phi from the |
- // now unneeded SwitchBB to the new BB |
- // We cannot do this here right now, as phis we encounter may be in the middle of processing (empty), so we queue these. |
- for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { |
- PHINode *Phi = dyn_cast<PHINode>(I); |
- if (!Phi) break; |
- PhiBlockChange Change; |
- Change.DD = BB; |
- Change.SwitchBB = SwitchBB; |
- Change.NewBB = NewBB; |
- PhiBlockChanges.push_back(Change); |
- break; // we saw a phi on this BB, and pushed a Change |
- } |
- } |
- |
- // We used to go SwitchBB->DD, but now go SwitchBB->NewBB->DD, fix that like with BB above. However here we do not replace, |
- // as the switch BB is still possible to arrive from - we can arrive at the default if either the lower bits were wrong (we |
- // arrive from the switchBB) or from the NewBB if the high bits were wrong. |
- PhiBlockChange Change; |
- Change.DD = DD; |
- Change.SwitchBB = SwitchBB; |
- Change.NewBB = NewBB; |
- PhiBlockChanges.push_back(Change); |
- } |
- break; |
- } |
- default: { |
- I->dump(); |
- assert(0 && "some i64 thing we can't legalize yet"); |
- } |
- } |
- |
- return true; |
-} |
- |
-ChunksVec ExpandI64::getChunks(Value *V, bool AllowUnreachable) { |
- assert(isIllegal(V->getType())); |
- |
- unsigned Num = getNumChunks(V->getType()); |
- Type *i32 = Type::getInt32Ty(V->getContext()); |
- |
- if (isa<UndefValue>(V)) |
- return ChunksVec(Num, UndefValue::get(i32)); |
- |
- if (Constant *C = dyn_cast<Constant>(V)) { |
- ChunksVec Chunks; |
- for (unsigned i = 0; i < Num; i++) { |
- Constant *Count = ConstantInt::get(C->getType(), i * 32); |
- Constant *NewC = ConstantExpr::getTrunc(ConstantExpr::getLShr(C, Count), i32); |
- TargetLibraryInfo *TLI = 0; // TODO |
- if (ConstantExpr *NewCE = dyn_cast<ConstantExpr>(NewC)) { |
- if (Constant *FoldedC = ConstantFoldConstantExpression(NewCE, *DL, TLI)) { |
- NewC = FoldedC; |
- } |
- } |
- |
- Chunks.push_back(NewC); |
- } |
- return Chunks; |
- } |
- |
- if (Splits.find(V) == Splits.end()) { |
- if (AllowUnreachable) |
- return ChunksVec(Num, UndefValue::get(i32)); |
- errs() << *V << "\n"; |
- report_fatal_error("could not find chunks for illegal value"); |
- } |
- assert(Splits[V].size() == Num); |
- return Splits[V]; |
-} |
- |
-void ExpandI64::ensureFuncs() { |
- if (Add != NULL) return; |
- |
- Type *i32 = Type::getInt32Ty(TheModule->getContext()); |
- |
- SmallVector<Type*, 4> FourArgTypes; |
- FourArgTypes.push_back(i32); |
- FourArgTypes.push_back(i32); |
- FourArgTypes.push_back(i32); |
- FourArgTypes.push_back(i32); |
- FunctionType *FourFunc = FunctionType::get(i32, FourArgTypes, false); |
- |
- Add = Function::Create(FourFunc, GlobalValue::ExternalLinkage, |
- "i64Add", TheModule); |
- Sub = Function::Create(FourFunc, GlobalValue::ExternalLinkage, |
- "i64Subtract", TheModule); |
- Mul = Function::Create(FourFunc, GlobalValue::ExternalLinkage, |
- "__muldi3", TheModule); |
- SDiv = Function::Create(FourFunc, GlobalValue::ExternalLinkage, |
- "__divdi3", TheModule); |
- UDiv = Function::Create(FourFunc, GlobalValue::ExternalLinkage, |
- "__udivdi3", TheModule); |
- SRem = Function::Create(FourFunc, GlobalValue::ExternalLinkage, |
- "__remdi3", TheModule); |
- URem = Function::Create(FourFunc, GlobalValue::ExternalLinkage, |
- "__uremdi3", TheModule); |
- LShr = Function::Create(FourFunc, GlobalValue::ExternalLinkage, |
- "bitshift64Lshr", TheModule); |
- AShr = Function::Create(FourFunc, GlobalValue::ExternalLinkage, |
- "bitshift64Ashr", TheModule); |
- Shl = Function::Create(FourFunc, GlobalValue::ExternalLinkage, |
- "bitshift64Shl", TheModule); |
- |
- if (!(GetHigh = TheModule->getFunction("getHigh32"))) { |
- SmallVector<Type*, 0> GetHighArgTypes; |
- FunctionType *GetHighFunc = FunctionType::get(i32, GetHighArgTypes, false); |
- GetHigh = Function::Create(GetHighFunc, GlobalValue::ExternalLinkage, |
- "getHigh32", TheModule); |
- } |
- |
- Type *V = Type::getVoidTy(TheModule->getContext()); |
- |
- SmallVector<Type*, 1> SetHighArgTypes; |
- SetHighArgTypes.push_back(i32); |
- FunctionType *SetHighFunc = FunctionType::get(V, SetHighArgTypes, false); |
- SetHigh = Function::Create(SetHighFunc, GlobalValue::ExternalLinkage, |
- "setHigh32", TheModule); |
- |
- Type *Double = Type::getDoubleTy(TheModule->getContext()); |
- Type *Float = Type::getFloatTy(TheModule->getContext()); |
- |
- SmallVector<Type*, 1> FtoITypes; |
- FtoITypes.push_back(Float); |
- FunctionType *FtoIFunc = FunctionType::get(i32, FtoITypes, false); |
- |
- SmallVector<Type*, 1> DtoITypes; |
- DtoITypes.push_back(Double); |
- FunctionType *DtoIFunc = FunctionType::get(i32, DtoITypes, false); |
- |
- FtoILow = Function::Create(FtoIFunc, GlobalValue::ExternalLinkage, |
- "FtoILow", TheModule); |
- FtoIHigh = Function::Create(FtoIFunc, GlobalValue::ExternalLinkage, |
- "FtoIHigh", TheModule); |
- DtoILow = Function::Create(DtoIFunc, GlobalValue::ExternalLinkage, |
- "DtoILow", TheModule); |
- DtoIHigh = Function::Create(DtoIFunc, GlobalValue::ExternalLinkage, |
- "DtoIHigh", TheModule); |
- BDtoILow = Function::Create(DtoIFunc, GlobalValue::ExternalLinkage, |
- "BDtoILow", TheModule); |
- BDtoIHigh = Function::Create(DtoIFunc, GlobalValue::ExternalLinkage, |
- "BDtoIHigh", TheModule); |
- |
- SmallVector<Type*, 2> ItoTypes; |
- ItoTypes.push_back(i32); |
- ItoTypes.push_back(i32); |
- |
- FunctionType *ItoFFunc = FunctionType::get(Float, ItoTypes, false); |
- SItoF = Function::Create(ItoFFunc, GlobalValue::ExternalLinkage, |
- "SItoF", TheModule); |
- UItoF = Function::Create(ItoFFunc, GlobalValue::ExternalLinkage, |
- "UItoF", TheModule); |
- |
- FunctionType *ItoDFunc = FunctionType::get(Double, ItoTypes, false); |
- SItoD = Function::Create(ItoDFunc, GlobalValue::ExternalLinkage, |
- "SItoD", TheModule); |
- UItoD = Function::Create(ItoDFunc, GlobalValue::ExternalLinkage, |
- "UItoD", TheModule); |
- |
- BItoD = Function::Create(ItoDFunc, GlobalValue::ExternalLinkage, |
- "BItoD", TheModule); |
-} |
- |
-bool ExpandI64::runOnModule(Module &M) { |
- TheModule = &M; |
- DL = &M.getDataLayout(); |
- Splits.clear(); |
- Changed = false; |
- |
- // pre pass - legalize functions |
- for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ) { |
- Function *Func = Iter++; |
- ensureLegalFunc(Func); |
- } |
- |
- // first pass - split |
- DeadVec Dead; |
- for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ++Iter) { |
- Function *Func = Iter; |
- if (Func->isDeclaration()) { |
- continue; |
- } |
- |
- // Walk the body of the function. We use reverse postorder so that we visit |
- // all operands of an instruction before the instruction itself. The |
- // exception to this is PHI nodes, which we put on a list and handle below. |
- ReversePostOrderTraversal<Function*> RPOT(Func); |
- for (ReversePostOrderTraversal<Function*>::rpo_iterator RI = RPOT.begin(), |
- RE = RPOT.end(); RI != RE; ++RI) { |
- BasicBlock *BB = *RI; |
- for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); |
- Iter != E; ) { |
- Instruction *I = Iter++; |
- if (!isLegalInstruction(I)) { |
- if (splitInst(I)) { |
- Changed = true; |
- Dead.push_back(I); |
- } |
- } |
- } |
- } |
- |
- // Fix up PHI node operands. |
- while (!Phis.empty()) { |
- PHINode *PN = Phis.pop_back_val(); |
- ChunksVec OutputChunks = getChunks(PN); |
- for (unsigned j = 0, je = PN->getNumIncomingValues(); j != je; ++j) { |
- Value *Op = PN->getIncomingValue(j); |
- ChunksVec InputChunks = getChunks(Op, true); |
- for (unsigned k = 0, ke = OutputChunks.size(); k != ke; ++k) { |
- PHINode *NewPN = cast<PHINode>(OutputChunks[k]); |
- NewPN->addIncoming(InputChunks[k], PN->getIncomingBlock(j)); |
- } |
- } |
- PN->dropAllReferences(); |
- } |
- |
- // Delete instructions which were replaced. We do this after the full walk |
- // of the instructions so that all uses are replaced first. |
- while (!Dead.empty()) { |
- Instruction *D = Dead.pop_back_val(); |
- D->eraseFromParent(); |
- } |
- |
- // Apply basic block changes to phis, now that phis are all processed (and illegal phis erased) |
- for (unsigned i = 0; i < PhiBlockChanges.size(); i++) { |
- PhiBlockChange &Change = PhiBlockChanges[i]; |
- for (BasicBlock::iterator I = Change.DD->begin(); I != Change.DD->end(); ++I) { |
- PHINode *Phi = dyn_cast<PHINode>(I); |
- if (!Phi) break; |
- int Index = Phi->getBasicBlockIndex(Change.SwitchBB); |
- assert(Index >= 0); |
- Phi->addIncoming(Phi->getIncomingValue(Index), Change.NewBB); |
- } |
- } |
- PhiBlockChanges.clear(); |
- |
- // We only visited blocks found by a DFS walk from the entry, so we haven't |
- // visited any unreachable blocks, and they may still contain illegal |
- // instructions at this point. Being unreachable, they can simply be deleted. |
- removeUnreachableBlocks(*Func); |
- } |
- |
- // post pass - clean up illegal functions that were legalized. We do this |
- // after the full walk of the functions so that all uses are replaced first. |
- for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ) { |
- Function *Func = Iter++; |
- removeIllegalFunc(Func); |
- } |
- |
- return Changed; |
-} |
- |
-ModulePass *llvm::createExpandI64Pass() { |
- return new ExpandI64(); |
-} |