aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms
diff options
context:
space:
mode:
authorDan Gohman <sunfish@mozilla.com>2014-02-26 08:47:51 -0800
committerDan Gohman <sunfish@mozilla.com>2014-02-28 11:22:37 -0800
commit0dac79df771f7708a03e724126dded4f64531bc5 (patch)
treec4ac706d40a5b261ef6536e39ddaab97f0e20b7a /lib/Transforms
parentafc95002f260faae520e91fa681cedf8485b4613 (diff)
Move ExpandI64 into lib/Target/JSBackend.
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/NaCl/CMakeLists.txt1
-rw-r--r--lib/Transforms/NaCl/ExpandI64.cpp1107
-rw-r--r--lib/Transforms/NaCl/PNaClABISimplify.cpp2
3 files changed, 0 insertions, 1110 deletions
diff --git a/lib/Transforms/NaCl/CMakeLists.txt b/lib/Transforms/NaCl/CMakeLists.txt
index 05cef0857e..dd76491d65 100644
--- a/lib/Transforms/NaCl/CMakeLists.txt
+++ b/lib/Transforms/NaCl/CMakeLists.txt
@@ -28,7 +28,6 @@ add_llvm_library(LLVMNaClTransforms
RewritePNaClLibraryCalls.cpp
StripAttributes.cpp
StripMetadata.cpp
- ExpandI64.cpp
LowerEmExceptionsPass.cpp
LowerEmSetjmp.cpp
NoExitRuntime.cpp
diff --git a/lib/Transforms/NaCl/ExpandI64.cpp b/lib/Transforms/NaCl/ExpandI64.cpp
deleted file mode 100644
index 911060ebfc..0000000000
--- a/lib/Transforms/NaCl/ExpandI64.cpp
+++ /dev/null
@@ -1,1107 +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/SmallVector.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Analysis/ConstantFolding.h"
-#include "llvm/Analysis/InstructionSimplify.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/Support/CFG.h"
-#include "llvm/Target/TargetLibraryInfo.h"
-#include "llvm/Transforms/NaCl.h"
-#include "llvm/Transforms/Utils/Local.h"
-#include <map>
-
-#include "llvm/Support/raw_ostream.h"
-
-#ifdef NDEBUG
-#undef assert
-#define assert(x) { if (!(x)) report_fatal_error(#x); }
-#endif
-
-using namespace llvm;
-
-namespace {
-
- 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;
- DataLayout *DL;
- Module *TheModule;
-
- SplitsMap Splits; // old illegal value to new insts
- PHIVec Phis;
-
- // 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
- ChunksVec getChunks(Value *V);
-
- 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);
- virtual void getAnalysisUsage(AnalysisUsage &AU) const;
- };
-}
-
-char ExpandI64::ID = 0;
-INITIALIZE_PASS(ExpandI64, "expand-illegal-ints",
- "Expand and lower illegal >i32 operations into 32-bit chunks",
- false, false)
-
-// Utilities
-
-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(), 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: {
- assert(I->getOperand(0)->getType() == i64);
- Instruction *A, *B, *C, *D, *Final;
- 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);
- }
- A = CopyDebug(new ICmpInst(I, StrictPred, LeftChunks[1], RightChunks[1]), I);
- B = CopyDebug(new ICmpInst(I, ICmpInst::ICMP_EQ, LeftChunks[1], RightChunks[1]), I);
- C = CopyDebug(new ICmpInst(I, UnsignedPred, LeftChunks[0], RightChunks[0]), I);
- D = CopyDebug(BinaryOperator::Create(Instruction::And, B, C, "", I), I);
- Final = CopyDebug(BinaryOperator::Create(Instruction::Or, A, D, "", 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 {
- // 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 = 0;
- for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i) {
- NumItems += i.getCaseValueEx().getNumItems();
- }
- 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();
- const IntegersSubset CaseVal = i.getCaseValueEx();
- assert(CaseVal.isSingleNumbersOnly());
- for (unsigned Index = 0; Index < CaseVal.getNumItems(); Index++) {
- uint64_t Bits = CaseVal.getSingleNumber(Index).toConstantInt()->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
- for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
- PHINode *Phi = dyn_cast<PHINode>(I);
- if (!Phi) break;
- Phi->setIncomingBlock(Phi->getBasicBlockIndex(SwitchBB), NewBB);
- }
- }
-
- // 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.
- for (BasicBlock::iterator I = DD->begin(); I != DD->end(); ++I) {
- PHINode *Phi = dyn_cast<PHINode>(I);
- if (!Phi) break;
- Phi->addIncoming(Phi->getIncomingValue(Phi->getBasicBlockIndex(SwitchBB)), NewBB);
- // XXX note that we add a new i64 thing here. now the phi was already an i64 operation, and is being legalized anyhow, but we only notice the original inputs!
- // we seem to be safe for now due to order of operation (phis show up after switches, but FIXME
- }
- }
- break;
- }
- default: {
- I->dump();
- assert(0 && "some i64 thing we can't legalize yet");
- }
- }
-
- return true;
-}
-
-ChunksVec ExpandI64::getChunks(Value *V) {
- 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);