From 4b7948e09e34701e306dccd4943ac09f4ba46275 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 11 Mar 2010 02:41:03 +0000 Subject: [PATCH] Do some final lowering in CodeGenPrepare of _chk calls similar to that in InstCombineCalls. More call lowering needed. llvm-svn: 98228 --- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp index 7ceda1fa1f2c..f5ccebfdefa9 100644 --- a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -28,6 +28,7 @@ #include "llvm/Transforms/Utils/AddrModeMatcher.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" +#include "llvm/Transforms/Utils/BuildLibCalls.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Assembly/Writer.h" @@ -36,6 +37,7 @@ #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/PatternMatch.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/IRBuilder.h" using namespace llvm; using namespace llvm::PatternMatch; @@ -72,6 +74,7 @@ namespace { DenseMap &SunkAddrs); bool OptimizeInlineAsmInst(Instruction *I, CallSite CS, DenseMap &SunkAddrs); + bool OptimizeCallInst(CallInst *CI); bool MoveExtToFormExtLoad(Instruction *I); bool OptimizeExtUses(Instruction *I); void findLoopBackEdges(const Function &F); @@ -537,6 +540,133 @@ static bool OptimizeCmpExpression(CmpInst *CI) { return MadeChange; } +bool CodeGenPrepare::OptimizeCallInst(CallInst *CI) { + bool MadeChange = false; + + // Lower all uses of llvm.objectsize.* + IntrinsicInst *II = dyn_cast(CI); + if (II && II->getIntrinsicID() == Intrinsic::objectsize) { + bool Min = (cast(II->getOperand(2))->getZExtValue() == 1); + const Type *ReturnTy = CI->getType(); + Constant *RetVal = ConstantInt::get(ReturnTy, Min ? 0 : -1ULL); + CI->replaceAllUsesWith(RetVal); + CI->eraseFromParent(); + return true; + } + + // From here on out we're working with named functions. + if (CI->getCalledFunction() == 0) return false; + + // We'll need TargetData from here on out. + const TargetData *TD = TLI ? TLI->getTargetData() : 0; + if (!TD) return false; + + // Lower all default uses of _chk calls. This is code very similar + // to the code in InstCombineCalls, but here we are only lowering calls + // that have the default "don't know" as the objectsize. Anything else + // should be left alone. + 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(CI->getOperand(4)); + if (!SizeCI) + return 0; + if (SizeCI->isAllOnesValue()) { + EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B, TD); + CI->replaceAllUsesWith(CI->getOperand(1)); + CI->eraseFromParent(); + return true; + } + return 0; + } + + // Should be similar to memcpy. + if (Name == "__mempcpy_chk") { + return 0; + } + + if (Name == "__memmove_chk") { + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + if (SizeCI->isAllOnesValue()) { + EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B, TD); + CI->replaceAllUsesWith(CI->getOperand(1)); + CI->eraseFromParent(); + return true; + } + return 0; + } + + if (Name == "__memset_chk") { + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + if (SizeCI->isAllOnesValue()) { + Value *Val = B.CreateIntCast(CI->getOperand(2), B.getInt8Ty(), + false); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD); + CI->replaceAllUsesWith(CI->getOperand(1)); + CI->eraseFromParent(); + return true; + } + return 0; + } + + if (Name == "__strcpy_chk") { + ConstantInt *SizeCI = dyn_cast(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()) { + Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD); + CI->replaceAllUsesWith(Ret); + CI->eraseFromParent(); + return true; + } + return 0; + } + + // Should be similar to strcpy. + if (Name == "__stpcpy_chk") { + return 0; + } + + if (Name == "__strncpy_chk") { + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + if (SizeCI->isAllOnesValue()) { + Value *Ret = EmitStrNCpy(CI->getOperand(1), CI->getOperand(2), + CI->getOperand(3), B, TD); + CI->replaceAllUsesWith(Ret); + CI->eraseFromParent(); + return true; + } + return 0; + } + + if (Name == "__strcat_chk") { + return 0; + } + + if (Name == "__strncat_chk") { + return 0; + } + + return MadeChange; +} //===----------------------------------------------------------------------===// // Memory Optimization //===----------------------------------------------------------------------===// @@ -913,6 +1043,10 @@ bool CodeGenPrepare::OptimizeBlock(BasicBlock &BB) { } else // Sink address computing for memory operands into the block. MadeChange |= OptimizeInlineAsmInst(I, &(*CI), SunkAddrs); + } else { + // Other CallInst optimizations that don't need to muck with the + // enclosing iterator here. + MadeChange |= OptimizeCallInst(CI); } } } -- GitLab