; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Verify that strnlen calls with constant string arguments and offsets ; and constant bounds are folded correctly. ; ; RUN: opt < %s -passes=instcombine -S | FileCheck %s declare i64 @strnlen(i8*, i64) @ax = external global [0 x i8] @s5 = constant [6 x i8] c"12345\00" @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(ax, 0) to 0. define i64 @fold_strnlen_ax_0() { ; CHECK-LABEL: @fold_strnlen_ax_0( ; CHECK-NEXT: ret i64 0 ; %ptr = getelementptr [0 x i8], [0 x i8]* @ax, i32 0, i32 0 %len = call i64 @strnlen(i8* %ptr, i64 0) ret i64 %len } ; Fold strnlen(ax, 1) to *ax ? 1 : 0. define i64 @fold_strnlen_ax_1() { ; CHECK-LABEL: @fold_strnlen_ax_1( ; CHECK-NEXT: [[STRNLEN_CHAR0:%.*]] = load i8, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), align 1 ; CHECK-NEXT: [[STRNLEN_CHAR0CMP:%.*]] = icmp ne i8 [[STRNLEN_CHAR0]], 0 ; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[STRNLEN_CHAR0CMP]] to i64 ; CHECK-NEXT: ret i64 [[TMP1]] ; %ptr = getelementptr [0 x i8], [0 x i8]* @ax, i32 0, i32 0 %len = call i64 @strnlen(i8* %ptr, i64 1) ret i64 %len } ; Fold strnlen(s5, 0) to 0. define i64 @fold_strnlen_s5_0() { ; CHECK-LABEL: @fold_strnlen_s5_0( ; CHECK-NEXT: ret i64 0 ; %ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0 %len = call i64 @strnlen(i8* %ptr, i64 0) ret i64 %len } ; Fold strnlen(s5, 4) to 4. define i64 @fold_strnlen_s5_4() { ; CHECK-LABEL: @fold_strnlen_s5_4( ; 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) ret i64 %len } ; Fold strnlen(s5, 5) to 5. define i64 @fold_strnlen_s5_5() { ; CHECK-LABEL: @fold_strnlen_s5_5( ; 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) ret i64 %len } ; Fold strnlen(s5, (size_t)-1) to 5. define i64 @fold_strnlen_s5_m1() { ; CHECK-LABEL: @fold_strnlen_s5_m1( ; 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) ret i64 %len } ; Fold strnlen(s5_3 + 4, 5) to 1. define i64 @fold_strnlen_s5_3_p4_5() { ; CHECK-LABEL: @fold_strnlen_s5_3_p4_5( ; 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) ret i64 %len } ; 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: 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) ret i64 %len } ; Fold strnlen(s5_3 + 6, 3) to 3. define i64 @fold_strnlen_s5_3_p6_3() { ; CHECK-LABEL: @fold_strnlen_s5_3_p6_3( ; 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 3) ret i64 %len } ; Fold even the invalid strnlen(s5_3 + 6, 4) call where the bound exceeds ; the number of characters in the array. This is arguably safer than ; making the library call (although the low bound makes it unlikely that ; the call would misbehave). define i64 @call_strnlen_s5_3_p6_4() { ; CHECK-LABEL: @call_strnlen_s5_3_p6_4( ; 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 4) ret i64 %len }