diff options
author | Dan Gohman <sunfish@google.com> | 2014-02-24 08:49:19 -0800 |
---|---|---|
committer | Dan Gohman <sunfish@google.com> | 2014-02-25 11:58:56 -0800 |
commit | 338da97ed47659b9ef04f60067f84cafc93e3dd3 (patch) | |
tree | 2a80c78435712eafe02ea4afdc96c8d7713016cb /lib/Transforms | |
parent | 5653eb58d0b0068f0ef341c8928aa06d1d0ea3f7 (diff) |
Support GEP and ConstantExprs directly in the JSBackend.
This patch also lays the groundwork for the single-use instruction trick to
reduce the number of temporary variables.
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/NaCl/ExpandI64.cpp | 55 | ||||
-rw-r--r-- | lib/Transforms/NaCl/ExpandVarArgs.cpp | 11 | ||||
-rw-r--r-- | lib/Transforms/NaCl/LowerEmExceptionsPass.cpp | 16 | ||||
-rw-r--r-- | lib/Transforms/NaCl/PNaClABISimplify.cpp | 4 | ||||
-rw-r--r-- | lib/Transforms/NaCl/PromoteIntegers.cpp | 10 |
5 files changed, 68 insertions, 28 deletions
diff --git a/lib/Transforms/NaCl/ExpandI64.cpp b/lib/Transforms/NaCl/ExpandI64.cpp index a4fbb8c709..911060ebfc 100644 --- a/lib/Transforms/NaCl/ExpandI64.cpp +++ b/lib/Transforms/NaCl/ExpandI64.cpp @@ -28,6 +28,7 @@ #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" @@ -37,6 +38,7 @@ #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> @@ -302,6 +304,23 @@ bool ExpandI64::splitInst(Instruction *I) { 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); @@ -881,32 +900,32 @@ bool ExpandI64::splitInst(Instruction *I) { ChunksVec ExpandI64::getChunks(Value *V) { assert(isIllegal(V->getType())); + unsigned Num = getNumChunks(V->getType()); Type *i32 = Type::getInt32Ty(V->getContext()); - Value *Zero = ConstantInt::get(i32, 0); - unsigned Num = getNumChunks(V->getType()); + if (isa<UndefValue>(V)) + return ChunksVec(Num, UndefValue::get(i32)); - if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { - APInt C = CI->getValue(); - ChunksVec Chunks; - for (unsigned i = 0; i < Num; i++) { - Chunks.push_back(ConstantInt::get(i32, C.trunc(32))); - C = C.lshr(32); - } - return Chunks; - } else if (Instruction *I = dyn_cast<Instruction>(V)) { - assert(Splits.find(I) != Splits.end()); - return Splits[I]; - } else if (isa<UndefValue>(V)) { + if (Constant *C = dyn_cast<Constant>(V)) { ChunksVec Chunks; for (unsigned i = 0; i < Num; i++) { - Chunks.push_back(Zero); + 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; - } else { - assert(Splits.find(V) != Splits.end()); - return Splits[V]; } + + assert(Splits.find(V) != Splits.end()); + assert(Splits[V].size() == Num); + return Splits[V]; } void ExpandI64::ensureFuncs() { diff --git a/lib/Transforms/NaCl/ExpandVarArgs.cpp b/lib/Transforms/NaCl/ExpandVarArgs.cpp index 99c200c9f0..1b605b79ee 100644 --- a/lib/Transforms/NaCl/ExpandVarArgs.cpp +++ b/lib/Transforms/NaCl/ExpandVarArgs.cpp @@ -283,9 +283,14 @@ static bool ExpandVarArgCall(InstType *Call, DataLayout *DL) { ArgTypes.push_back(VarArgsTy->getPointerTo()); FunctionType *NFTy = FunctionType::get(FuncType->getReturnType(), ArgTypes, false); - Value *CastFunc = - CopyDebug(new BitCastInst(Call->getCalledValue(), NFTy->getPointerTo(), - "vararg_func", Call), Call); + /// XXX EMSCRIPTEN: Handle Constants as well as Instructions, since we + /// don't run the ConstantExpr lowering pass. + Value *CastFunc; + if (Constant *C = dyn_cast<Constant>(Call->getCalledValue())) + CastFunc = ConstantExpr::getBitCast(C, NFTy->getPointerTo()); + else + CastFunc = CopyDebug(new BitCastInst(Call->getCalledValue(), NFTy->getPointerTo(), + "vararg_func", Call), Call); // Create the converted function call. FixedArgs.push_back(Buf); diff --git a/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp b/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp index a562588c3a..2e3f0924cc 100644 --- a/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp +++ b/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp @@ -231,7 +231,21 @@ bool LowerEmExceptions::runOnModule(Module &M) { unsigned Num = LP->getNumClauses(); SmallVector<Value*,16> NewLPArgs; NewLPArgs.push_back(LP->getPersonalityFn()); - for (unsigned i = 0; i < Num; i++) NewLPArgs.push_back(LP->getClause(i)); + for (unsigned i = 0; i < Num; i++) { + Value *Arg = LP->getClause(i); + // As a temporary workaround for the lack of aggregate varargs support + // in the varargs lowering code, break out filter operands into their + // component elements. + if (LP->isFilter(i)) { + ArrayType *ATy = cast<ArrayType>(Arg->getType()); + for (unsigned elem = 0, elemEnd = ATy->getNumElements(); elem != elemEnd; ++elem) { + Instruction *EE = ExtractValueInst::Create(Arg, makeArrayRef(elem), "", LP); + NewLPArgs.push_back(EE); + } + } else { + NewLPArgs.push_back(Arg); + } + } NewLPArgs.push_back(LP->isCleanup() ? ConstantInt::getTrue(i1) : ConstantInt::getFalse(i1)); CallInst *NewLP = CallInst::Create(LandingPad, NewLPArgs, "", LP); diff --git a/lib/Transforms/NaCl/PNaClABISimplify.cpp b/lib/Transforms/NaCl/PNaClABISimplify.cpp index 520663152a..416c38dd17 100644 --- a/lib/Transforms/NaCl/PNaClABISimplify.cpp +++ b/lib/Transforms/NaCl/PNaClABISimplify.cpp @@ -116,15 +116,19 @@ void llvm::PNaClABISimplifyAddPostOptPasses(PassManager &PM) { // are expanded out later. PM.add(createFlattenGlobalsPass()); +#if 0 // XXX EMSCRIPTEN: We can handle ConstantExprs in our backend. // We should not place arbitrary passes after ExpandConstantExpr // because they might reintroduce ConstantExprs. PM.add(createExpandConstantExprPass()); +#endif // PromoteIntegersPass does not handle constexprs and creates GEPs, // so it goes between those passes. PM.add(createPromoteIntegersPass()); +#if 0 // XXX EMSCRIPTEN: We can handle GEPs in our backend. // ExpandGetElementPtr must follow ExpandConstantExpr to expand the // getelementptr instructions it creates. PM.add(createExpandGetElementPtrPass()); +#endif // Rewrite atomic and volatile instructions with intrinsic calls. #if 0 // EMSCRIPTEN: we don't need to fix volatiles etc, and can use llvm intrinsics PM.add(createRewriteAtomicsPass()); diff --git a/lib/Transforms/NaCl/PromoteIntegers.cpp b/lib/Transforms/NaCl/PromoteIntegers.cpp index b8050b5ba2..af34faa7e5 100644 --- a/lib/Transforms/NaCl/PromoteIntegers.cpp +++ b/lib/Transforms/NaCl/PromoteIntegers.cpp @@ -233,14 +233,14 @@ class ConversionState { Value *PromoteIntegers::splitLoad(LoadInst *Inst, ConversionState &State) { if (Inst->isVolatile() || Inst->isAtomic()) report_fatal_error("Can't split volatile/atomic loads"); - if (cast<IntegerType>(Inst->getType())->getBitWidth() % 8 != 0) + if (DL->getTypeSizeInBits(Inst->getType()) % 8 != 0) report_fatal_error("Loads must be a multiple of 8 bits"); Value *OrigPtr = State.getConverted(Inst->getPointerOperand()); // OrigPtr is a placeholder in recursive calls, and so has no name if (OrigPtr->getName().empty()) OrigPtr->setName(Inst->getPointerOperand()->getName()); - unsigned Width = cast<IntegerType>(Inst->getType())->getBitWidth(); + unsigned Width = DL->getTypeSizeInBits(Inst->getType()); Type *NewType = getPromotedType(Inst->getType()); unsigned LoWidth = Width; @@ -293,8 +293,7 @@ Value *PromoteIntegers::splitLoad(LoadInst *Inst, ConversionState &State) { Value *PromoteIntegers::splitStore(StoreInst *Inst, ConversionState &State) { if (Inst->isVolatile() || Inst->isAtomic()) report_fatal_error("Can't split volatile/atomic stores"); - if (cast<IntegerType>(Inst->getValueOperand()->getType())->getBitWidth() % 8 - != 0) + if (DL->getTypeSizeInBits(Inst->getValueOperand()->getType()) % 8 != 0) report_fatal_error("Stores must be a multiple of 8 bits"); Value *OrigPtr = State.getConverted(Inst->getPointerOperand()); @@ -302,8 +301,7 @@ Value *PromoteIntegers::splitStore(StoreInst *Inst, ConversionState &State) { if (OrigPtr->getName().empty()) OrigPtr->setName(Inst->getPointerOperand()->getName()); Value *OrigVal = State.getConverted(Inst->getValueOperand()); - unsigned Width = cast<IntegerType>( - Inst->getValueOperand()->getType())->getBitWidth(); + unsigned Width = DL->getTypeSizeInBits(Inst->getValueOperand()->getType()); unsigned LoWidth = Width; while (!isLegalSize(LoWidth)) LoWidth -= 8; |