1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Verify that equality tests of strnlen calls against zero are folded 3; 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@a5 = external global [5 x i8] 11@s5 = constant [6 x i8] c"12345\00" 12 13 14; Fold strnlen(ax, 0) == 0 to true. 15 16define i1 @fold_strnlen_ax_0_eqz() { 17; CHECK-LABEL: @fold_strnlen_ax_0_eqz( 18; CHECK-NEXT: ret i1 true 19; 20 21 %len = tail call i64 @strnlen(ptr @ax, i64 0) 22 %eqz = icmp eq i64 %len, 0 23 ret i1 %eqz 24} 25 26 27; Fold strnlen(ax, 0) > 0 to false. 28 29define i1 @fold_strnlen_ax_0_gtz() { 30; CHECK-LABEL: @fold_strnlen_ax_0_gtz( 31; CHECK-NEXT: ret i1 false 32; 33 34 %len = tail call i64 @strnlen(ptr @ax, i64 0) 35 %gtz = icmp ugt i64 %len, 0 36 ret i1 %gtz 37} 38 39 40; Fold strnlen(ax, 1) == 0 to *ax == 0. 41 42define i1 @fold_strnlen_ax_1_eqz() { 43; CHECK-LABEL: @fold_strnlen_ax_1_eqz( 44; CHECK-NEXT: [[CHAR0:%.*]] = load i8, ptr @ax, align 1 45; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0 46; CHECK-NEXT: ret i1 [[EQZ]] 47; 48 49 %len = tail call i64 @strnlen(ptr @ax, i64 1) 50 %eqz = icmp eq i64 %len, 0 51 ret i1 %eqz 52} 53 54 55; Likewise, fold strnlen(ax, 1) < 1 to *ax == 0. 56 57define i1 @fold_strnlen_ax_1_lt1() { 58; CHECK-LABEL: @fold_strnlen_ax_1_lt1( 59; CHECK-NEXT: [[STRNLEN_CHAR0:%.*]] = load i8, ptr @ax, align 1 60; CHECK-NEXT: [[STRNLEN_CHAR0CMP_NOT:%.*]] = icmp eq i8 [[STRNLEN_CHAR0]], 0 61; CHECK-NEXT: ret i1 [[STRNLEN_CHAR0CMP_NOT]] 62; 63 64 %len = tail call i64 @strnlen(ptr @ax, i64 1) 65 %nez = icmp ult i64 %len, 1 66 ret i1 %nez 67} 68 69 70; Fold strnlen(ax, 1) != 0 to *ax != 0. 71 72define i1 @fold_strnlen_ax_1_neqz() { 73; CHECK-LABEL: @fold_strnlen_ax_1_neqz( 74; CHECK-NEXT: [[CHAR0:%.*]] = load i8, ptr @ax, align 1 75; CHECK-NEXT: [[NEZ:%.*]] = icmp ne i8 [[CHAR0]], 0 76; CHECK-NEXT: ret i1 [[NEZ]] 77; 78 79 %len = tail call i64 @strnlen(ptr @ax, i64 1) 80 %nez = icmp ne i64 %len, 0 81 ret i1 %nez 82} 83 84 85; Likewise, fold strnlen(ax, 1) > 0 to *ax != 0. 86 87define i1 @fold_strnlen_ax_1_gtz() { 88; CHECK-LABEL: @fold_strnlen_ax_1_gtz( 89; CHECK-NEXT: [[STRNLEN_CHAR0:%.*]] = load i8, ptr @ax, align 1 90; CHECK-NEXT: [[STRNLEN_CHAR0CMP:%.*]] = icmp ne i8 [[STRNLEN_CHAR0]], 0 91; CHECK-NEXT: ret i1 [[STRNLEN_CHAR0CMP]] 92; 93 94 %len = tail call i64 @strnlen(ptr @ax, i64 1) 95 %nez = icmp ugt i64 %len, 0 96 ret i1 %nez 97} 98 99 100; Fold strnlen(ax, 9) == 0 to *ax == 0. 101 102define i1 @fold_strnlen_ax_9_eqz() { 103; CHECK-LABEL: @fold_strnlen_ax_9_eqz( 104; CHECK-NEXT: [[CHAR0:%.*]] = load i8, ptr @ax, align 1 105; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0 106; CHECK-NEXT: ret i1 [[EQZ]] 107; 108 109 %len = tail call i64 @strnlen(ptr @ax, i64 9) 110 %eqz = icmp eq i64 %len, 0 111 ret i1 %eqz 112} 113 114 115; Do not fold strnlen(ax, n) == 0 for n that might be zero. 116 117define i1 @call_strnlen_ax_n_eqz(i64 %n) { 118; CHECK-LABEL: @call_strnlen_ax_n_eqz( 119; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(ptr nonnull @ax, i64 [[N:%.*]]) 120; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0 121; CHECK-NEXT: ret i1 [[EQZ]] 122; 123 124 %len = tail call i64 @strnlen(ptr @ax, i64 %n) 125 %eqz = icmp eq i64 %len, 0 126 ret i1 %eqz 127} 128 129 130; Fold strnlen(ax, n) == 0 to *ax == 0 for %0 that's not zero. 131 132define i1 @fold_strnlen_ax_nz_eqz(i64 %n) { 133; CHECK-LABEL: @fold_strnlen_ax_nz_eqz( 134; CHECK-NEXT: [[CHAR0:%.*]] = load i8, ptr @ax, align 1 135; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0 136; CHECK-NEXT: ret i1 [[EQZ]] 137; 138 139 %max = or i64 %n, 1 140 %len = tail call i64 @strnlen(ptr @ax, i64 %max) 141 %eqz = icmp eq i64 %len, 0 142 ret i1 %eqz 143} 144 145 146; Fold strnlen(ax, n) > 0 to *ax != 0 for n that's not zero. 147 148define i1 @fold_strnlen_ax_nz_gtz(i64 %n) { 149; CHECK-LABEL: @fold_strnlen_ax_nz_gtz( 150; CHECK-NEXT: [[CHAR0:%.*]] = load i8, ptr @ax, align 1 151; CHECK-NEXT: [[GTZ:%.*]] = icmp ne i8 [[CHAR0]], 0 152; CHECK-NEXT: ret i1 [[GTZ]] 153; 154 155 %max = or i64 %n, 1 156 %len = tail call i64 @strnlen(ptr @ax, i64 %max) 157 %gtz = icmp ugt i64 %len, 0 158 ret i1 %gtz 159} 160 161 162; Fold strnlen(a5 + i, n) == 0 to a5[i] == 0 for a nonconstant a5 163; and a nonzero n. 164 165define i1 @fold_strnlen_a5_pi_nz_eqz(i64 %i, i64 %n) { 166; CHECK-LABEL: @fold_strnlen_a5_pi_nz_eqz( 167; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [5 x i8], ptr @a5, i64 0, i64 [[I:%.*]] 168; CHECK-NEXT: [[CHAR0:%.*]] = load i8, ptr [[PTR]], align 1 169; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0 170; CHECK-NEXT: ret i1 [[EQZ]] 171; 172 173 %nz = or i64 %n, 1 174 %ptr = getelementptr inbounds [5 x i8], ptr @a5, i64 0, i64 %i 175 %len = call i64 @strnlen(ptr %ptr, i64 %nz) 176 %eqz = icmp eq i64 %len, 0 177 ret i1 %eqz 178} 179 180 181; Fold strnlen(s5 + i, n) == 0 for a constant s5 and nonzero n. 182; This is first folded to s5[i] == 0 like the above and then finally 183; to %0 == 5. 184 185define i1 @fold_strnlen_s5_pi_nz_eqz(i64 %i, i64 %n) { 186; CHECK-LABEL: @fold_strnlen_s5_pi_nz_eqz( 187; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[I:%.*]], 5 188; CHECK-NEXT: ret i1 [[EQZ]] 189; 190 191 %nz = or i64 %n, 1 192 %ptr = getelementptr inbounds [6 x i8], ptr @s5, i64 0, i64 %i 193 %len = call i64 @strnlen(ptr %ptr, i64 %nz) 194 %eqz = icmp eq i64 %len, 0 195 ret i1 %eqz 196} 197 198 199; Do not fold strnlen(s5 + i, n) for a constant s5 when n might be zero. 200 201define i1 @call_strnlen_s5_pi_n_eqz(i64 %i, i64 %n) { 202; CHECK-LABEL: @call_strnlen_s5_pi_n_eqz( 203; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [6 x i8], ptr @s5, i64 0, i64 [[I:%.*]] 204; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(ptr nonnull [[PTR]], i64 [[N:%.*]]) 205; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0 206; CHECK-NEXT: ret i1 [[EQZ]] 207; 208 209 %ptr = getelementptr inbounds [6 x i8], ptr @s5, i64 0, i64 %i 210 %len = call i64 @strnlen(ptr %ptr, i64 %n) 211 %eqz = icmp eq i64 %len, 0 212 ret i1 %eqz 213} 214