xref: /llvm-project/llvm/test/Transforms/InstCombine/memcmp-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 memcmp calls with constant arrays and nonconstant
5; sizes.
6
7declare i32 @memcmp(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@d9123012  = constant [7 x i8] c"9123012"
14
15
16; Exercise memcmp(A, B, N) folding of arrays with the same bytes.
17
18define void @fold_memcmp_a_b_n(ptr %pcmp, i64 %n) {
19; CHECK-LABEL: @fold_memcmp_a_b_n(
20; CHECK-NEXT:    store i32 0, ptr [[PCMP:%.*]], align 4
21; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[N:%.*]], 0
22; CHECK-NEXT:    [[C0_1:%.*]] = sext i1 [[TMP1]] to i32
23; CHECK-NEXT:    [[S0_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4
24; CHECK-NEXT:    store i32 [[C0_1]], ptr [[S0_1]], align 4
25; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[N]], 0
26; CHECK-NEXT:    [[C0_2:%.*]] = sext i1 [[TMP2]] to i32
27; CHECK-NEXT:    [[S0_2:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8
28; CHECK-NEXT:    store i32 [[C0_2]], ptr [[S0_2]], align 4
29; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i64 [[N]], 0
30; CHECK-NEXT:    [[C0_3:%.*]] = sext i1 [[TMP3]] to i32
31; CHECK-NEXT:    [[S0_3:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12
32; CHECK-NEXT:    store i32 [[C0_3]], ptr [[S0_3]], align 4
33; CHECK-NEXT:    [[S0_4:%.*]] = getelementptr i8, ptr [[PCMP]], i64 16
34; CHECK-NEXT:    store i32 0, ptr [[S0_4]], align 4
35; CHECK-NEXT:    [[TMP4:%.*]] = icmp ne i64 [[N]], 0
36; CHECK-NEXT:    [[C0_5:%.*]] = sext i1 [[TMP4]] to i32
37; CHECK-NEXT:    [[S0_5:%.*]] = getelementptr i8, ptr [[PCMP]], i64 20
38; CHECK-NEXT:    store i32 [[C0_5]], ptr [[S0_5]], align 4
39; CHECK-NEXT:    ret void
40;
41
42
43  %q1 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 1
44  %q2 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 2
45  %q3 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 3
46  %q4 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 4
47  %q5 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 5
48
49  ; Fold memcmp(a, b, n) to 0.
50  %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @b01230123, i64 %n)
51  store i32 %c0_0, ptr %pcmp
52
53  ; Fold memcmp(a, b + 1, n) to N != 0 ? -1 : 0.
54  %c0_1 = call i32 @memcmp(ptr @a01230123, ptr %q1, i64 %n)
55  %s0_1 = getelementptr i32, ptr %pcmp, i64 1
56  store i32 %c0_1, ptr %s0_1
57
58  ; Fold memcmp(a, b + 2, n) to N != 0 ? -1 : 0.
59  %c0_2 = call i32 @memcmp(ptr @a01230123, ptr %q2, i64 %n)
60  %s0_2 = getelementptr i32, ptr %pcmp, i64 2
61  store i32 %c0_2, ptr %s0_2
62
63  ; Fold memcmp(a, b + 3, n) to N != 0 ? -1 : 0.
64  %c0_3 = call i32 @memcmp(ptr @a01230123, ptr %q3, i64 %n)
65  %s0_3 = getelementptr i32, ptr %pcmp, i64 3
66  store i32 %c0_3, ptr %s0_3
67
68  ; Fold memcmp(a, b + 4, n) to 0.
69  %c0_4 = call i32 @memcmp(ptr @a01230123, ptr %q4, i64 %n)
70  %s0_4 = getelementptr i32, ptr %pcmp, i64 4
71  store i32 %c0_4, ptr %s0_4
72
73  ; Fold memcmp(a, b + 5, n) to N != 0 ? -1 : 0.
74  %c0_5 = call i32 @memcmp(ptr @a01230123, ptr %q5, i64 %n)
75  %s0_5 = getelementptr i32, ptr %pcmp, i64 5
76  store i32 %c0_5, ptr %s0_5
77
78  ret void
79}
80
81; Vefify that a memcmp() call involving a constant array with unknown
82; contents is not folded.
83
84define void @call_memcmp_a_ax_n(ptr %pcmp, i64 %n) {
85; CHECK-LABEL: @call_memcmp_a_ax_n(
86; CHECK-NEXT:    [[C0_0:%.*]] = call i32 @memcmp(ptr nonnull @a01230123, ptr nonnull @ax, i64 [[N:%.*]])
87; CHECK-NEXT:    store i32 [[C0_0]], ptr [[PCMP:%.*]], align 4
88; CHECK-NEXT:    ret void
89;
90
91
92  ; Do not fold memcmp(a, ax, n).
93  %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @ax, i64 %n)
94  store i32 %c0_0, ptr %pcmp
95
96  ret void
97}
98
99
100; Exercise memcmp(A, C, N) folding of arrays with the same leading bytes
101; but a difference in the trailing byte.
102
103define void @fold_memcmp_a_c_n(ptr %pcmp, i64 %n) {
104; CHECK-LABEL: @fold_memcmp_a_c_n(
105; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i64 [[N:%.*]], 7
106; CHECK-NEXT:    [[C0_0:%.*]] = sext i1 [[TMP1]] to i32
107; CHECK-NEXT:    store i32 [[C0_0]], ptr [[PCMP:%.*]], align 4
108; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[N]], 0
109; CHECK-NEXT:    [[C0_1:%.*]] = sext i1 [[TMP2]] to i32
110; CHECK-NEXT:    [[S0_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4
111; CHECK-NEXT:    store i32 [[C0_1]], ptr [[S0_1]], align 4
112; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i64 [[N]], 0
113; CHECK-NEXT:    [[C0_2:%.*]] = sext i1 [[TMP3]] to i32
114; CHECK-NEXT:    [[S0_2:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8
115; CHECK-NEXT:    store i32 [[C0_2]], ptr [[S0_2]], align 4
116; CHECK-NEXT:    [[TMP4:%.*]] = icmp ne i64 [[N]], 0
117; CHECK-NEXT:    [[C0_3:%.*]] = sext i1 [[TMP4]] to i32
118; CHECK-NEXT:    [[S0_3:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12
119; CHECK-NEXT:    store i32 [[C0_3]], ptr [[S0_3]], align 4
120; CHECK-NEXT:    [[TMP5:%.*]] = icmp ugt i64 [[N]], 3
121; CHECK-NEXT:    [[C0_4:%.*]] = sext i1 [[TMP5]] to i32
122; CHECK-NEXT:    [[S0_4:%.*]] = getelementptr i8, ptr [[PCMP]], i64 16
123; CHECK-NEXT:    store i32 [[C0_4]], ptr [[S0_4]], align 4
124; CHECK-NEXT:    [[TMP6:%.*]] = icmp ugt i64 [[N]], 3
125; CHECK-NEXT:    [[C0_5:%.*]] = sext i1 [[TMP6]] to i32
126; CHECK-NEXT:    [[S0_5:%.*]] = getelementptr i8, ptr [[PCMP]], i64 20
127; CHECK-NEXT:    store i32 [[C0_5]], ptr [[S0_5]], align 4
128; CHECK-NEXT:    ret void
129;
130
131
132  %q1 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 1
133  %q2 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 2
134  %q3 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 3
135  %q4 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 4
136  %q5 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 5
137
138  ; Fold memcmp(a, c, n) to N > 7 ? -1 : 0.
139  %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @c01230129, i64 %n)
140  store i32 %c0_0, ptr %pcmp
141
142  ; Fold memcmp(a, c + 1, n) to N != 0 ? -1 : 0.
143  %c0_1 = call i32 @memcmp(ptr @a01230123, ptr %q1, i64 %n)
144  %s0_1 = getelementptr i32, ptr %pcmp, i64 1
145  store i32 %c0_1, ptr %s0_1
146
147  ; Fold memcmp(a, c + 2, n) to N != 0 ? -1 : 0.
148  %c0_2 = call i32 @memcmp(ptr @a01230123, ptr %q2, i64 %n)
149  %s0_2 = getelementptr i32, ptr %pcmp, i64 2
150  store i32 %c0_2, ptr %s0_2
151
152  ; Fold memcmp(a, c + 3, n) to N != 0 ? -1 : 0.
153  %c0_3 = call i32 @memcmp(ptr @a01230123, ptr %q3, i64 %n)
154  %s0_3 = getelementptr i32, ptr %pcmp, i64 3
155  store i32 %c0_3, ptr %s0_3
156
157  ; Fold memcmp(a, c + 4, n) to N > 3 ? -1 : 0.
158  %c0_4 = call i32 @memcmp(ptr @a01230123, ptr %q4, i64 %n)
159  %s0_4 = getelementptr i32, ptr %pcmp, i64 4
160  store i32 %c0_4, ptr %s0_4
161
162  ; Fold memcmp(a, c + 5, n) to N != 0 ? -1 : 0.
163  %c0_5 = call i32 @memcmp(ptr @a01230123, ptr %q4, i64 %n)
164  %s0_5 = getelementptr i32, ptr %pcmp, i64 5
165  store i32 %c0_5, ptr %s0_5
166
167  ret void
168}
169
170
171; Exercise memcmp(A, D, N) folding of arrays of different sizes and
172; a difference in the leading byte.
173
174define void @fold_memcmp_a_d_n(ptr %pcmp, i64 %n) {
175; CHECK-LABEL: @fold_memcmp_a_d_n(
176; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[N:%.*]], 0
177; CHECK-NEXT:    [[C0_0:%.*]] = sext i1 [[TMP1]] to i32
178; CHECK-NEXT:    store i32 [[C0_0]], ptr [[PCMP:%.*]], align 4
179; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i64 [[N]], 0
180; CHECK-NEXT:    [[C0_1:%.*]] = sext i1 [[TMP2]] to i32
181; CHECK-NEXT:    [[S0_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4
182; CHECK-NEXT:    store i32 [[C0_1]], ptr [[S0_1]], align 4
183; CHECK-NEXT:    [[S1_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8
184; CHECK-NEXT:    store i32 0, ptr [[S1_1]], align 4
185; CHECK-NEXT:    [[S6_6:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12
186; CHECK-NEXT:    store i32 0, ptr [[S6_6]], align 4
187; CHECK-NEXT:    ret void
188;
189
190  %p1 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 1
191  %p6 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 6
192
193  %q1 = getelementptr [7 x i8], ptr @d9123012, i64 0, i64 1
194  %q6 = getelementptr [7 x i8], ptr @d9123012, i64 0, i64 6
195
196  ; Fold memcmp(a, d, n) to N != 0 ? -1 : 0.
197  %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @d9123012, i64 %n)
198  store i32 %c0_0, ptr %pcmp
199
200  ; Fold memcmp(a, d + 1, n) to N != 0 -1 : 0.
201  %c0_1 = call i32 @memcmp(ptr @a01230123, ptr %q1, i64 %n)
202  %s0_1 = getelementptr i32, ptr %pcmp, i64 1
203  store i32 %c0_1, ptr %s0_1
204
205  ; Fold memcmp(a + 1, d + 1, n) to 0.
206  %c1_1 = call i32 @memcmp(ptr %p1, ptr %q1, i64 %n)
207  %s1_1 = getelementptr i32, ptr %pcmp, i64 2
208  store i32 %c1_1, ptr %s1_1
209
210  ; Fold memcmp(a + 6, d + 6, n) to 0.
211  %c6_6 = call i32 @memcmp(ptr %p6, ptr %q6, i64 %n)
212  %s6_6 = getelementptr i32, ptr %pcmp, i64 3
213  store i32 %c6_6, ptr %s6_6
214
215  ret void
216}
217
218
219; Exercise memcmp(A, D, N) folding of arrays with the same bytes and
220; a nonzero size.
221
222define void @fold_memcmp_a_d_nz(ptr %pcmp, i64 %n) {
223; CHECK-LABEL: @fold_memcmp_a_d_nz(
224; CHECK-NEXT:    store i32 -1, ptr [[PCMP:%.*]], align 4
225; CHECK-NEXT:    ret void
226;
227
228  %nz = or i64 %n, 1
229
230  %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @d9123012, i64 %nz)
231  store i32 %c0_0, ptr %pcmp
232
233  ret void
234}
235