1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; Exercise folding of memcmp calls with constant arrays and nonconstant
7 declare i32 @memcmp(ptr, ptr, i64)
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"
16 ; Exercise memcmp(A, B, N) folding of arrays with the same bytes.
18 define 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 i32, ptr [[PCMP]], i64 1
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 i32, ptr [[PCMP]], i64 2
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 i32, ptr [[PCMP]], i64 3
32 ; CHECK-NEXT: store i32 [[C0_3]], ptr [[S0_3]], align 4
33 ; CHECK-NEXT: [[S0_4:%.*]] = getelementptr i32, ptr [[PCMP]], i64 4
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 i32, ptr [[PCMP]], i64 5
38 ; CHECK-NEXT: store i32 [[C0_5]], ptr [[S0_5]], align 4
39 ; CHECK-NEXT: ret void
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
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
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
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
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
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
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
81 ; Vefify that a memcmp() call involving a constant array with unknown
82 ; contents is not folded.
84 define 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
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
100 ; Exercise memcmp(A, C, N) folding of arrays with the same leading bytes
101 ; but a difference in the trailing byte.
103 define 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 i32, ptr [[PCMP]], i64 1
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 i32, ptr [[PCMP]], i64 2
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 i32, ptr [[PCMP]], i64 3
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 i32, ptr [[PCMP]], i64 4
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 i32, ptr [[PCMP]], i64 5
127 ; CHECK-NEXT: store i32 [[C0_5]], ptr [[S0_5]], align 4
128 ; CHECK-NEXT: ret void
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
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
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
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
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
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
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
171 ; Exercise memcmp(A, D, N) folding of arrays of different sizes and
172 ; a difference in the leading byte.
174 define 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 i32, ptr [[PCMP]], i64 1
182 ; CHECK-NEXT: store i32 [[C0_1]], ptr [[S0_1]], align 4
183 ; CHECK-NEXT: [[S1_1:%.*]] = getelementptr i32, ptr [[PCMP]], i64 2
184 ; CHECK-NEXT: store i32 0, ptr [[S1_1]], align 4
185 ; CHECK-NEXT: [[S6_6:%.*]] = getelementptr i32, ptr [[PCMP]], i64 3
186 ; CHECK-NEXT: store i32 0, ptr [[S6_6]], align 4
187 ; CHECK-NEXT: ret void
190 %p1 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 1
191 %p6 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 6
193 %q1 = getelementptr [7 x i8], ptr @d9123012, i64 0, i64 1
194 %q6 = getelementptr [7 x i8], ptr @d9123012, i64 0, i64 6
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
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
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
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
219 ; Exercise memcmp(A, D, N) folding of arrays with the same bytes and
222 define 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
230 %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @d9123012, i64 %nz)
231 store i32 %c0_0, ptr %pcmp