1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3; 4; Exercise folding of strncmp calls with constant arrays and nonconstant 5; sizes. 6 7declare i32 @strncmp(ptr, ptr, i64) 8 9@ax = external constant [8 x i8] 10@a01230123 = constant [8 x i8] c"01230123" 11@b01230123 = constant [8 x i8] c"01230123" 12@c01230129 = constant [8 x i8] c"01230129" 13@d9123_12 = constant [7 x i8] c"9123\0012" 14@e9123_34 = constant [7 x i8] c"9123\0034" 15 16 17; Exercise strncmp(A, B, N) folding of arrays with the same bytes. 18 19define void @fold_strncmp_a_b_n(ptr %pcmp, i64 %n) { 20; CHECK-LABEL: @fold_strncmp_a_b_n( 21; CHECK-NEXT: store i32 0, ptr [[PCMP:%.*]], align 4 22; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[N:%.*]], 0 23; CHECK-NEXT: [[C0_1:%.*]] = sext i1 [[TMP1]] to i32 24; CHECK-NEXT: [[S0_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4 25; CHECK-NEXT: store i32 [[C0_1]], ptr [[S0_1]], align 4 26; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[N]], 0 27; CHECK-NEXT: [[C0_2:%.*]] = sext i1 [[TMP2]] to i32 28; CHECK-NEXT: [[S0_2:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8 29; CHECK-NEXT: store i32 [[C0_2]], ptr [[S0_2]], align 4 30; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[N]], 0 31; CHECK-NEXT: [[C0_3:%.*]] = sext i1 [[TMP3]] to i32 32; CHECK-NEXT: [[S0_3:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12 33; CHECK-NEXT: store i32 [[C0_3]], ptr [[S0_3]], align 4 34; CHECK-NEXT: [[S0_4:%.*]] = getelementptr i8, ptr [[PCMP]], i64 16 35; CHECK-NEXT: store i32 0, ptr [[S0_4]], align 4 36; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[N]], 0 37; CHECK-NEXT: [[C0_5:%.*]] = sext i1 [[TMP4]] to i32 38; CHECK-NEXT: [[S0_5:%.*]] = getelementptr i8, ptr [[PCMP]], i64 20 39; CHECK-NEXT: store i32 [[C0_5]], ptr [[S0_5]], align 4 40; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i64 [[N]], 0 41; CHECK-NEXT: [[C5_0:%.*]] = zext i1 [[TMP5]] to i32 42; CHECK-NEXT: [[S5_0:%.*]] = getelementptr i8, ptr [[PCMP]], i64 24 43; CHECK-NEXT: store i32 [[C5_0]], ptr [[S5_0]], align 4 44; CHECK-NEXT: ret void 45; 46 47 48 %q1 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 1 49 %q2 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 2 50 %q3 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 3 51 %q4 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 4 52 %q5 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 5 53 54 ; Fold strncmp(a, b, n) to 0. 55 %c0_0 = call i32 @strncmp(ptr @a01230123, ptr @b01230123, i64 %n) 56 store i32 %c0_0, ptr %pcmp 57 58 ; Fold strncmp(a, b + 1, n) to N != 0 ? -1 : 0. 59 %c0_1 = call i32 @strncmp(ptr @a01230123, ptr %q1, i64 %n) 60 %s0_1 = getelementptr i32, ptr %pcmp, i64 1 61 store i32 %c0_1, ptr %s0_1 62 63 ; Fold strncmp(a, b + 2, n) to N != 0 ? -1 : 0. 64 %c0_2 = call i32 @strncmp(ptr @a01230123, ptr %q2, i64 %n) 65 %s0_2 = getelementptr i32, ptr %pcmp, i64 2 66 store i32 %c0_2, ptr %s0_2 67 68 ; Fold strncmp(a, b + 3, n) to N != 0 ? -1 : 0. 69 %c0_3 = call i32 @strncmp(ptr @a01230123, ptr %q3, i64 %n) 70 %s0_3 = getelementptr i32, ptr %pcmp, i64 3 71 store i32 %c0_3, ptr %s0_3 72 73 ; Fold strncmp(a, b + 4, n) to 0. 74 %c0_4 = call i32 @strncmp(ptr @a01230123, ptr %q4, i64 %n) 75 %s0_4 = getelementptr i32, ptr %pcmp, i64 4 76 store i32 %c0_4, ptr %s0_4 77 78 ; Fold strncmp(a, b + 5, n) to N != 0 ? -1 : 0. 79 %c0_5 = call i32 @strncmp(ptr @a01230123, ptr %q5, i64 %n) 80 %s0_5 = getelementptr i32, ptr %pcmp, i64 5 81 store i32 %c0_5, ptr %s0_5 82 83 ; Fold strncmp(b + 5, a, n) to N != 0 ? +1 : 0. 84 %c5_0 = call i32 @strncmp(ptr %q5, ptr @a01230123, i64 %n) 85 %s5_0 = getelementptr i32, ptr %pcmp, i64 6 86 store i32 %c5_0, ptr %s5_0 87 88 ret void 89} 90 91; Vefify that a strncmp() call involving a constant array with unknown 92; contents is not folded. 93 94define void @call_strncmp_a_ax_n(ptr %pcmp, i64 %n) { 95; CHECK-LABEL: @call_strncmp_a_ax_n( 96; CHECK-NEXT: [[C0_0:%.*]] = call i32 @strncmp(ptr nonnull @a01230123, ptr nonnull @ax, i64 [[N:%.*]]) 97; CHECK-NEXT: store i32 [[C0_0]], ptr [[PCMP:%.*]], align 4 98; CHECK-NEXT: ret void 99; 100 101 102 ; Do not fold strncmp(a, ax, n). 103 %c0_0 = call i32 @strncmp(ptr @a01230123, ptr @ax, i64 %n) 104 store i32 %c0_0, ptr %pcmp 105 106 ret void 107} 108 109 110; Exercise strncmp(A, C, N) folding of arrays with the same leading bytes 111; but a difference in the trailing byte. 112 113define void @fold_strncmp_a_c_n(ptr %pcmp, i64 %n) { 114; CHECK-LABEL: @fold_strncmp_a_c_n( 115; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i64 [[N:%.*]], 7 116; CHECK-NEXT: [[C0_0:%.*]] = sext i1 [[TMP1]] to i32 117; CHECK-NEXT: store i32 [[C0_0]], ptr [[PCMP:%.*]], align 4 118; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[N]], 0 119; CHECK-NEXT: [[C0_1:%.*]] = sext i1 [[TMP2]] to i32 120; CHECK-NEXT: [[S0_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4 121; CHECK-NEXT: store i32 [[C0_1]], ptr [[S0_1]], align 4 122; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[N]], 0 123; CHECK-NEXT: [[C0_2:%.*]] = sext i1 [[TMP3]] to i32 124; CHECK-NEXT: [[S0_2:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8 125; CHECK-NEXT: store i32 [[C0_2]], ptr [[S0_2]], align 4 126; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[N]], 0 127; CHECK-NEXT: [[C0_3:%.*]] = sext i1 [[TMP4]] to i32 128; CHECK-NEXT: [[S0_3:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12 129; CHECK-NEXT: store i32 [[C0_3]], ptr [[S0_3]], align 4 130; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[N]], 3 131; CHECK-NEXT: [[C0_4:%.*]] = sext i1 [[TMP5]] to i32 132; CHECK-NEXT: [[S0_4:%.*]] = getelementptr i8, ptr [[PCMP]], i64 16 133; CHECK-NEXT: store i32 [[C0_4]], ptr [[S0_4]], align 4 134; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i64 [[N]], 3 135; CHECK-NEXT: [[C0_5:%.*]] = sext i1 [[TMP6]] to i32 136; CHECK-NEXT: [[S0_5:%.*]] = getelementptr i8, ptr [[PCMP]], i64 20 137; CHECK-NEXT: store i32 [[C0_5]], ptr [[S0_5]], align 4 138; CHECK-NEXT: ret void 139; 140 141 142 %q1 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 1 143 %q2 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 2 144 %q3 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 3 145 %q4 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 4 146 %q5 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 5 147 148 ; Fold strncmp(a, c, n) to N > 7 ? -1 : 0. 149 %c0_0 = call i32 @strncmp(ptr @a01230123, ptr @c01230129, i64 %n) 150 store i32 %c0_0, ptr %pcmp 151 152 ; Fold strncmp(a, c + 1, n) to N != 0 ? -1 : 0. 153 %c0_1 = call i32 @strncmp(ptr @a01230123, ptr %q1, i64 %n) 154 %s0_1 = getelementptr i32, ptr %pcmp, i64 1 155 store i32 %c0_1, ptr %s0_1 156 157 ; Fold strncmp(a, c + 2, n) to N != 0 ? -1 : 0. 158 %c0_2 = call i32 @strncmp(ptr @a01230123, ptr %q2, i64 %n) 159 %s0_2 = getelementptr i32, ptr %pcmp, i64 2 160 store i32 %c0_2, ptr %s0_2 161 162 ; Fold strncmp(a, c + 3, n) to N != 0 ? -1 : 0. 163 %c0_3 = call i32 @strncmp(ptr @a01230123, ptr %q3, i64 %n) 164 %s0_3 = getelementptr i32, ptr %pcmp, i64 3 165 store i32 %c0_3, ptr %s0_3 166 167 ; Fold strncmp(a, c + 4, n) to N > 3 ? -1 : 0. 168 %c0_4 = call i32 @strncmp(ptr @a01230123, ptr %q4, i64 %n) 169 %s0_4 = getelementptr i32, ptr %pcmp, i64 4 170 store i32 %c0_4, ptr %s0_4 171 172 ; Fold strncmp(a, c + 5, n) to N != 0 ? -1 : 0. 173 %c0_5 = call i32 @strncmp(ptr @a01230123, ptr %q4, i64 %n) 174 %s0_5 = getelementptr i32, ptr %pcmp, i64 5 175 store i32 %c0_5, ptr %s0_5 176 177 ret void 178} 179 180 181; Exercise strncmp(A, D, N) folding of arrays of different sizes and 182; a difference in the leading byte. 183 184define void @fold_strncmp_a_d_n(ptr %pcmp, i64 %n) { 185; CHECK-LABEL: @fold_strncmp_a_d_n( 186; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[N:%.*]], 0 187; CHECK-NEXT: [[C0_0:%.*]] = sext i1 [[TMP1]] to i32 188; CHECK-NEXT: store i32 [[C0_0]], ptr [[PCMP:%.*]], align 4 189; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[N]], 0 190; CHECK-NEXT: [[C0_1:%.*]] = sext i1 [[TMP2]] to i32 191; CHECK-NEXT: [[S0_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4 192; CHECK-NEXT: store i32 [[C0_1]], ptr [[S0_1]], align 4 193; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt i64 [[N]], 3 194; CHECK-NEXT: [[C1_1:%.*]] = zext i1 [[TMP3]] to i32 195; CHECK-NEXT: [[S1_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8 196; CHECK-NEXT: store i32 [[C1_1]], ptr [[S1_1]], align 4 197; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i64 [[N]], 2 198; CHECK-NEXT: [[C2_2:%.*]] = zext i1 [[TMP4]] to i32 199; CHECK-NEXT: [[S2_2:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12 200; CHECK-NEXT: store i32 [[C2_2]], ptr [[S2_2]], align 4 201; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i64 [[N]], 0 202; CHECK-NEXT: [[C4_4:%.*]] = zext i1 [[TMP5]] to i32 203; CHECK-NEXT: [[S4_4:%.*]] = getelementptr i8, ptr [[PCMP]], i64 16 204; CHECK-NEXT: store i32 [[C4_4]], ptr [[S4_4]], align 4 205; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i64 [[N]], 0 206; CHECK-NEXT: [[C4_4_2:%.*]] = sext i1 [[TMP6]] to i32 207; CHECK-NEXT: [[S4_4_2:%.*]] = getelementptr i8, ptr [[PCMP]], i64 20 208; CHECK-NEXT: store i32 [[C4_4_2]], ptr [[S4_4_2]], align 4 209; CHECK-NEXT: [[S5_5:%.*]] = getelementptr i8, ptr [[PCMP]], i64 24 210; CHECK-NEXT: store i32 0, ptr [[S5_5]], align 4 211; CHECK-NEXT: [[S6_6:%.*]] = getelementptr i8, ptr [[PCMP]], i64 28 212; CHECK-NEXT: store i32 0, ptr [[S6_6]], align 4 213; CHECK-NEXT: ret void 214; 215 216 %p1 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 1 217 %p2 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 2 218 %p3 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 3 219 %p4 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 4 220 %p5 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 5 221 %p6 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 6 222 223 %q1 = getelementptr [7 x i8], ptr @d9123_12, i64 0, i64 1 224 %q2 = getelementptr [7 x i8], ptr @d9123_12, i64 0, i64 2 225 %q3 = getelementptr [7 x i8], ptr @d9123_12, i64 0, i64 3 226 %q4 = getelementptr [7 x i8], ptr @d9123_12, i64 0, i64 4 227 %q5 = getelementptr [7 x i8], ptr @d9123_12, i64 0, i64 5 228 %q6 = getelementptr [7 x i8], ptr @d9123_12, i64 0, i64 6 229 230 ; Fold strncmp(a, d, n) to N != 0 ? -1 : 0. 231 %c0_0 = call i32 @strncmp(ptr @a01230123, ptr @d9123_12, i64 %n) 232 store i32 %c0_0, ptr %pcmp 233 234 ; Fold strncmp(a, d + 1, n) to N != 0 ? -1 : 0. 235 %c0_1 = call i32 @strncmp(ptr @a01230123, ptr %q1, i64 %n) 236 %s0_1 = getelementptr i32, ptr %pcmp, i64 1 237 store i32 %c0_1, ptr %s0_1 238 239 ; Fold strncmp(a + 1, d + 1, n) N > 3 ? +1 : 0. 240 %c1_1 = call i32 @strncmp(ptr %p1, ptr %q1, i64 %n) 241 %s1_1 = getelementptr i32, ptr %pcmp, i64 2 242 store i32 %c1_1, ptr %s1_1 243 244 ; Fold strncmp(a + 2, d + 2, n) N > 2 ? +1 : 0. 245 %c2_2 = call i32 @strncmp(ptr %p2, ptr %q2, i64 %n) 246 %s2_2 = getelementptr i32, ptr %pcmp, i64 3 247 store i32 %c2_2, ptr %s2_2 248 249 ; Fold strncmp(a + 3, d + 3, n) N > 1 ? +1 : 0. 250 %c3_3 = call i32 @strncmp(ptr %p3, ptr %q3, i64 %n) 251 %s3_3 = getelementptr i32, ptr %pcmp, i64 4 252 store i32 %c3_3, ptr %s3_3 253 254 ; Fold strncmp(a + 4, d + 4, n) N != 0 ? +1 : 0. 255 %c4_4 = call i32 @strncmp(ptr %p4, ptr %q4, i64 %n) 256 %s4_4 = getelementptr i32, ptr %pcmp, i64 4 257 store i32 %c4_4, ptr %s4_4 258 259 ; Fold strncmp(d + 4, a + 4, n) N != 0 ? -1 : 0 (same as above but 260 ; with the array arguments reversed). 261 %c4_4_2 = call i32 @strncmp(ptr %q4, ptr %p4, i64 %n) 262 %s4_4_2 = getelementptr i32, ptr %pcmp, i64 5 263 store i32 %c4_4_2, ptr %s4_4_2 264 265 ; Fold strncmp(a + 5, d + 5, n) to 0. 266 %c5_5 = call i32 @strncmp(ptr %p5, ptr %q5, i64 %n) 267 %s5_5 = getelementptr i32, ptr %pcmp, i64 6 268 store i32 %c5_5, ptr %s5_5 269 270 ; Fold strncmp(a + 6, d + 6, n) to 0. 271 %c6_6 = call i32 @strncmp(ptr %p6, ptr %q6, i64 %n) 272 %s6_6 = getelementptr i32, ptr %pcmp, i64 7 273 store i32 %c6_6, ptr %s6_6 274 275 ret void 276} 277 278 279; Exercise strncmp(A, D, N) folding of arrays with the same bytes and 280; a nonzero size. 281 282define void @fold_strncmp_a_d_nz(ptr %pcmp, i64 %n) { 283; CHECK-LABEL: @fold_strncmp_a_d_nz( 284; CHECK-NEXT: store i32 -1, ptr [[PCMP:%.*]], align 4 285; CHECK-NEXT: ret void 286; 287 288 %nz = or i64 %n, 1 289 290 %c0_0 = call i32 @strncmp(ptr @a01230123, ptr @d9123_12, i64 %nz) 291 store i32 %c0_0, ptr %pcmp 292 293 ret void 294} 295 296 297; Exercise strncmp(D, E, N) folding of equal strings but unequal arrays. 298 299define void @fold_strncmp_d_e_n(ptr %pcmp, i64 %n) { 300; CHECK-LABEL: @fold_strncmp_d_e_n( 301; CHECK-NEXT: store i32 0, ptr [[PCMP:%.*]], align 4 302; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[N:%.*]], 0 303; CHECK-NEXT: [[C0_1:%.*]] = zext i1 [[TMP1]] to i32 304; CHECK-NEXT: [[S0_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4 305; CHECK-NEXT: store i32 [[C0_1]], ptr [[S0_1]], align 4 306; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[N]], 0 307; CHECK-NEXT: [[C1_0:%.*]] = sext i1 [[TMP2]] to i32 308; CHECK-NEXT: [[S1_0:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8 309; CHECK-NEXT: store i32 [[C1_0]], ptr [[S1_0]], align 4 310; CHECK-NEXT: [[S1_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12 311; CHECK-NEXT: store i32 0, ptr [[S1_1]], align 4 312; CHECK-NEXT: ret void 313; 314 315 %p1 = getelementptr [7 x i8], ptr @d9123_12, i64 0, i64 1 316 317 %q1 = getelementptr [7 x i8], ptr @e9123_34, i64 0, i64 1 318 319 ; Fold to 0. 320 %c0_0 = call i32 @strncmp(ptr @d9123_12, ptr @e9123_34, i64 %n) 321 store i32 %c0_0, ptr %pcmp 322 323 ; Fold to N ? +1 : 0. 324 %c0_1 = call i32 @strncmp(ptr @d9123_12, ptr %q1, i64 %n) 325 %s0_1 = getelementptr i32, ptr %pcmp, i64 1 326 store i32 %c0_1, ptr %s0_1 327 328 ; Fold to N ? -1 : 0. 329 %c1_0 = call i32 @strncmp(ptr %p1, ptr @e9123_34, i64 %n) 330 %s1_0 = getelementptr i32, ptr %pcmp, i64 2 331 store i32 %c1_0, ptr %s1_0 332 333 ; Fold to 0. 334 %c1_1 = call i32 @strncmp(ptr %p1, ptr %q1, i64 %n) 335 %s1_1 = getelementptr i32, ptr %pcmp, i64 3 336 store i32 %c1_1, ptr %s1_1 337 338 ret void 339} 340