On strtod and friends, mark 'endptr' nocapture in the function prototype, and
authorNick Lewycky <nicholas@mxc.ca>
Fri, 13 Feb 2009 15:31:46 +0000 (15:31 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Fri, 13 Feb 2009 15:31:46 +0000 (15:31 +0000)
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

lib/Transforms/Scalar/SimplifyLibCalls.cpp
test/Transforms/SimplifyLibCalls/2009-02-12-StrTo.ll [new file with mode: 0644]

index d8b923ac3b86d10364f95e1160029d12df2c180b..fed239eae3690a53490ee45fdcc85296ff2a56e9 100644 (file)
@@ -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<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
 
@@ -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<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 (file)
index 0000000..3d51d78
--- /dev/null
@@ -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
+}