diff options
| author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-01-23 11:09:33 +0000 |
|---|---|---|
| committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-01-23 11:09:33 +0000 |
| commit | 989df958a10f0beb90b89ccadd8351cbe51d90b1 (patch) | |
| tree | 74eecbae571601ec6a626a53374b1eddc7b164a5 /lib/Transforms/Scalar | |
| parent | 829000e035f46f2a227a5466e4e427a2f3cc00a9 (diff) | |
Notes
Diffstat (limited to 'lib/Transforms/Scalar')
| -rw-r--r-- | lib/Transforms/Scalar/CodeGenPrepare.cpp | 29 | ||||
| -rw-r--r-- | lib/Transforms/Scalar/GVN.cpp | 99 | ||||
| -rw-r--r-- | lib/Transforms/Scalar/IndVarSimplify.cpp | 14 | ||||
| -rw-r--r-- | lib/Transforms/Scalar/Makefile | 1 | ||||
| -rw-r--r-- | lib/Transforms/Scalar/ScalarReplAggregates.cpp | 82 | ||||
| -rw-r--r-- | lib/Transforms/Scalar/SimplifyLibCalls.cpp | 47 |
6 files changed, 132 insertions, 140 deletions
diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 9c1b440bd5c1..c3139a511bb5 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -617,7 +617,23 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, TLI->getTargetData()->getIntPtrType(AccessTy->getContext()); Value *Result = 0; - // Start with the scale value. + + // Start with the base register. Do this first so that subsequent address + // matching finds it last, which will prevent it from trying to match it + // as the scaled value in case it happens to be a mul. That would be + // problematic if we've sunk a different mul for the scale, because then + // we'd end up sinking both muls. + if (AddrMode.BaseReg) { + Value *V = AddrMode.BaseReg; + if (isa<PointerType>(V->getType())) + V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt); + if (V->getType() != IntPtrTy) + V = CastInst::CreateIntegerCast(V, IntPtrTy, /*isSigned=*/true, + "sunkaddr", InsertPt); + Result = V; + } + + // Add the scale value. if (AddrMode.Scale) { Value *V = AddrMode.ScaledReg; if (V->getType() == IntPtrTy) { @@ -634,17 +650,6 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, V = BinaryOperator::CreateMul(V, ConstantInt::get(IntPtrTy, AddrMode.Scale), "sunkaddr", InsertPt); - Result = V; - } - - // Add in the base register. - if (AddrMode.BaseReg) { - Value *V = AddrMode.BaseReg; - if (isa<PointerType>(V->getType())) - V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt); - if (V->getType() != IntPtrTy) - V = CastInst::CreateIntegerCast(V, IntPtrTy, /*isSigned=*/true, - "sunkaddr", InsertPt); if (Result) Result = BinaryOperator::CreateAdd(Result, V, "sunkaddr", InsertPt); else diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index ac0d850360d6..b29fe74b1ec7 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -70,18 +70,44 @@ static cl::opt<bool> EnableLoadPRE("enable-load-pre", cl::init(true)); /// two values. namespace { struct Expression { - enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL, - UDIV, SDIV, FDIV, UREM, SREM, - FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ, - ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE, - ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ, - FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE, - FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE, - FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT, - SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI, - FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT, - PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, CONSTANT, - INSERTVALUE, EXTRACTVALUE, EMPTY, TOMBSTONE }; + enum ExpressionOpcode { + ADD = Instruction::Add, + FADD = Instruction::FAdd, + SUB = Instruction::Sub, + FSUB = Instruction::FSub, + MUL = Instruction::Mul, + FMUL = Instruction::FMul, + UDIV = Instruction::UDiv, + SDIV = Instruction::SDiv, + FDIV = Instruction::FDiv, + UREM = Instruction::URem, + SREM = Instruction::SRem, + FREM = Instruction::FRem, + SHL = Instruction::Shl, + LSHR = Instruction::LShr, + ASHR = Instruction::AShr, + AND = Instruction::And, + OR = Instruction::Or, + XOR = Instruction::Xor, + TRUNC = Instruction::Trunc, + ZEXT = Instruction::ZExt, + SEXT = Instruction::SExt, + FPTOUI = Instruction::FPToUI, + FPTOSI = Instruction::FPToSI, + UITOFP = Instruction::UIToFP, + SITOFP = Instruction::SIToFP, + FPTRUNC = Instruction::FPTrunc, + FPEXT = Instruction::FPExt, + PTRTOINT = Instruction::PtrToInt, + INTTOPTR = Instruction::IntToPtr, + BITCAST = Instruction::BitCast, + ICMPEQ, ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE, + ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ, + FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE, + FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE, + FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT, + SHUFFLE, SELECT, GEP, CALL, CONSTANT, + INSERTVALUE, EXTRACTVALUE, EMPTY, TOMBSTONE }; ExpressionOpcode opcode; const Type* type; @@ -127,9 +153,7 @@ namespace { uint32_t nextValueNumber; - Expression::ExpressionOpcode getOpcode(BinaryOperator* BO); Expression::ExpressionOpcode getOpcode(CmpInst* C); - Expression::ExpressionOpcode getOpcode(CastInst* C); Expression create_expression(BinaryOperator* BO); Expression create_expression(CmpInst* C); Expression create_expression(ShuffleVectorInst* V); @@ -200,30 +224,6 @@ struct isPodLike<Expression> { static const bool value = true; }; //===----------------------------------------------------------------------===// // ValueTable Internal Functions //===----------------------------------------------------------------------===// -Expression::ExpressionOpcode ValueTable::getOpcode(BinaryOperator* BO) { - switch(BO->getOpcode()) { - default: // THIS SHOULD NEVER HAPPEN - llvm_unreachable("Binary operator with unknown opcode?"); - case Instruction::Add: return Expression::ADD; - case Instruction::FAdd: return Expression::FADD; - case Instruction::Sub: return Expression::SUB; - case Instruction::FSub: return Expression::FSUB; - case Instruction::Mul: return Expression::MUL; - case Instruction::FMul: return Expression::FMUL; - case Instruction::UDiv: return Expression::UDIV; - case Instruction::SDiv: return Expression::SDIV; - case Instruction::FDiv: return Expression::FDIV; - case Instruction::URem: return Expression::UREM; - case Instruction::SRem: return Expression::SREM; - case Instruction::FRem: return Expression::FREM; - case Instruction::Shl: return Expression::SHL; - case Instruction::LShr: return Expression::LSHR; - case Instruction::AShr: return Expression::ASHR; - case Instruction::And: return Expression::AND; - case Instruction::Or: return Expression::OR; - case Instruction::Xor: return Expression::XOR; - } -} Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) { if (isa<ICmpInst>(C)) { @@ -263,25 +263,6 @@ Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) { } } -Expression::ExpressionOpcode ValueTable::getOpcode(CastInst* C) { - switch(C->getOpcode()) { - default: // THIS SHOULD NEVER HAPPEN - llvm_unreachable("Cast operator with unknown opcode?"); - case Instruction::Trunc: return Expression::TRUNC; - case Instruction::ZExt: return Expression::ZEXT; - case Instruction::SExt: return Expression::SEXT; - case Instruction::FPToUI: return Expression::FPTOUI; - case Instruction::FPToSI: return Expression::FPTOSI; - case Instruction::UIToFP: return Expression::UITOFP; - case Instruction::SIToFP: return Expression::SITOFP; - case Instruction::FPTrunc: return Expression::FPTRUNC; - case Instruction::FPExt: return Expression::FPEXT; - case Instruction::PtrToInt: return Expression::PTRTOINT; - case Instruction::IntToPtr: return Expression::INTTOPTR; - case Instruction::BitCast: return Expression::BITCAST; - } -} - Expression ValueTable::create_expression(CallInst* C) { Expression e; @@ -302,7 +283,7 @@ Expression ValueTable::create_expression(BinaryOperator* BO) { e.varargs.push_back(lookup_or_add(BO->getOperand(1))); e.function = 0; e.type = BO->getType(); - e.opcode = getOpcode(BO); + e.opcode = static_cast<Expression::ExpressionOpcode>(BO->getOpcode()); return e; } @@ -325,7 +306,7 @@ Expression ValueTable::create_expression(CastInst* C) { e.varargs.push_back(lookup_or_add(C->getOperand(0))); e.function = 0; e.type = C->getType(); - e.opcode = getOpcode(C); + e.opcode = static_cast<Expression::ExpressionOpcode>(C->getOpcode()); return e; } diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index ce1307c8df3b..17f7d985097a 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -471,6 +471,13 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType, // Compute the final addrec to expand into code. const SCEV *AR = IU->getReplacementExpr(*UI); + // Evaluate the expression out of the loop, if possible. + if (!L->contains(UI->getUser())) { + const SCEV *ExitVal = SE->getSCEVAtScope(AR, L->getParentLoop()); + if (ExitVal->isLoopInvariant(L)) + AR = ExitVal; + } + // FIXME: It is an extremely bad idea to indvar substitute anything more // complex than affine induction variables. Doing so will put expensive // polynomial evaluations inside of the loop, and the str reduction pass @@ -522,11 +529,10 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType, Rewriter.clear(); // Now that we're done iterating through lists, clean up any instructions // which are now dead. - while (!DeadInsts.empty()) { - Instruction *Inst = dyn_cast_or_null<Instruction>(DeadInsts.pop_back_val()); - if (Inst) + while (!DeadInsts.empty()) + if (Instruction *Inst = + dyn_cast_or_null<Instruction>(DeadInsts.pop_back_val())) RecursivelyDeleteTriviallyDeadInstructions(Inst); - } } /// If there's a single exit block, sink any loop-invariant values that diff --git a/lib/Transforms/Scalar/Makefile b/lib/Transforms/Scalar/Makefile index cc42fd00ac7d..e18f30f143ea 100644 --- a/lib/Transforms/Scalar/Makefile +++ b/lib/Transforms/Scalar/Makefile @@ -10,6 +10,7 @@ LEVEL = ../../.. LIBRARYNAME = LLVMScalarOpts BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index 9e1e79a1c29c..f4734801e0f8 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -85,10 +85,6 @@ namespace { /// isUnsafe - This is set to true if the alloca cannot be SROA'd. bool isUnsafe : 1; - /// needsCleanup - This is set to true if there is some use of the alloca - /// that requires cleanup. - bool needsCleanup : 1; - /// isMemCpySrc - This is true if this aggregate is memcpy'd from. bool isMemCpySrc : 1; @@ -96,15 +92,14 @@ namespace { bool isMemCpyDst : 1; AllocaInfo() - : isUnsafe(false), needsCleanup(false), - isMemCpySrc(false), isMemCpyDst(false) {} + : isUnsafe(false), isMemCpySrc(false), isMemCpyDst(false) {} }; unsigned SRThreshold; void MarkUnsafe(AllocaInfo &I) { I.isUnsafe = true; } - int isSafeAllocaToScalarRepl(AllocaInst *AI); + bool isSafeAllocaToScalarRepl(AllocaInst *AI); void isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, AllocaInfo &Info); @@ -119,7 +114,6 @@ namespace { void DoScalarReplacement(AllocaInst *AI, std::vector<AllocaInst*> &WorkList); void DeleteDeadInstructions(); - void CleanupAllocaUsers(Value *V); AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocaInst *Base); void RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, @@ -281,14 +275,7 @@ bool SROA::performScalarRepl(Function &F) { getNumSAElements(AI->getAllocatedType()) <= SRThreshold/4) { // Check that all of the users of the allocation are capable of being // transformed. - switch (isSafeAllocaToScalarRepl(AI)) { - default: llvm_unreachable("Unexpected value!"); - case 0: // Not safe to scalar replace. - break; - case 1: // Safe, but requires cleanup/canonicalizations first - CleanupAllocaUsers(AI); - // FALL THROUGH. - case 3: // Safe to scalar replace. + if (isSafeAllocaToScalarRepl(AI)) { DoScalarReplacement(AI, WorkList); Changed = true; continue; @@ -437,14 +424,6 @@ void SROA::isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, SIType, true, Info); } else MarkUnsafe(Info); - } else if (isa<DbgInfoIntrinsic>(UI)) { - // If one user is DbgInfoIntrinsic then check if all users are - // DbgInfoIntrinsics. - if (OnlyUsedByDbgInfoIntrinsics(I)) { - Info.needsCleanup = true; - return; - } - MarkUnsafe(Info); } else { DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); MarkUnsafe(Info); @@ -752,9 +731,16 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, } break; } - // If OtherPtr has already been rewritten, this intrinsic will be dead. - if (OtherPtr == NewElts[0]) + // Copying the alloca to itself is a no-op: just delete it. + if (OtherPtr == AI || OtherPtr == NewElts[0]) { + // This code will run twice for a no-op memcpy -- once for each operand. + // Put only one reference to MI on the DeadInsts list. + for (SmallVector<Value*, 32>::const_iterator I = DeadInsts.begin(), + E = DeadInsts.end(); I != E; ++I) + if (*I == MI) return; + DeadInsts.push_back(MI); return; + } if (ConstantExpr *BCE = dyn_cast<ConstantExpr>(OtherPtr)) if (BCE->getOpcode() == Instruction::BitCast) @@ -779,10 +765,7 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, Value *OtherElt = 0; unsigned OtherEltAlign = MemAlignment; - if (OtherPtr == AI) { - OtherElt = NewElts[i]; - OtherEltAlign = 0; - } else if (OtherPtr) { + if (OtherPtr) { Value *Idx[2] = { Zero, ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) }; OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx, Idx + 2, @@ -1146,7 +1129,7 @@ static bool HasPadding(const Type *Ty, const TargetData &TD) { /// isSafeStructAllocaToScalarRepl - Check to see if the specified allocation of /// an aggregate can be broken down into elements. Return 0 if not, 3 if safe, /// or 1 if safe after canonicalization has been performed. -int SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) { +bool SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) { // Loop over the use list of the alloca. We can only transform it if all of // the users are safe to transform. AllocaInfo Info; @@ -1154,7 +1137,7 @@ int SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) { isSafeForScalarRepl(AI, AI, 0, Info); if (Info.isUnsafe) { DEBUG(dbgs() << "Cannot transform: " << *AI << '\n'); - return 0; + return false; } // Okay, we know all the users are promotable. If the aggregate is a memcpy @@ -1164,29 +1147,9 @@ int SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) { // struct. if (Info.isMemCpySrc && Info.isMemCpyDst && HasPadding(AI->getAllocatedType(), *TD)) - return 0; - - // If we require cleanup, return 1, otherwise return 3. - return Info.needsCleanup ? 1 : 3; -} + return false; -/// CleanupAllocaUsers - If SROA reported that it can promote the specified -/// allocation, but only if cleaned up, perform the cleanups required. -void SROA::CleanupAllocaUsers(Value *V) { - for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); - UI != E; ) { - User *U = *UI++; - Instruction *I = cast<Instruction>(U); - SmallVector<DbgInfoIntrinsic *, 2> DbgInUses; - if (!isa<StoreInst>(I) && OnlyUsedByDbgInfoIntrinsics(I, &DbgInUses)) { - // Safe to remove debug info uses. - while (!DbgInUses.empty()) { - DbgInfoIntrinsic *DI = DbgInUses.pop_back_val(); - DI->eraseFromParent(); - } - I->eraseFromParent(); - } - } + return true; } /// MergeInType - Add the 'In' type to the accumulated type (Accum) so far at @@ -1321,10 +1284,6 @@ bool SROA::CanConvertToScalar(Value *V, bool &IsNotTrivial, const Type *&VecTy, } } - // Ignore dbg intrinsic. - if (isa<DbgInfoIntrinsic>(User)) - continue; - // Otherwise, we cannot handle this! return false; } @@ -1449,18 +1408,11 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset) { } else { // Noop transfer. Src == Dst } - MTI->eraseFromParent(); continue; } - // If user is a dbg info intrinsic then it is safe to remove it. - if (isa<DbgInfoIntrinsic>(User)) { - User->eraseFromParent(); - continue; - } - llvm_unreachable("Unsupported operation!"); } } diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 9183f3aac1fb..a49da9ce9e50 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -81,6 +81,10 @@ public: /// and the return value has 'i8*' type. Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B); + /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the + /// specified pointer arguments. + Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B); + /// EmitMemCpy - Emit a call to the memcpy function to the builder. This /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, @@ -176,6 +180,22 @@ Value *LibCallOptimization::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B) { return CI; } +/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the +/// specified pointer arguments. +Value *LibCallOptimization::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI[2]; + AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + const Type *I8Ptr = Type::getInt8PtrTy(*Context); + Value *StrCpy = M->getOrInsertFunction("strcpy", AttrListPtr::get(AWI, 2), + I8Ptr, I8Ptr, I8Ptr, NULL); + CallInst *CI = B.CreateCall2(StrCpy, CastToCStr(Dst, B), CastToCStr(Src, B), + "strcpy"); + if (const Function *F = dyn_cast<Function>(StrCpy->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + return CI; +} /// EmitMemCpy - Emit a call to the memcpy function to the builder. This always /// expects that the size has type 'intptr_t' and Dst/Src are pointers. @@ -1181,6 +1201,31 @@ struct MemMoveChkOpt : public LibCallOptimization { } }; +struct StrCpyChkOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || + !isa<PointerType>(FT->getParamType(0)) || + !isa<PointerType>(FT->getParamType(1)) || + !isa<IntegerType>(FT->getParamType(2))) + return 0; + + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeCI) + return 0; + + // We don't have any length information, just lower to a plain strcpy. + if (SizeCI->isAllOnesValue()) + return EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B); + + return 0; + } +}; + + //===----------------------------------------------------------------------===// // Math Library Optimizations //===----------------------------------------------------------------------===// @@ -1725,6 +1770,7 @@ namespace { // Object Size Checking MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk; + StrCpyChkOpt StrCpyChk; bool Modified; // This is only used by doInitialization. public: @@ -1836,6 +1882,7 @@ void SimplifyLibCalls::InitOptimizations() { Optimizations["__memcpy_chk"] = &MemCpyChk; Optimizations["__memset_chk"] = &MemSetChk; Optimizations["__memmove_chk"] = &MemMoveChk; + Optimizations["__strcpy_chk"] = &StrCpyChk; } |
