1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Verify that strnlen calls with constant string arguments and offsets 3; and constant bounds are folded correctly. 4; 5; RUN: opt < %s -passes=instcombine -S | FileCheck %s 6 7declare i64 @strnlen(ptr, i64) 8 9@ax = external global [0 x i8] 10@s5 = constant [6 x i8] c"12345\00" 11@s5_3 = constant [9 x i8] c"12345\00xyz" 12 13 14; Verify that the strnlen pointer argument is not annotated nonnull when 15; nothing is known about the bound. 16 17define i64 @no_access_strnlen_p_n(ptr %ptr, i64 %n) { 18; CHECK-LABEL: @no_access_strnlen_p_n( 19; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(ptr [[PTR:%.*]], i64 [[N:%.*]]) 20; CHECK-NEXT: ret i64 [[LEN]] 21; 22 %len = call i64 @strnlen(ptr %ptr, i64 %n) 23 ret i64 %len 24} 25 26 27; Verify that the strnlen pointer argument is annotated dereferenceable(1) 28; (and not more) when the constant bound is greater than 1. 29 30define i64 @access_strnlen_p_2(ptr %ptr) { 31; CHECK-LABEL: @access_strnlen_p_2( 32; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR:%.*]], i64 2) 33; CHECK-NEXT: ret i64 [[LEN]] 34; 35 %len = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) %ptr, i64 2) 36 ret i64 %len 37} 38 39 40; Verify that the strnlen pointer argument is annotated nonnull etc., 41; when the bound is known to be nonzero. 42 43define i64 @access_strnlen_p_nz(ptr %ptr, i64 %n) { 44; CHECK-LABEL: @access_strnlen_p_nz( 45; CHECK-NEXT: [[NNZ:%.*]] = or i64 [[N:%.*]], 1 46; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR:%.*]], i64 [[NNZ]]) 47; CHECK-NEXT: ret i64 [[LEN]] 48; 49 %nnz = or i64 %n, 1 50 %len = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) %ptr, i64 %nnz) 51 ret i64 %len 52} 53 54 55; Fold strnlen(ax, 0) to 0. 56 57define i64 @fold_strnlen_ax_0() { 58; CHECK-LABEL: @fold_strnlen_ax_0( 59; CHECK-NEXT: ret i64 0 60; 61 %len = call i64 @strnlen(ptr @ax, i64 0) 62 ret i64 %len 63} 64 65 66; Fold strnlen(ax, 1) to *ax ? 1 : 0. 67 68define i64 @fold_strnlen_ax_1() { 69; CHECK-LABEL: @fold_strnlen_ax_1( 70; CHECK-NEXT: [[STRNLEN_CHAR0:%.*]] = load i8, ptr @ax, align 1 71; CHECK-NEXT: [[STRNLEN_CHAR0CMP:%.*]] = icmp ne i8 [[STRNLEN_CHAR0]], 0 72; CHECK-NEXT: [[LEN:%.*]] = zext i1 [[STRNLEN_CHAR0CMP]] to i64 73; CHECK-NEXT: ret i64 [[LEN]] 74; 75 %len = call i64 @strnlen(ptr @ax, i64 1) 76 ret i64 %len 77} 78 79 80; Fold strnlen(s5, 0) to 0. 81 82define i64 @fold_strnlen_s5_0() { 83; CHECK-LABEL: @fold_strnlen_s5_0( 84; CHECK-NEXT: ret i64 0 85; 86 %len = call i64 @strnlen(ptr @s5, i64 0) 87 ret i64 %len 88} 89 90 91; Fold strnlen(s5, 4) to 4. 92 93define i64 @fold_strnlen_s5_4() { 94; CHECK-LABEL: @fold_strnlen_s5_4( 95; CHECK-NEXT: ret i64 4 96; 97 %len = call i64 @strnlen(ptr @s5, i64 4) 98 ret i64 %len 99} 100 101 102; Fold strnlen(s5, 5) to 5. 103 104define i64 @fold_strnlen_s5_5() { 105; CHECK-LABEL: @fold_strnlen_s5_5( 106; CHECK-NEXT: ret i64 5 107; 108 %len = call i64 @strnlen(ptr @s5, i64 5) 109 ret i64 %len 110} 111 112 113; Fold strnlen(s5, (size_t)-1) to 5. 114 115define i64 @fold_strnlen_s5_m1() { 116; CHECK-LABEL: @fold_strnlen_s5_m1( 117; CHECK-NEXT: ret i64 5 118; 119 %len = call i64 @strnlen(ptr @s5, i64 -1) 120 ret i64 %len 121} 122 123 124; Fold strnlen(s5_3 + 4, 5) to 1. 125 126define i64 @fold_strnlen_s5_3_p4_5() { 127; CHECK-LABEL: @fold_strnlen_s5_3_p4_5( 128; CHECK-NEXT: ret i64 1 129; 130 %ptr = getelementptr [9 x i8], ptr @s5_3, i32 0, i32 4 131 %len = call i64 @strnlen(ptr %ptr, i64 5) 132 ret i64 %len 133} 134 135 136; Fold strnlen(s5_3 + 5, 5) to 0. 137 138define i64 @fold_strnlen_s5_3_p5_5() { 139; CHECK-LABEL: @fold_strnlen_s5_3_p5_5( 140; CHECK-NEXT: ret i64 0 141; 142 %ptr = getelementptr [9 x i8], ptr @s5_3, i32 0, i32 5 143 %len = call i64 @strnlen(ptr %ptr, i64 5) 144 ret i64 %len 145} 146 147 148; Fold strnlen(s5_3 + 6, 3) to 3. 149 150define i64 @fold_strnlen_s5_3_p6_3() { 151; CHECK-LABEL: @fold_strnlen_s5_3_p6_3( 152; CHECK-NEXT: ret i64 3 153; 154 %ptr = getelementptr [9 x i8], ptr @s5_3, i32 0, i32 6 155 %len = call i64 @strnlen(ptr %ptr, i64 3) 156 ret i64 %len 157} 158 159 160; Fold even the invalid strnlen(s5_3 + 6, 4) call where the bound exceeds 161; the number of characters in the array. This is arguably safer than 162; making the library call (although the low bound makes it unlikely that 163; the call would misbehave). 164 165define i64 @call_strnlen_s5_3_p6_4() { 166; CHECK-LABEL: @call_strnlen_s5_3_p6_4( 167; CHECK-NEXT: ret i64 3 168; 169 %ptr = getelementptr [9 x i8], ptr @s5_3, i32 0, i32 6 170 %len = call i64 @strnlen(ptr %ptr, i64 4) 171 ret i64 %len 172} 173