[llvm] 449adaf - [InstCombine] Fold strnlen of constant strings.

Martin Sebor via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 26 15:16:02 PDT 2022


Author: Martin Sebor
Date: 2022-04-26T16:15:28-06:00
New Revision: 449adafabe46ded951bf9bcde9c88c883c8aa0e6

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

LOG: [InstCombine] Fold strnlen of constant strings.

Reviewed By: nikic

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

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
    llvm/test/Transforms/InstCombine/strnlen-1.ll
    llvm/test/Transforms/InstCombine/strnlen-3.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 312aebf46db7c..a948a554e2799 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -632,6 +632,7 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B,
                                                unsigned CharSize,
                                                Value *Bound) {
   Value *Src = CI->getArgOperand(0);
+  Type *CharTy = B.getIntNTy(CharSize);
 
   if (Bound) {
     if (ConstantInt *BoundCst = dyn_cast<ConstantInt>(Bound)) {
@@ -641,20 +642,26 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B,
 
       if (BoundCst->isOne()) {
         // Fold strnlen(s, 1) -> *s ? 1 : 0 for any s.
-        Type *CharTy = B.getIntNTy(CharSize);
         Value *CharVal = B.CreateLoad(CharTy, Src, "strnlen.char0");
         Value *ZeroChar = ConstantInt::get(CharTy, 0);
         Value *Cmp = B.CreateICmpNE(CharVal, ZeroChar, "strnlen.char0cmp");
         return B.CreateZExt(Cmp, CI->getType());
       }
     }
-    // Otherwise punt for strnlen for now.
-    return nullptr;
   }
 
-  // Constant folding: strlen("xyz") -> 3
-  if (uint64_t Len = GetStringLength(Src, CharSize))
-    return ConstantInt::get(CI->getType(), Len - 1);
+  if (uint64_t Len = GetStringLength(Src, CharSize)) {
+    Value *LenC = ConstantInt::get(CI->getType(), Len - 1);
+    // Fold strlen("xyz") -> 3 and strnlen("xyz", 2) -> 2
+    // and strnlen("xyz", Bound) -> min(3, Bound) for nonconstant Bound.
+    if (Bound)
+      return B.CreateBinaryIntrinsic(Intrinsic::umin, LenC, Bound);
+    return LenC;
+  }
+
+  if (Bound)
+    // Punt for strnlen for now.
+    return nullptr;
 
   // If s is a constant pointer pointing to a string literal, we can fold
   // strlen(s + x) to strlen(s) - x, when x is known to be in the range

diff  --git a/llvm/test/Transforms/InstCombine/strnlen-1.ll b/llvm/test/Transforms/InstCombine/strnlen-1.ll
index d07e8ddb9893d..d17c11e21964c 100644
--- a/llvm/test/Transforms/InstCombine/strnlen-1.ll
+++ b/llvm/test/Transforms/InstCombine/strnlen-1.ll
@@ -95,8 +95,7 @@ define i64 @fold_strnlen_s5_0() {
 
 define i64 @fold_strnlen_s5_4() {
 ; CHECK-LABEL: @fold_strnlen_s5_4(
-; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i64 4)
-; CHECK-NEXT:    ret i64 [[LEN]]
+; CHECK-NEXT:    ret i64 4
 ;
   %ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0
   %len = call i64 @strnlen(i8* %ptr, i64 4)
@@ -108,8 +107,7 @@ define i64 @fold_strnlen_s5_4() {
 
 define i64 @fold_strnlen_s5_5() {
 ; CHECK-LABEL: @fold_strnlen_s5_5(
-; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i64 5)
-; CHECK-NEXT:    ret i64 [[LEN]]
+; CHECK-NEXT:    ret i64 5
 ;
   %ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0
   %len = call i64 @strnlen(i8* %ptr, i64 5)
@@ -121,8 +119,7 @@ define i64 @fold_strnlen_s5_5() {
 
 define i64 @fold_strnlen_s5_m1() {
 ; CHECK-LABEL: @fold_strnlen_s5_m1(
-; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i64 -1)
-; CHECK-NEXT:    ret i64 [[LEN]]
+; CHECK-NEXT:    ret i64 5
 ;
   %ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0
   %len = call i64 @strnlen(i8* %ptr, i64 -1)
@@ -134,8 +131,7 @@ define i64 @fold_strnlen_s5_m1() {
 
 define i64 @fold_strnlen_s5_3_p4_5() {
 ; CHECK-LABEL: @fold_strnlen_s5_3_p4_5(
-; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @s5_3, i64 0, i64 4), i64 5)
-; CHECK-NEXT:    ret i64 [[LEN]]
+; CHECK-NEXT:    ret i64 1
 ;
   %ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 4
   %len = call i64 @strnlen(i8* %ptr, i64 5)
@@ -143,12 +139,11 @@ define i64 @fold_strnlen_s5_3_p4_5() {
 }
 
 
-; Fold strnlen(s5_3 + 5, 5) to 1.
+; Fold strnlen(s5_3 + 5, 5) to 0.
 
 define i64 @fold_strnlen_s5_3_p5_5() {
 ; CHECK-LABEL: @fold_strnlen_s5_3_p5_5(
-; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @s5_3, i64 0, i64 5), i64 5)
-; CHECK-NEXT:    ret i64 [[LEN]]
+; CHECK-NEXT:    ret i64 0
 ;
   %ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 5
   %len = call i64 @strnlen(i8* %ptr, i64 5)
@@ -160,8 +155,7 @@ define i64 @fold_strnlen_s5_3_p5_5() {
 
 define i64 @fold_strnlen_s5_3_p6_5() {
 ; CHECK-LABEL: @fold_strnlen_s5_3_p6_5(
-; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @s5_3, i64 0, i64 6), i64 5)
-; CHECK-NEXT:    ret i64 [[LEN]]
+; CHECK-NEXT:    ret i64 3
 ;
   %ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 6
   %len = call i64 @strnlen(i8* %ptr, i64 5)

diff  --git a/llvm/test/Transforms/InstCombine/strnlen-3.ll b/llvm/test/Transforms/InstCombine/strnlen-3.ll
index 585a69d1b6db0..877eae813c683 100644
--- a/llvm/test/Transforms/InstCombine/strnlen-3.ll
+++ b/llvm/test/Transforms/InstCombine/strnlen-3.ll
@@ -126,8 +126,8 @@ define i64 @call_strnlen_s5_3_pi_n(i64 zeroext %i, i64 %n) {
 
 define i64 @fold_strnlen_a3_n(i64 %n) {
 ; CHECK-LABEL: @fold_strnlen_a3_n(
-; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @a3, i64 0, i64 0), i64 [[N:%.*]])
-; CHECK-NEXT:    ret i64 [[LEN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.umin.i64(i64 [[N:%.*]], i64 3)
+; CHECK-NEXT:    ret i64 [[TMP1]]
 ;
 
   %ptr = getelementptr [3 x i8], [3 x i8]* @a3, i64 0, i64 0
@@ -140,8 +140,8 @@ define i64 @fold_strnlen_a3_n(i64 %n) {
 
 define i64 @fold_strnlen_s3_n(i64 %n) {
 ; CHECK-LABEL: @fold_strnlen_s3_n(
-; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i64 [[N:%.*]])
-; CHECK-NEXT:    ret i64 [[LEN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.umin.i64(i64 [[N:%.*]], i64 3)
+; CHECK-NEXT:    ret i64 [[TMP1]]
 ;
 
   %ptr = getelementptr [4 x i8], [4 x i8]* @s3, i64 0, i64 0


        


More information about the llvm-commits mailing list