Skip to content

Commit 7067486

Browse files
committed
[SingleSource/Vectorizer] Add unit tests for index-select pattern.
Dedicated unit tests for vectorization of loops which select the index of the minimum value like below: uint32_t Min = -1; uint32_t MinIdx = 0;, for (unsigned I = 0; I < TC; I++) { uint32_t D = A[I] + B[I]; if (D < Min) { Min = D; MinIdx = I; } } return MinIdx; This adds runtime test coverage for D132063. Depends on D143377. Reviewed By: ABataev, Meinersbur Differential Revision: https://reviews.llvm.org/D143378
1 parent 1dd439e commit 7067486

File tree

2 files changed

+281
-0
lines changed

2 files changed

+281
-0
lines changed
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
#include <algorithm>
2+
#include <functional>
3+
#include <iostream>
4+
#include <limits>
5+
#include <memory>
6+
#include <stdint.h>
7+
8+
#include "common.h"
9+
10+
template <typename RetTy, typename Ty>
11+
using Fn2Ty = std::function<RetTy(Ty *, Ty *, unsigned)>;
12+
template <typename RetTy, typename Ty>
13+
static void checkVectorFunction(Fn2Ty<RetTy, Ty> ScalarFn,
14+
Fn2Ty<RetTy, Ty> VectorFn, const char *Name) {
15+
std::cout << "Checking " << Name << "\n";
16+
17+
unsigned N = 1000;
18+
std::unique_ptr<Ty[]> Src1(new Ty[N]);
19+
std::unique_ptr<Ty[]> Src2(new Ty[N]);
20+
init_data(Src1, N);
21+
init_data(Src2, N);
22+
23+
// Test VectorFn with different input data.
24+
{
25+
// Check with random inputs.
26+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
27+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
28+
if (Reference != ToCheck) {
29+
std::cerr << "Miscompare\n";
30+
exit(1);
31+
}
32+
}
33+
34+
{
35+
// Check with sorted inputs.
36+
std::sort(&Src1[0], &Src1[N]);
37+
std::sort(&Src2[0], &Src2[N]);
38+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
39+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
40+
if (Reference != ToCheck) {
41+
std::cerr << "Miscompare\n";
42+
exit(1);
43+
}
44+
}
45+
46+
{
47+
// Check with all max values.
48+
for (unsigned I = 0; I != N; ++I) {
49+
Src1[I] = std::numeric_limits<Ty>::max();
50+
Src2[I] = std::numeric_limits<Ty>::max();
51+
}
52+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
53+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
54+
if (Reference != ToCheck) {
55+
std::cerr << "Miscompare\n";
56+
exit(1);
57+
}
58+
}
59+
60+
{
61+
// Check with first input all zeros and second input -1.
62+
for (unsigned I = 0; I != N; ++I) {
63+
Src1[I] = 0;
64+
Src2[I] = std::numeric_limits<Ty>::max();
65+
}
66+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
67+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
68+
if (Reference != ToCheck) {
69+
std::cerr << "Miscompare\n";
70+
exit(1);
71+
}
72+
}
73+
74+
{
75+
// Check with first input all max values and second input all zeros.
76+
for (unsigned I = 0; I != N; ++I) {
77+
Src1[I] = std::numeric_limits<Ty>::max();
78+
Src2[I] = 0;
79+
}
80+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
81+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
82+
if (Reference != ToCheck) {
83+
std::cerr << "Miscompare\n";
84+
exit(1);
85+
}
86+
}
87+
88+
{
89+
// Check with inputs all zero.
90+
for (unsigned I = 0; I != N; ++I) {
91+
Src1[I] = 0;
92+
Src2[I] = 0;
93+
}
94+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
95+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
96+
if (Reference != ToCheck) {
97+
std::cerr << "Miscompare\n";
98+
exit(1);
99+
}
100+
}
101+
}
102+
103+
int main(void) {
104+
rng = std::mt19937(15);
105+
106+
// Tests select-minimum-index loops, where the loop selects the minimum value
107+
// and the first index of that value.
108+
{
109+
// Check loop starting at index 0 and stepping by 1.
110+
DEFINE_SCALAR_AND_VECTOR_FN2(
111+
uint32_t Min = std::numeric_limits<uint32_t>::max();
112+
uint32_t MinIdx = 0;,
113+
for (unsigned I = 0; I < TC; I++) {
114+
uint32_t D = A[I] + B[I];
115+
if (D < Min) {
116+
Min = D;
117+
MinIdx = I;
118+
}
119+
}
120+
return MinIdx;
121+
);
122+
checkVectorFunction<uint32_t, uint32_t>(ScalarFn, VectorFn,
123+
"min_index_select_u32_u32_start_0");
124+
}
125+
126+
{
127+
// Check loop starting at index 0 and stepping by 1.
128+
DEFINE_SCALAR_AND_VECTOR_FN2(
129+
uint32_t Min = std::numeric_limits<uint32_t>::max();
130+
uint32_t MinIdx = 0;,
131+
for (unsigned I = 0; I < TC / 2; I += 2) {
132+
uint32_t D = A[I] + B[I];
133+
if (D < Min) {
134+
Min = D;
135+
MinIdx = I;
136+
}
137+
}
138+
return MinIdx;
139+
);
140+
checkVectorFunction<uint32_t, uint32_t>(
141+
ScalarFn, VectorFn, "min_index_select_u32_u32_start_0_inc_2");
142+
}
143+
144+
{
145+
// Check loop starting at index 0 and stepping by 1. MinIdx starting at 2.
146+
DEFINE_SCALAR_AND_VECTOR_FN2(
147+
uint32_t Min = std::numeric_limits<uint32_t>::max();
148+
uint32_t MinIdx = 2;,
149+
for (unsigned I = 0; I < TC; I++) {
150+
uint32_t D = A[I] + B[I];
151+
if (D < Min) {
152+
Min = D;
153+
MinIdx = I;
154+
}
155+
}
156+
return MinIdx;
157+
);
158+
checkVectorFunction<uint32_t, uint32_t>(ScalarFn, VectorFn,
159+
"min_index_select_u32_u32_start_2");
160+
}
161+
162+
{
163+
// Index is truncated in the loop.
164+
DEFINE_SCALAR_AND_VECTOR_FN2(
165+
uint32_t Min = std::numeric_limits<uint32_t>::max();
166+
uint32_t MinIdx = 0;,
167+
for (uint64_t I = 0; I < TC; I++) {
168+
uint32_t D = A[I] + B[I];
169+
if (D < Min) {
170+
Min = D;
171+
MinIdx = I;
172+
}
173+
}
174+
return MinIdx;
175+
);
176+
checkVectorFunction<uint32_t, uint32_t>(
177+
ScalarFn, VectorFn, "min_index_select_u32_u32_with_trunc");
178+
}
179+
180+
{
181+
// Check loop where induction is truncated.
182+
DEFINE_SCALAR_AND_VECTOR_FN2(
183+
uint32_t Min = std::numeric_limits<uint32_t>::max();
184+
uint32_t MinIdx = 0;,
185+
for (unsigned I = TC; I > 0; I--) {
186+
uint32_t D = A[I] + B[I];
187+
if (D < Min) {
188+
Min = D;
189+
MinIdx = I;
190+
}
191+
}
192+
return MinIdx;
193+
);
194+
checkVectorFunction<uint32_t, uint32_t>(
195+
ScalarFn, VectorFn, "min_index_select_u32_u32_induction_decrement");
196+
}
197+
198+
{
199+
// Check loop where both Min and MinIdx starts at the maximum value.
200+
DEFINE_SCALAR_AND_VECTOR_FN2(
201+
uint32_t Min = std::numeric_limits<uint32_t>::max();
202+
uint32_t MinIdx = std::numeric_limits<uint32_t>::max();,
203+
for (unsigned I = 0; I < TC; I++) {
204+
uint32_t D = A[I] + B[I];
205+
if (D < Min) {
206+
Min = D;
207+
MinIdx = I;
208+
}
209+
}
210+
return MinIdx;
211+
);
212+
checkVectorFunction<uint32_t, uint32_t>(
213+
ScalarFn, VectorFn, "min_index_select_u32_u32_start_0_min_idx_neg1");
214+
}
215+
216+
{
217+
// Check loop starting at index 3 and stepping by 1. MinIdx starts at 3.
218+
DEFINE_SCALAR_AND_VECTOR_FN2(
219+
uint32_t Min = std::numeric_limits<uint32_t>::max();
220+
uint32_t MinIdx = 3;,
221+
for (unsigned I = 3; I < TC; I++) {
222+
uint32_t D = A[I] + B[I];
223+
if (D < Min) {
224+
Min = D;
225+
MinIdx = I;
226+
}
227+
}
228+
return MinIdx;
229+
);
230+
checkVectorFunction<uint32_t, uint32_t>(
231+
ScalarFn, VectorFn, "min_index_select_u32_u32_start_3_min_idx_3");
232+
}
233+
234+
{
235+
// Check loop starting at index 3 and stepping by 1. MinIdx starts at 2.
236+
DEFINE_SCALAR_AND_VECTOR_FN2(
237+
uint32_t Min = std::numeric_limits<uint32_t>::max();
238+
uint32_t MinIdx = 2;,
239+
for (unsigned I = 3; I < TC; I++) {
240+
uint32_t D = A[I] + B[I];
241+
if (D < Min) {
242+
Min = D;
243+
MinIdx = I;
244+
}
245+
}
246+
return MinIdx;
247+
);
248+
checkVectorFunction<uint32_t, uint32_t>(
249+
ScalarFn, VectorFn, "min_index_select_u32_u32_start_3_min_idx_2");
250+
}
251+
252+
{
253+
// Check loop starting at index 3 and stepping by 1. MinIdx starts at 4.
254+
DEFINE_SCALAR_AND_VECTOR_FN2(
255+
uint32_t Min = std::numeric_limits<uint32_t>::max();
256+
uint32_t MinIdx = 4;,
257+
for (unsigned I = 3; I < TC; I++) {
258+
uint32_t D = A[I] + B[I];
259+
if (D < Min) {
260+
Min = D;
261+
MinIdx = I;
262+
}
263+
}
264+
return MinIdx;
265+
);
266+
checkVectorFunction<uint32_t, uint32_t>(
267+
ScalarFn, VectorFn, "min_index_select_u32_u32_start_3_min_idx_4");
268+
}
269+
270+
return 0;
271+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Checking min_index_select_u32_u32_start_0
2+
Checking min_index_select_u32_u32_start_0_inc_2
3+
Checking min_index_select_u32_u32_start_2
4+
Checking min_index_select_u32_u32_with_trunc
5+
Checking min_index_select_u32_u32_induction_decrement
6+
Checking min_index_select_u32_u32_start_0_min_idx_neg1
7+
Checking min_index_select_u32_u32_start_3_min_idx_3
8+
Checking min_index_select_u32_u32_start_3_min_idx_2
9+
Checking min_index_select_u32_u32_start_3_min_idx_4
10+
exit 0

0 commit comments

Comments
 (0)