diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h index 9a3af3d66a72a5..7eca16275cbbb9 100644 --- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -163,6 +163,7 @@ class LibCallSimplifier { Value *optimizeStpCpy(CallInst *CI, IRBuilderBase &B); Value *optimizeStrNCpy(CallInst *CI, IRBuilderBase &B); Value *optimizeStrLen(CallInst *CI, IRBuilderBase &B); + Value *optimizeStrNLen(CallInst *CI, IRBuilderBase &B); Value *optimizeStrPBrk(CallInst *CI, IRBuilderBase &B); Value *optimizeStrTo(CallInst *CI, IRBuilderBase &B); Value *optimizeStrSpn(CallInst *CI, IRBuilderBase &B); diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index e130ffbaf41fa2..455632730570dd 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -717,6 +717,13 @@ Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilderBase &B) { return nullptr; } +Value *LibCallSimplifier::optimizeStrNLen(CallInst *CI, IRBuilderBase &B) { + Value *Bound = CI->getArgOperand(1); + if (isKnownNonZero(Bound, DL)) + annotateNonNullNoUndefBasedOnAccess(CI, 0); + return nullptr; +} + Value *LibCallSimplifier::optimizeWcslen(CallInst *CI, IRBuilderBase &B) { Module &M = *CI->getModule(); unsigned WCharSize = TLI->getWCharSize(M) * 8; @@ -2879,6 +2886,8 @@ Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI, return optimizeStrNCpy(CI, Builder); case LibFunc_strlen: return optimizeStrLen(CI, Builder); + case LibFunc_strnlen: + return optimizeStrNLen(CI, Builder); case LibFunc_strpbrk: return optimizeStrPBrk(CI, Builder); case LibFunc_strndup: diff --git a/llvm/test/Transforms/InstCombine/strnlen-1.ll b/llvm/test/Transforms/InstCombine/strnlen-1.ll index 0fb94dba6c0ff4..f8fabbe8fe6155 100644 --- a/llvm/test/Transforms/InstCombine/strnlen-1.ll +++ b/llvm/test/Transforms/InstCombine/strnlen-1.ll @@ -10,6 +10,47 @@ declare i64 @strnlen(i8*, i64) @s5_3 = constant [9 x i8] c"12345\00xyz" +; Verify that the strnlen pointer argument is not annotated nonnull when +; nothing is known about the bound. + +define i64 @no_access_strnlen_p_n(i8* %ptr, i64 %n) { +; CHECK-LABEL: @no_access_strnlen_p_n( +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* [[PTR:%.*]], i64 [[N:%.*]]) +; CHECK-NEXT: ret i64 [[LEN]] +; + %len = call i64 @strnlen(i8* %ptr, i64 %n) + ret i64 %len +} + + +; Verify that the strnlen pointer argument is annotated dereferenceable(1) +; (and not more) when the constant bound is greater than 1. + +define i64 @access_strnlen_p_2(i8* %ptr) { +; CHECK-LABEL: @access_strnlen_p_2( +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[PTR:%.*]], i64 2) +; CHECK-NEXT: ret i64 [[LEN]] +; + %len = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) %ptr, i64 2) + ret i64 %len +} + + +; Verify that the strnlen pointer argument is annotated nonnull etc., +; when the bound is known to be nonzero. + +define i64 @access_strnlen_p_nz(i8* %ptr, i64 %n) { +; CHECK-LABEL: @access_strnlen_p_nz( +; CHECK-NEXT: [[NNZ:%.*]] = or i64 [[N:%.*]], 1 +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[PTR:%.*]], i64 [[NNZ]]) +; CHECK-NEXT: ret i64 [[LEN]] +; + %nnz = or i64 %n, 1 + %len = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) %ptr, i64 %nnz) + ret i64 %len +} + + ; Fold strnlen(s5, 0) to 0. define i64 @fold_strnlen_s5_0() { @@ -27,7 +68,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* getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i64 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]] ; %ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0 @@ -40,7 +81,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* getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i64 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]] ; %ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0 @@ -53,7 +94,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* getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i64 -1) +; 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]] ; %ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0 @@ -66,7 +107,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* getelementptr inbounds ([9 x i8], [9 x i8]* @s5_3, i64 0, i64 4), i64 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]] ; %ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 4 @@ -79,7 +120,7 @@ define i64 @fold_strnlen_s5_3_p4_5() { define i64 @fold_strnlen_s5_3_p5_5() { ; CHECK-LABEL: @fold_strnlen_s5_3_p5_5( -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @s5_3, i64 0, i64 5), i64 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]] ; %ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 5 @@ -92,7 +133,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* getelementptr inbounds ([9 x i8], [9 x i8]* @s5_3, i64 0, i64 6), i64 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]] ; %ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 6 diff --git a/llvm/test/Transforms/InstCombine/strnlen-2.ll b/llvm/test/Transforms/InstCombine/strnlen-2.ll index f46886598e3183..a58ea6b2963692 100644 --- a/llvm/test/Transforms/InstCombine/strnlen-2.ll +++ b/llvm/test/Transforms/InstCombine/strnlen-2.ll @@ -33,7 +33,7 @@ define i64 @fold_strnlen_s3_s5_0(i1 %C) { define i64 @fold_strnlen_s3_s5_1(i1 %C) { ; CHECK-LABEL: @fold_strnlen_s3_s5_1( ; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @s6, i64 0, i64 0) -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* [[PTR]], i64 1) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[PTR]], i64 1) ; CHECK-NEXT: ret i64 [[LEN]] ; %ptr = select i1 %C, i8* getelementptr ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* getelementptr ([7 x i8], [7 x i8]* @s6, i64 0, i64 0) @@ -48,7 +48,7 @@ define i64 @fold_strnlen_s3_s5_1(i1 %C) { define i64 @fold_strnlen_s3_s5_3(i1 %C) { ; CHECK-LABEL: @fold_strnlen_s3_s5_3( ; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @s6, i64 0, i64 0) -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* [[PTR]], i64 3) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[PTR]], i64 3) ; CHECK-NEXT: ret i64 [[LEN]] ; %ptr = select i1 %C, i8* getelementptr ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* getelementptr ([7 x i8], [7 x i8]* @s6, i64 0, i64 0) @@ -63,7 +63,7 @@ define i64 @fold_strnlen_s3_s5_3(i1 %C) { define i64 @fold_strnlen_s3_s5_4(i1 %C) { ; CHECK-LABEL: @fold_strnlen_s3_s5_4( ; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @s6, i64 0, i64 0) -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* [[PTR]], i64 4) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[PTR]], i64 4) ; CHECK-NEXT: ret i64 [[LEN]] ; %ptr = select i1 %C, i8* getelementptr ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* getelementptr ([7 x i8], [7 x i8]* @s6, i64 0, i64 0) @@ -78,7 +78,7 @@ define i64 @fold_strnlen_s3_s5_4(i1 %C) { define i64 @fold_strnlen_s3_s5_5(i1 %C) { ; CHECK-LABEL: @fold_strnlen_s3_s5_5( ; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @s6, i64 0, i64 0) -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* [[PTR]], i64 5) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[PTR]], i64 5) ; CHECK-NEXT: ret i64 [[LEN]] ; %ptr = select i1 %C, i8* getelementptr ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* getelementptr ([7 x i8], [7 x i8]* @s6, i64 0, i64 0) @@ -93,7 +93,7 @@ define i64 @fold_strnlen_s3_s5_5(i1 %C) { define i64 @fold_strnlen_s5_6(i1 %C) { ; CHECK-LABEL: @fold_strnlen_s5_6( ; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], i8* getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @s6, i64 0, i64 0) -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* [[PTR]], i64 6) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[PTR]], i64 6) ; CHECK-NEXT: ret i64 [[LEN]] ; @@ -113,7 +113,7 @@ define i64 @fold_strnlen_s3_s5_s7_4(i32 %X) { ; CHECK-NEXT: [[X_EQ_5:%.*]] = icmp eq i32 [[X]], 5 ; CHECK-NEXT: [[SEL_X_EQ_5:%.*]] = select i1 [[X_EQ_5]], i8* getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @s7, i64 0, i64 0) ; CHECK-NEXT: [[SEL_X_EQ_3:%.*]] = select i1 [[X_EQ_3]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* [[SEL_X_EQ_5]] -; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* [[SEL_X_EQ_3]], i64 4) +; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[SEL_X_EQ_3]], i64 4) ; CHECK-NEXT: ret i64 [[LEN]] ; @@ -136,7 +136,7 @@ define i64 @fold_strnlen_s3_s5_s7_6(i32 %X) { ; CHECK-NEXT: [[X_EQ_5:%.*]] = icmp eq i32 [[X]], 5 ; CHECK-NEXT: [[SEL_X_EQ_5:%.*]] = select i1 [[X_EQ_5]], i8* getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @s7, i64 0, i64 0) ; CHECK-NEXT: [[SEL_X_EQ_3:%.*]] = select i1 [[X_EQ_3]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* [[SEL_X_EQ_5]] -; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* [[SEL_X_EQ_3]], i64 6) +; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[SEL_X_EQ_3]], i64 6) ; CHECK-NEXT: ret i64 [[LEN]] ; @@ -159,7 +159,7 @@ define i64 @fold_strnlen_s3_s5_s7_8(i32 %X) { ; CHECK-NEXT: [[X_EQ_5:%.*]] = icmp eq i32 [[X]], 5 ; CHECK-NEXT: [[SEL_X_EQ_5:%.*]] = select i1 [[X_EQ_5]], i8* getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @s7, i64 0, i64 0) ; CHECK-NEXT: [[SEL_X_EQ_3:%.*]] = select i1 [[X_EQ_3]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i8* [[SEL_X_EQ_5]] -; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* [[SEL_X_EQ_3]], i64 8) +; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[SEL_X_EQ_3]], i64 8) ; CHECK-NEXT: ret i64 [[LEN]] ; diff --git a/llvm/test/Transforms/InstCombine/strnlen-3.ll b/llvm/test/Transforms/InstCombine/strnlen-3.ll index 9128d49b0cece8..9d1004a1b0800a 100644 --- a/llvm/test/Transforms/InstCombine/strnlen-3.ll +++ b/llvm/test/Transforms/InstCombine/strnlen-3.ll @@ -49,7 +49,7 @@ define i64 @call_strnlen_sx_pi_n(i64 %i, i64 %n) { define i64 @call_strnlen_a3_pi_2(i64 %i) { ; CHECK-LABEL: @call_strnlen_a3_pi_2( ; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [3 x i8], [3 x i8]* @a3, i64 0, i64 [[I:%.*]] -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* nonnull [[PTR]], i64 2) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull [[PTR]], i64 2) ; CHECK-NEXT: ret i64 [[LEN]] ; @@ -64,7 +64,7 @@ define i64 @call_strnlen_a3_pi_2(i64 %i) { define i64 @call_strnlen_a3_pi_3(i64 %i) { ; CHECK-LABEL: @call_strnlen_a3_pi_3( ; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [3 x i8], [3 x i8]* @a3, i64 0, i64 [[I:%.*]] -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* nonnull [[PTR]], i64 3) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull [[PTR]], i64 3) ; CHECK-NEXT: ret i64 [[LEN]] ; @@ -162,7 +162,7 @@ define i64 @fold_strnlen_s3_n(i64 %n) { define i64 @fold_strnlen_a3_pi_2(i64 %i) { ; CHECK-LABEL: @fold_strnlen_a3_pi_2( ; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [3 x i8], [3 x i8]* @a3, i64 0, i64 [[I:%.*]] -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* nonnull [[PTR]], i64 2) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull [[PTR]], i64 2) ; CHECK-NEXT: ret i64 [[LEN]] ; @@ -177,7 +177,7 @@ define i64 @fold_strnlen_a3_pi_2(i64 %i) { define i64 @fold_strnlen_s3_pi_2(i64 %i) { ; CHECK-LABEL: @fold_strnlen_s3_pi_2( ; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* @s3, i64 0, i64 [[I:%.*]] -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* nonnull [[PTR]], i64 2) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull [[PTR]], i64 2) ; CHECK-NEXT: ret i64 [[LEN]] ; @@ -192,7 +192,7 @@ define i64 @fold_strnlen_s3_pi_2(i64 %i) { define i64 @fold_strnlen_s3_pi_3(i64 %i) { ; CHECK-LABEL: @fold_strnlen_s3_pi_3( ; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* @s3, i64 0, i64 [[I:%.*]] -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* nonnull [[PTR]], i64 3) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull [[PTR]], i64 3) ; CHECK-NEXT: ret i64 [[LEN]] ; @@ -223,7 +223,7 @@ define i64 @fold_strnlen_s3_pi_n(i64 %i, i64 %n) { define i64 @call_strnlen_s5_3_pi_2(i64 %i) { ; CHECK-LABEL: @call_strnlen_s5_3_pi_2( ; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [10 x i8], [10 x i8]* @s5_3, i64 0, i64 [[I:%.*]] -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* nonnull [[PTR]], i64 2) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull [[PTR]], i64 2) ; CHECK-NEXT: ret i64 [[LEN]] ; diff --git a/llvm/test/Transforms/InstCombine/strnlen-5.ll b/llvm/test/Transforms/InstCombine/strnlen-5.ll index 46f9e8a7223e34..125ffda2458927 100644 --- a/llvm/test/Transforms/InstCombine/strnlen-5.ll +++ b/llvm/test/Transforms/InstCombine/strnlen-5.ll @@ -47,7 +47,7 @@ define i1 @fold_strnlen_ax_0_gtz() { define i1 @fold_strnlen_ax_1_eqz() { ; CHECK-LABEL: @fold_strnlen_ax_1_eqz( -; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 1) +; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 1) ; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0 ; CHECK-NEXT: ret i1 [[EQZ]] ; @@ -63,7 +63,7 @@ define i1 @fold_strnlen_ax_1_eqz() { define i1 @fold_strnlen_ax_1_neqz() { ; CHECK-LABEL: @fold_strnlen_ax_1_neqz( -; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 1) +; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 1) ; CHECK-NEXT: [[NEZ:%.*]] = icmp ne i64 [[LEN]], 0 ; CHECK-NEXT: ret i1 [[NEZ]] ; @@ -79,7 +79,7 @@ define i1 @fold_strnlen_ax_1_neqz() { define i1 @fold_strnlen_ax_9_eqz() { ; CHECK-LABEL: @fold_strnlen_ax_9_eqz( -; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 9) +; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 9) ; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0 ; CHECK-NEXT: ret i1 [[EQZ]] ; @@ -112,7 +112,7 @@ define i1 @call_strnlen_ax_n_eqz(i64 %n) { define i1 @fold_strnlen_ax_nz_eqz(i64 %n) { ; CHECK-LABEL: @fold_strnlen_ax_nz_eqz( ; CHECK-NEXT: [[MAX:%.*]] = or i64 [[N:%.*]], 1 -; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 [[MAX]]) +; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 [[MAX]]) ; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0 ; CHECK-NEXT: ret i1 [[EQZ]] ; @@ -130,7 +130,7 @@ define i1 @fold_strnlen_ax_nz_eqz(i64 %n) { define i1 @fold_strnlen_ax_nz_gtz(i64 %n) { ; CHECK-LABEL: @fold_strnlen_ax_nz_gtz( ; CHECK-NEXT: [[MAX:%.*]] = or i64 [[N:%.*]], 1 -; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 [[MAX]]) +; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 [[MAX]]) ; CHECK-NEXT: [[GTZ:%.*]] = icmp ne i64 [[LEN]], 0 ; CHECK-NEXT: ret i1 [[GTZ]] ; @@ -150,7 +150,7 @@ define i1 @fold_strnlen_a5_pi_nz_eqz(i64 %i, i64 %n) { ; CHECK-LABEL: @fold_strnlen_a5_pi_nz_eqz( ; CHECK-NEXT: [[NZ:%.*]] = or i64 [[N:%.*]], 1 ; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [5 x i8], [5 x i8]* @a5, i64 0, i64 [[I:%.*]] -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* nonnull [[PTR]], i64 [[NZ]]) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull [[PTR]], i64 [[NZ]]) ; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0 ; CHECK-NEXT: ret i1 [[EQZ]] ; @@ -171,7 +171,7 @@ define i1 @fold_strnlen_s5_pi_nz_eqz(i64 %i, i64 %n) { ; CHECK-LABEL: @fold_strnlen_s5_pi_nz_eqz( ; CHECK-NEXT: [[NZ:%.*]] = or i64 [[N:%.*]], 1 ; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [6 x i8], [6 x i8]* @s5, i64 0, i64 [[I:%.*]] -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* nonnull [[PTR]], i64 [[NZ]]) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull [[PTR]], i64 [[NZ]]) ; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0 ; CHECK-NEXT: ret i1 [[EQZ]] ; diff --git a/llvm/test/Transforms/InstCombine/strnlen-6.ll b/llvm/test/Transforms/InstCombine/strnlen-6.ll index 91c85825ba4ca6..64d94e401d3e6c 100644 --- a/llvm/test/Transforms/InstCombine/strnlen-6.ll +++ b/llvm/test/Transforms/InstCombine/strnlen-6.ll @@ -16,7 +16,7 @@ declare i64 @strnlen(i8*, i64) define i64 @deref_strnlen_ecp_3() { ; CHECK-LABEL: @deref_strnlen_ecp_3( ; CHECK-NEXT: [[PTR:%.*]] = load i8*, i8** @ecp, align 8 -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* [[PTR]], i64 3) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[PTR]], i64 3) ; CHECK-NEXT: ret i64 [[LEN]] ; %ptr = load i8*, i8** @ecp @@ -32,7 +32,7 @@ define i64 @deref_strnlen_ecp_nz(i64 %n) { ; CHECK-LABEL: @deref_strnlen_ecp_nz( ; CHECK-NEXT: [[NONZERO:%.*]] = or i64 [[N:%.*]], 1 ; CHECK-NEXT: [[PTR:%.*]] = load i8*, i8** @ecp, align 8 -; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* [[PTR]], i64 [[NONZERO]]) +; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) [[PTR]], i64 [[NONZERO]]) ; CHECK-NEXT: ret i64 [[LEN]] ; %nonzero = or i64 %n, 1