On strtod and friends, mark 'endptr' nocapture in the function prototype, and
mark the first argument nocapture if endptr=NULL for each particular call.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@64453 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
index d8b923a..fed239e 100644
--- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp
+++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
@@ -722,6 +722,26 @@
};
//===---------------------------------------===//
+// '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<PointerType>(FT->getParamType(0)) ||
+ !isa<PointerType>(FT->getParamType(1)))
+ return 0;
+
+ Value *EndPtr = CI->getOperand(2);
+ if (isa<ConstantPointerNull>(EndPtr))
+ CI->addAttribute(1, Attribute::NoCapture);
+
+ return 0;
+ }
+};
+
+
+//===---------------------------------------===//
// 'memcmp' Optimizations
struct VISIBILITY_HIDDEN MemCmpOpt : public LibCallOptimization {
@@ -1329,8 +1349,8 @@
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 @@
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 @@
} 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<PointerType>(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 0000000..3d51d78
--- /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
+}