xref: /llvm-project/llvm/test/Transforms/InstCombine/strncmp-5.ll (revision 90ba33099cbb17e7c159e9ebc5a512037db99d6d)
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