diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index d8b923ac3b8..fed239eae36 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -721,6 +721,26 @@ struct VISIBILITY_HIDDEN StrLenOpt : public LibCallOptimization { } }; +//===---------------------------------------===// +// 'strto*' Optimizations + +struct VISIBILITY_HIDDEN StrToOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if ((FT->getNumParams() != 2 && FT->getNumParams() != 3) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1))) + return 0; + + Value *EndPtr = CI->getOperand(2); + if (isa(EndPtr)) + CI->addAttribute(1, Attribute::NoCapture); + + return 0; + } +}; + + //===---------------------------------------===// // 'memcmp' Optimizations @@ -1329,8 +1349,8 @@ namespace { ExitOpt Exit; // String and Memory LibCall Optimizations StrCatOpt StrCat; StrChrOpt StrChr; StrCmpOpt StrCmp; StrNCmpOpt StrNCmp; - StrCpyOpt StrCpy; StrLenOpt StrLen; MemCmpOpt MemCmp; MemCpyOpt MemCpy; - MemMoveOpt MemMove; MemSetOpt MemSet; + StrCpyOpt StrCpy; StrLenOpt StrLen; StrToOpt StrTo; MemCmpOpt MemCmp; + MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet; // Math Library Optimizations PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP; // Integer Optimizations @@ -1383,6 +1403,13 @@ void SimplifyLibCalls::InitOptimizations() { Optimizations["strncmp"] = &StrNCmp; Optimizations["strcpy"] = &StrCpy; Optimizations["strlen"] = &StrLen; + Optimizations["strtol"] = &StrTo; + Optimizations["strtod"] = &StrTo; + Optimizations["strtof"] = &StrTo; + Optimizations["strtoul"] = &StrTo; + Optimizations["strtoll"] = &StrTo; + Optimizations["strtold"] = &StrTo; + Optimizations["strtoull"] = &StrTo; Optimizations["memcmp"] = &MemCmp; Optimizations["memcpy"] = &MemCpy; Optimizations["memmove"] = &MemMove; @@ -1566,8 +1593,15 @@ bool SimplifyLibCalls::doInitialization(Module &M) { } else if ((NameLen == 6 && !strcmp(NameStr, "strcpy")) || (NameLen == 6 && !strcmp(NameStr, "stpcpy")) || (NameLen == 6 && !strcmp(NameStr, "strcat")) || + (NameLen == 6 && !strcmp(NameStr, "strtol")) || + (NameLen == 6 && !strcmp(NameStr, "strtod")) || + (NameLen == 6 && !strcmp(NameStr, "strtof")) || + (NameLen == 7 && !strcmp(NameStr, "strtoul")) || + (NameLen == 7 && !strcmp(NameStr, "strtoll")) || + (NameLen == 7 && !strcmp(NameStr, "strtold")) || (NameLen == 7 && !strcmp(NameStr, "strncat")) || - (NameLen == 7 && !strcmp(NameStr, "strncpy"))) { + (NameLen == 7 && !strcmp(NameStr, "strncpy")) || + (NameLen == 8 && !strcmp(NameStr, "strtoull"))) { if (FTy->getNumParams() < 2 || !isa(FTy->getParamType(1))) continue; diff --git a/test/Transforms/SimplifyLibCalls/2009-02-12-StrTo.ll b/test/Transforms/SimplifyLibCalls/2009-02-12-StrTo.ll new file mode 100644 index 00000000000..3d51d78ecea --- /dev/null +++ b/test/Transforms/SimplifyLibCalls/2009-02-12-StrTo.ll @@ -0,0 +1,13 @@ +; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis > %t +; RUN: grep nocapture %t | count 2 +; RUN: grep null %t | grep nocapture | count 1 + +; Test that we do add nocapture to the declaration, and to the second call only. + +declare float @strtof(i8* %s, i8** %endptr, i32 %base) + +define void @foo(i8* %x, i8** %endptr) { + call float @strtof(i8* %x, i8** %endptr, i32 0) + call float @strtof(i8* %x, i8** null, i32 0) + ret void +}