[llvm] ab7ee3c - [InstCombine] Enable strtol folding with nonnull endptr

Martin Sebor via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 13 08:27:54 PDT 2022


Author: Martin Sebor
Date: 2022-07-13T09:26:34-06:00
New Revision: ab7ee3c9911ff90bb209213b1385336f1619d174

URL: https://github.com/llvm/llvm-project/commit/ab7ee3c9911ff90bb209213b1385336f1619d174
DIFF: https://github.com/llvm/llvm-project/commit/ab7ee3c9911ff90bb209213b1385336f1619d174.diff

LOG: [InstCombine] Enable strtol folding with nonnull endptr

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D129593

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
    llvm/test/Transforms/InstCombine/str-int-2.ll
    llvm/test/Transforms/InstCombine/str-int.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index eafb17c1c50b7..b359717424a6a 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -75,7 +75,8 @@ static bool callHasFP128Argument(const CallInst *CI) {
   });
 }
 
-static Value *convertStrToNumber(CallInst *CI, StringRef &Str, int64_t Base) {
+static Value *convertStrToNumber(CallInst *CI, StringRef &Str, Value *EndPtr,
+                                 int64_t Base, IRBuilderBase &B) {
   if (Base < 2 || Base > 36)
     // handle special zero base
     if (Base != 0)
@@ -97,6 +98,15 @@ static Value *convertStrToNumber(CallInst *CI, StringRef &Str, int64_t Base) {
   if (!isIntN(CI->getType()->getPrimitiveSizeInBits(), Result))
     return nullptr;
 
+  if (EndPtr) {
+    // Store the pointer to the end.
+    uint64_t ILen = End - nptr.c_str();
+    Value *Off = B.getInt64(ILen);
+    Value *StrBeg = CI->getArgOperand(0);
+    Value *StrEnd = B.CreateInBoundsGEP(B.getInt8Ty(), StrBeg, Off, "endptr");
+    B.CreateStore(StrEnd, EndPtr);
+  }
+
   return ConstantInt::get(CI->getType(), Result);
 }
 
@@ -2523,7 +2533,7 @@ Value *LibCallSimplifier::optimizeAtoi(CallInst *CI, IRBuilderBase &B) {
   if (!getConstantStringInfo(CI->getArgOperand(0), Str))
     return nullptr;
 
-  return convertStrToNumber(CI, Str, 10);
+  return convertStrToNumber(CI, Str, nullptr, 10, B);
 }
 
 Value *LibCallSimplifier::optimizeStrtol(CallInst *CI, IRBuilderBase &B) {
@@ -2531,11 +2541,14 @@ Value *LibCallSimplifier::optimizeStrtol(CallInst *CI, IRBuilderBase &B) {
   if (!getConstantStringInfo(CI->getArgOperand(0), Str))
     return nullptr;
 
-  if (!isa<ConstantPointerNull>(CI->getArgOperand(1)))
+  Value *EndPtr = CI->getArgOperand(1);
+  if (isa<ConstantPointerNull>(EndPtr))
+    EndPtr = nullptr;
+  else if (!isKnownNonZero(EndPtr, DL))
     return nullptr;
 
   if (ConstantInt *CInt = dyn_cast<ConstantInt>(CI->getArgOperand(2))) {
-    return convertStrToNumber(CI, Str, CInt->getSExtValue());
+    return convertStrToNumber(CI, Str, EndPtr, CInt->getSExtValue(), B);
   }
 
   return nullptr;

diff  --git a/llvm/test/Transforms/InstCombine/str-int-2.ll b/llvm/test/Transforms/InstCombine/str-int-2.ll
index 290c3398f241a..d81ecbb774029 100644
--- a/llvm/test/Transforms/InstCombine/str-int-2.ll
+++ b/llvm/test/Transforms/InstCombine/str-int-2.ll
@@ -40,14 +40,25 @@ define i64 @strtol_hex() #0 {
   ret i64 %call
 }
 
-define i64 @strtol_endptr_not_null() #0 {
+; Fold a call to strtol with an endptr known to be nonnull.
+
+define i64 @strtol_endptr_not_null(i8** nonnull %pend) {
 ; CHECK-LABEL: @strtol_endptr_not_null(
-; CHECK-NEXT:    [[END:%.*]] = alloca i8*, align 4
-; CHECK-NEXT:    [[CALL:%.*]] = call i64 @strtol(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0), i8** nonnull [[END]], i32 10)
+; CHECK-NEXT:    store i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 2), i8** [[PEND:%.*]], align 8
+; CHECK-NEXT:    ret i64 12
+;
+  %call = call i64 @strtol(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i8** %pend, i32 10)
+  ret i64 %call
+}
+
+; Don't fold a call to strtol with an endptr that's not known to be nonnull.
+
+define i64 @strtol_endptr_maybe_null(i8** %end) {
+; CHECK-LABEL: @strtol_endptr_maybe_null(
+; CHECK-NEXT:    [[CALL:%.*]] = call i64 @strtol(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0), i8** [[END:%.*]], i32 10)
 ; CHECK-NEXT:    ret i64 [[CALL]]
 ;
-  %end = alloca i8*, align 4
-  %call = call i64 @strtol(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i32 0, i32 0), i8** %end, i32 10) #2
+  %call = call i64 @strtol(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i32 0, i32 0), i8** %end, i32 10)
   ret i64 %call
 }
 

diff  --git a/llvm/test/Transforms/InstCombine/str-int.ll b/llvm/test/Transforms/InstCombine/str-int.ll
index 6de0a0795b64b..f74d774b42cbf 100644
--- a/llvm/test/Transforms/InstCombine/str-int.ll
+++ b/llvm/test/Transforms/InstCombine/str-int.ll
@@ -40,14 +40,28 @@ define i32 @strtol_hex() #0 {
   ret i32 %call
 }
 
-define i32 @strtol_endptr_not_null() #0 {
+; Fold a call to strtol with an endptr known to be nonnull (the result
+; of pointer increment).
+
+define i32 @strtol_endptr_not_null(i8** %pend) {
 ; CHECK-LABEL: @strtol_endptr_not_null(
-; CHECK-NEXT:    [[END:%.*]] = alloca i8*, align 4
-; CHECK-NEXT:    [[CALL:%.*]] = call i32 @strtol(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0), i8** nonnull [[END]], i32 10)
+; CHECK-NEXT:    [[ENDP1:%.*]] = getelementptr inbounds i8*, i8** [[PEND:%.*]], i64 1
+; CHECK-NEXT:    store i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 2), i8** [[ENDP1]], align 8
+; CHECK-NEXT:    ret i32 12
+;
+  %endp1 = getelementptr inbounds i8*, i8** %pend, i32 1
+  %call = call i32 @strtol(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i8** %endp1, i32 10)
+  ret i32 %call
+}
+
+; Don't fold a call to strtol with an endptr that's not known to be nonnull.
+
+define i32 @strtol_endptr_maybe_null(i8** %end) {
+; CHECK-LABEL: @strtol_endptr_maybe_null(
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 @strtol(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0), i8** [[END:%.*]], i32 10)
 ; CHECK-NEXT:    ret i32 [[CALL]]
 ;
-  %end = alloca i8*, align 4
-  %call = call i32 @strtol(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i32 0, i32 0), i8** %end, i32 10) #2
+  %call = call i32 @strtol(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i32 0, i32 0), i8** %end, i32 10)
   ret i32 %call
 }
 


        


More information about the llvm-commits mailing list