diff options
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/IPO/InlineAlways.cpp | 5 | ||||
-rw-r--r-- | lib/Transforms/IPO/InlineSimple.cpp | 3 | ||||
-rw-r--r-- | lib/Transforms/IPO/Inliner.cpp | 15 | ||||
-rw-r--r-- | lib/Transforms/InstCombine/InstCombine.h | 1 | ||||
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineCalls.cpp | 141 | ||||
-rw-r--r-- | lib/Transforms/Scalar/SimplifyLibCalls.cpp | 134 | ||||
-rw-r--r-- | lib/Transforms/Utils/CloneFunction.cpp | 6 | ||||
-rw-r--r-- | lib/Transforms/Utils/LoopSimplify.cpp | 2 |
8 files changed, 160 insertions, 147 deletions
diff --git a/lib/Transforms/IPO/InlineAlways.cpp b/lib/Transforms/IPO/InlineAlways.cpp index f11ecae..bc8028c 100644 --- a/lib/Transforms/IPO/InlineAlways.cpp +++ b/lib/Transforms/IPO/InlineAlways.cpp @@ -45,7 +45,10 @@ namespace { return CA.getInlineFudgeFactor(CS); } void resetCachedCostInfo(Function *Caller) { - return CA.resetCachedCostInfo(Caller); + CA.resetCachedCostInfo(Caller); + } + void growCachedCostInfo(Function* Caller, Function* Callee) { + CA.growCachedCostInfo(Caller, Callee); } virtual bool doFinalization(CallGraph &CG) { return removeDeadFunctions(CG, &NeverInline); diff --git a/lib/Transforms/IPO/InlineSimple.cpp b/lib/Transforms/IPO/InlineSimple.cpp index 598043d..46cf4b2 100644 --- a/lib/Transforms/IPO/InlineSimple.cpp +++ b/lib/Transforms/IPO/InlineSimple.cpp @@ -45,6 +45,9 @@ namespace { void resetCachedCostInfo(Function *Caller) { CA.resetCachedCostInfo(Caller); } + void growCachedCostInfo(Function* Caller, Function* Callee) { + CA.growCachedCostInfo(Caller, Callee); + } virtual bool doInitialization(CallGraph &CG); }; } diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index 752a97c..03ec72c 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -219,8 +219,10 @@ bool Inliner::shouldInline(CallSite CS) { Function *Caller = CS.getCaller(); int CurrentThreshold = getInlineThreshold(CS); float FudgeFactor = getInlineFudgeFactor(CS); - if (Cost >= (int)(CurrentThreshold * FudgeFactor)) { + int AdjThreshold = (int)(CurrentThreshold * FudgeFactor); + if (Cost >= AdjThreshold) { DEBUG(dbgs() << " NOT Inlining: cost=" << Cost + << ", thres=" << AdjThreshold << ", Call: " << *CS.getInstruction() << "\n"); return false; } @@ -285,6 +287,7 @@ bool Inliner::shouldInline(CallSite CS) { } DEBUG(dbgs() << " Inlining: cost=" << Cost + << ", thres=" << AdjThreshold << ", Call: " << *CS.getInstruction() << '\n'); return true; } @@ -366,6 +369,8 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) { CG[Caller]->removeCallEdgeFor(CS); CS.getInstruction()->eraseFromParent(); ++NumCallsDeleted; + // Update the cached cost info with the missing call + growCachedCostInfo(Caller, NULL); } else { // We can only inline direct calls to non-declarations. if (Callee == 0 || Callee->isDeclaration()) continue; @@ -379,6 +384,9 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) { if (!InlineCallIfPossible(CS, CG, TD, InlinedArrayAllocas)) continue; ++NumInlined; + + // Update the cached cost info with the inlined call. + growCachedCostInfo(Caller, Callee); } // If we inlined or deleted the last possible call site to the function, @@ -404,11 +412,6 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) { delete CG.removeFunctionFromModule(CalleeNode); ++NumDeleted; } - - // Remove any cached cost info for this caller, as inlining the - // callee has increased the size of the caller (which may be the - // same as the callee). - resetCachedCostInfo(Caller); // Remove this call site from the list. If possible, use // swap/pop_back for efficiency, but do not use it if doing so would diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h index 07fb15e..bd06499 100644 --- a/lib/Transforms/InstCombine/InstCombine.h +++ b/lib/Transforms/InstCombine/InstCombine.h @@ -207,6 +207,7 @@ private: const Type *Ty); Instruction *visitCallSite(CallSite CS); + Instruction *tryOptimizeCall(CallInst *CI, const TargetData *TD); bool transformConstExprCastCall(CallSite CS); Instruction *transformCallThroughTrampoline(CallSite CS); Instruction *transformZExtICmp(ICmpInst *ICI, Instruction &CI, diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index a241f169..0582210 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -16,6 +16,7 @@ #include "llvm/Support/CallSite.h" #include "llvm/Target/TargetData.h" #include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Transforms/Utils/BuildLibCalls.h" using namespace llvm; /// getPromotedType - Return the specified type promoted as it would be to pass @@ -336,6 +337,16 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { } return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, AllocaSize)); } + } else if (CallInst *MI = extractMallocCall(Op1)) { + const Type* MallocType = getMallocAllocatedType(MI); + // Get alloca size. + if (MallocType && MallocType->isSized()) { + if (Value *NElems = getMallocArraySize(MI, TD, true)) { + if (ConstantInt *NElements = dyn_cast<ConstantInt>(NElems)) + return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, + (NElements->getZExtValue() * TD->getTypeAllocSize(MallocType)))); + } + } } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Op1)) { // Only handle constant GEPs here. if (CE->getOpcode() != Instruction::GetElementPtr) break; @@ -347,7 +358,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { Operand = Operand->stripPointerCasts(); if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Operand)) if (!GV->hasDefinitiveInitializer()) break; - + // Get what we're pointing to and its size. const PointerType *BaseType = cast<PointerType>(Operand->getType()); @@ -370,7 +381,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { Constant *RetVal = ConstantInt::get(ReturnTy, Size-Offset); return ReplaceInstUsesWith(CI, RetVal); - } + } // Do not return "I don't know" here. Later optimization passes could // make it possible to evaluate objectsize to a constant. @@ -740,6 +751,122 @@ static bool isSafeToEliminateVarargsCast(const CallSite CS, return true; } +// Try to fold some different type of calls here. +// Currently we're only working with the checking functions, memcpy_chk, +// mempcpy_chk, memmove_chk, memset_chk, strcpy_chk, stpcpy_chk, strncpy_chk, +// strcat_chk and strncat_chk. +Instruction *InstCombiner::tryOptimizeCall(CallInst *CI, const TargetData *TD) { + if (CI->getCalledFunction() == 0) return 0; + + StringRef Name = CI->getCalledFunction()->getName(); + BasicBlock *BB = CI->getParent(); + IRBuilder<> B(CI->getParent()->getContext()); + + // Set the builder to the instruction after the call. + B.SetInsertPoint(BB, CI); + + if (Name == "__memcpy_chk") { + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B, TD); + return ReplaceInstUsesWith(*CI, CI->getOperand(1)); + } + return 0; + } + + // Should be similar to memcpy. + if (Name == "__mempcpy_chk") { + return 0; + } + + if (Name == "__memmove_chk") { + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B, TD); + return ReplaceInstUsesWith(*CI, CI->getOperand(1)); + } + return 0; + } + + if (Name == "__memset_chk") { + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + Value *Val = B.CreateIntCast(CI->getOperand(2), B.getInt8Ty(), + false); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD); + return ReplaceInstUsesWith(*CI, CI->getOperand(1)); + } + return 0; + } + + if (Name == "__strcpy_chk") { + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeCI) + return 0; + // If a) we don't have any length information, or b) we know this will + // fit then just lower to a plain strcpy. Otherwise we'll keep our + // strcpy_chk call which may fail at runtime if the size is too long. + // TODO: It might be nice to get a maximum length out of the possible + // string lengths for varying. + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() >= GetStringLength(CI->getOperand(2))) { + Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD); + return ReplaceInstUsesWith(*CI, Ret); + } + return 0; + } + + // Should be similar to strcpy. + if (Name == "__stpcpy_chk") { + return 0; + } + + if (Name == "__strncpy_chk") { + ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD); + return ReplaceInstUsesWith(*CI, Ret); + } + return 0; + } + + if (Name == "__strcat_chk") { + return 0; + } + + if (Name == "__strncat_chk") { + return 0; + } + + return 0; +} + // visitCallSite - Improvements for call and invoke instructions. // Instruction *InstCombiner::visitCallSite(CallSite CS) { @@ -826,6 +953,16 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) { Changed = true; } + // Try to optimize the call if possible, we require TargetData for most of + // this. None of these calls are seen as possibly dead so go ahead and + // delete the instruction now. + if (CallInst *CI = dyn_cast<CallInst>(CS.getInstruction())) { + Instruction *I = tryOptimizeCall(CI, TD); + // If we changed something return the result, etc. Otherwise let + // the fallthrough check. + if (I) return EraseInstFromFunction(*I); + } + return Changed ? CS.getInstruction() : 0; } diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 86ddeac..05027ae 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -633,130 +633,6 @@ struct MemSetOpt : public LibCallOptimization { }; //===----------------------------------------------------------------------===// -// Object Size Checking Optimizations -//===----------------------------------------------------------------------===// - -//===---------------------------------------===// -// 'memcpy_chk' Optimizations - -struct MemCpyChkOpt : 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() != 4 || FT->getReturnType() != FT->getParamType(0) || - !FT->getParamType(0)->isPointerTy() || - !FT->getParamType(1)->isPointerTy() || - !FT->getParamType(3)->isIntegerTy() || - FT->getParamType(2) != TD->getIntPtrType(*Context)) - return 0; - - ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); - if (!ObjSizeCI) - return 0; - ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); - if (ObjSizeCI->isAllOnesValue() || - (SizeCI && ObjSizeCI->getValue().uge(SizeCI->getValue()))) { - EmitMemCpy(CI->getOperand(1), CI->getOperand(2), - CI->getOperand(3), 1, B, TD); - return CI->getOperand(1); - } - - return 0; - } -}; - -//===---------------------------------------===// -// 'memset_chk' Optimizations - -struct MemSetChkOpt : 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() != 4 || FT->getReturnType() != FT->getParamType(0) || - !FT->getParamType(0)->isPointerTy() || - !FT->getParamType(1)->isIntegerTy() || - !FT->getParamType(3)->isIntegerTy() || - FT->getParamType(2) != TD->getIntPtrType(*Context)) - return 0; - - ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); - if (!ObjSizeCI) - return 0; - ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); - if (ObjSizeCI->isAllOnesValue() || - (SizeCI && ObjSizeCI->getValue().uge(SizeCI->getValue()))) { - Value *Val = B.CreateIntCast(CI->getOperand(2), Type::getInt8Ty(*Context), - false); - EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD); - return CI->getOperand(1); - } - - return 0; - } -}; - -//===---------------------------------------===// -// 'memmove_chk' Optimizations - -struct MemMoveChkOpt : 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() != 4 || FT->getReturnType() != FT->getParamType(0) || - !FT->getParamType(0)->isPointerTy() || - !FT->getParamType(1)->isPointerTy() || - !FT->getParamType(3)->isIntegerTy() || - FT->getParamType(2) != TD->getIntPtrType(*Context)) - return 0; - - ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); - if (!ObjSizeCI) - return 0; - ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); - if (ObjSizeCI->isAllOnesValue() || - (SizeCI && ObjSizeCI->getValue().uge(SizeCI->getValue()))) { - EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), - 1, B, TD); - return CI->getOperand(1); - } - - return 0; - } -}; - -struct StrCpyChkOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || - !FT->getParamType(0)->isPointerTy() || - !FT->getParamType(1)->isPointerTy()) - return 0; - - ConstantInt *ObjSizeCI = dyn_cast<ConstantInt>(CI->getOperand(3)); - if (!ObjSizeCI) - return 0; - - // If a) we don't have any length information, or b) we know this will - // fit then just lower to a plain strcpy. Otherwise we'll keep our - // strcpy_chk call which may fail at runtime if the size is too long. - // TODO: It might be nice to get a maximum length out of the possible - // string lengths for varying. - if (ObjSizeCI->isAllOnesValue() || - ObjSizeCI->getZExtValue() >= GetStringLength(CI->getOperand(2))) - return EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD); - - return 0; - } -}; - - -//===----------------------------------------------------------------------===// // Math Library Optimizations //===----------------------------------------------------------------------===// @@ -1298,10 +1174,6 @@ namespace { SPrintFOpt SPrintF; PrintFOpt PrintF; FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF; - // Object Size Checking - MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk; - StrCpyChkOpt StrCpyChk; - bool Modified; // This is only used by doInitialization. public: static char ID; // Pass identification @@ -1407,12 +1279,6 @@ void SimplifyLibCalls::InitOptimizations() { Optimizations["fwrite"] = &FWrite; Optimizations["fputs"] = &FPuts; Optimizations["fprintf"] = &FPrintF; - - // Object Size Checking - Optimizations["__memcpy_chk"] = &MemCpyChk; - Optimizations["__memset_chk"] = &MemSetChk; - Optimizations["__memmove_chk"] = &MemMoveChk; - Optimizations["__strcpy_chk"] = &StrCpyChk; } diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index c80827d..62fc2ec 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -336,14 +336,14 @@ ConstantFoldMappedInstruction(const Instruction *I) { static MDNode *UpdateInlinedAtInfo(MDNode *InsnMD, MDNode *TheCallMD) { DILocation ILoc(InsnMD); - if (ILoc.isNull()) return InsnMD; + if (!ILoc.Verify()) return InsnMD; DILocation CallLoc(TheCallMD); - if (CallLoc.isNull()) return InsnMD; + if (!CallLoc.Verify()) return InsnMD; DILocation OrigLocation = ILoc.getOrigLocation(); MDNode *NewLoc = TheCallMD; - if (!OrigLocation.isNull()) + if (OrigLocation.Verify()) NewLoc = UpdateInlinedAtInfo(OrigLocation.getNode(), TheCallMD); Value *MDVs[] = { diff --git a/lib/Transforms/Utils/LoopSimplify.cpp b/lib/Transforms/Utils/LoopSimplify.cpp index 924b744..584ec14 100644 --- a/lib/Transforms/Utils/LoopSimplify.cpp +++ b/lib/Transforms/Utils/LoopSimplify.cpp @@ -132,7 +132,7 @@ bool LoopSimplify::ProcessLoop(Loop *L, LPPassManager &LPM) { bool Changed = false; ReprocessLoop: - // Check to see that no blocks (other than the header) in this loop that has + // Check to see that no blocks (other than the header) in this loop have // predecessors that are not in the loop. This is not valid for natural // loops, but can occur if the blocks are unreachable. Since they are // unreachable we can just shamelessly delete those CFG edges! |