Skip to content

Commit 8946a3f

Browse files
authored
[SingleSource/Vectorizer] Add unit tests for AnyOf pattern. (#195)
This patch adds runtime test case for vectorization of AnyOf reduction idiom: int32_t Rdx = -1; for (unsigned I = 0; I < TC; I++) { Rdx = A[I] > B[I] ? 3 : Rdx; } return Rdx; Improving test coverage, and please refer the issue llvm/llvm-project#120405.
1 parent e6f6740 commit 8946a3f

File tree

2 files changed

+222
-0
lines changed

2 files changed

+222
-0
lines changed
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
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 Src1 > Src2 for all elements.
36+
for (unsigned I = 0; I != N; ++I) {
37+
Src1[I] = std::numeric_limits<Ty>::max();
38+
Src2[I] = std::numeric_limits<Ty>::min();
39+
}
40+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
41+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
42+
if (Reference != ToCheck) {
43+
std::cerr << "Miscompare\n";
44+
exit(1);
45+
}
46+
}
47+
48+
{
49+
// Check with Src1 < Src2 for all elements.
50+
for (unsigned I = 0; I != N; ++I) {
51+
Src1[I] = std::numeric_limits<Ty>::min();
52+
Src2[I] = std::numeric_limits<Ty>::max();
53+
}
54+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
55+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
56+
if (Reference != ToCheck) {
57+
std::cerr << "Miscompare\n";
58+
exit(1);
59+
}
60+
}
61+
62+
{
63+
// Check with only Src1[998] > Src2[998].
64+
for (unsigned I = 0; I != N; ++I)
65+
Src1[I] = Src2[I] = std::numeric_limits<Ty>::min();
66+
Src1[998] = std::numeric_limits<Ty>::max();
67+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
68+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
69+
if (Reference != ToCheck) {
70+
std::cerr << "Miscompare\n";
71+
exit(1);
72+
}
73+
}
74+
75+
{
76+
// Check with only Src1[0] > Src2[0].
77+
for (unsigned I = 0; I != N; ++I)
78+
Src1[I] = Src2[I] = std::numeric_limits<Ty>::min();
79+
Src1[0] = std::numeric_limits<Ty>::max();
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 only Src1[N - 1] > Src2[N - 1].
90+
for (unsigned I = 0; I != N; ++I)
91+
Src1[I] = Src2[I] = std::numeric_limits<Ty>::min();
92+
Src1[N - 1] = std::numeric_limits<Ty>::max();
93+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
94+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
95+
if (Reference != ToCheck) {
96+
std::cerr << "Miscompare\n";
97+
exit(1);
98+
}
99+
}
100+
101+
{
102+
// Check with only Src1[0] > Src2[0] and Src1[N - 1] > Src2[N - 1].
103+
for (unsigned I = 0; I != N; ++I)
104+
Src1[I] = Src2[I] = std::numeric_limits<Ty>::min();
105+
Src1[0] = Src1[N - 1] = std::numeric_limits<Ty>::max();
106+
auto Reference = ScalarFn(&Src1[0], &Src2[0], N);
107+
auto ToCheck = VectorFn(&Src1[0], &Src2[0], N);
108+
if (Reference != ToCheck) {
109+
std::cerr << "Miscompare\n";
110+
exit(1);
111+
}
112+
}
113+
}
114+
115+
int main(void) {
116+
rng = std::mt19937(15);
117+
118+
#define DEFINE_ANYOF_LOOP_BODY(TrueVal, FalseVal) \
119+
for (unsigned I = 0; I < TC; I++) { \
120+
Rdx = A[I] > B[I] ? TrueVal : FalseVal; \
121+
} \
122+
return Rdx;
123+
124+
{
125+
// Update 32-bits integer Rdx to 3 once any A[i] > B[i] is true.
126+
DEFINE_SCALAR_AND_VECTOR_FN2(
127+
int32_t Rdx = -1;
128+
, DEFINE_ANYOF_LOOP_BODY(/* TrueVal= */ 3, /* FalseVal= */ Rdx));
129+
checkVectorFunction<int32_t, int32_t>(ScalarFn, VectorFn,
130+
"anyof_icmp_s32_true_update");
131+
checkVectorFunction<int32_t, float>(ScalarFn, VectorFn,
132+
"anyof_fcmp_s32_true_update");
133+
}
134+
135+
{
136+
// Update 16-bits integer Rdx to 3 once any A[i] > B[i] is true.
137+
DEFINE_SCALAR_AND_VECTOR_FN2(
138+
int16_t Rdx = -1;
139+
, DEFINE_ANYOF_LOOP_BODY(/* TrueVal= */ 3, /* FalseVal= */ Rdx));
140+
checkVectorFunction<int16_t, int16_t>(ScalarFn, VectorFn,
141+
"anyof_icmp_s16_true_update");
142+
}
143+
144+
{
145+
// Update 32-bits integer Rdx to 3 once any A[i] > B[i] is false.
146+
DEFINE_SCALAR_AND_VECTOR_FN2(
147+
int32_t Rdx = -1;
148+
, DEFINE_ANYOF_LOOP_BODY(/* TrueVal= */ Rdx, /* FalseVal= */ 3));
149+
checkVectorFunction<int32_t, int32_t>(ScalarFn, VectorFn,
150+
"anyof_icmp_s32_false_update");
151+
checkVectorFunction<int32_t, float>(ScalarFn, VectorFn,
152+
"anyof_fcmp_s32_false_update");
153+
}
154+
155+
{
156+
// Update 16-bits integer Rdx to 3 once any A[i] > B[i] is false.
157+
DEFINE_SCALAR_AND_VECTOR_FN2(
158+
int16_t Rdx = -1;
159+
, DEFINE_ANYOF_LOOP_BODY(/* TrueVal= */ Rdx, /* FalseVal= */ 3));
160+
checkVectorFunction<int16_t, int16_t>(ScalarFn, VectorFn,
161+
"anyof_icmp_s16_false_update");
162+
}
163+
164+
{
165+
// 32-bits integer Rdx starts from TC, and will be updated to 3 once any
166+
// A[i] > B[i] is true.
167+
DEFINE_SCALAR_AND_VECTOR_FN2(
168+
uint32_t Rdx = TC;
169+
, DEFINE_ANYOF_LOOP_BODY(/* TrueVal= */ 3, /* FalseVal= */ Rdx));
170+
checkVectorFunction<uint32_t, uint32_t>(ScalarFn, VectorFn,
171+
"anyof_icmp_u32_start_TC");
172+
checkVectorFunction<uint32_t, float>(ScalarFn, VectorFn,
173+
"anyof_fcmp_u32_start_TC");
174+
}
175+
176+
{
177+
// 16-bits integer Rdx starts from TC, and will be updated to 3 once any
178+
// A[i] > B[i] is true.
179+
DEFINE_SCALAR_AND_VECTOR_FN2(
180+
uint16_t Rdx = TC;
181+
, DEFINE_ANYOF_LOOP_BODY(/* TrueVal= */ 3, /* FalseVal= */ Rdx));
182+
checkVectorFunction<uint16_t, uint16_t>(ScalarFn, VectorFn,
183+
"anyof_icmp_u16_start_TC");
184+
}
185+
186+
{
187+
// 32-bits integer Rdx starts from 3, and will be updated to TC once any
188+
// A[i] > B[i] is true.
189+
DEFINE_SCALAR_AND_VECTOR_FN2(
190+
uint32_t Rdx = 3;
191+
, DEFINE_ANYOF_LOOP_BODY(/* TrueVal= */ TC, /* FalseVal= */ Rdx));
192+
checkVectorFunction<uint32_t, uint32_t>(ScalarFn, VectorFn,
193+
"anyof_icmp_u32_update_by_TC");
194+
checkVectorFunction<uint32_t, float>(ScalarFn, VectorFn,
195+
"anyof_fcmp_u32_update_by_TC");
196+
}
197+
198+
{
199+
// 16-bits integer Rdx starts from 3, and will be updated to TC once any
200+
// A[i] > B[i] is true.
201+
DEFINE_SCALAR_AND_VECTOR_FN2(
202+
uint16_t Rdx = 3;
203+
, DEFINE_ANYOF_LOOP_BODY(/* TrueVal= */ TC, /* FalseVal= */ Rdx));
204+
checkVectorFunction<uint16_t, uint16_t>(ScalarFn, VectorFn,
205+
"anyof_icmp_u16_update_by_TC");
206+
}
207+
208+
return 0;
209+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Checking anyof_icmp_s32_true_update
2+
Checking anyof_fcmp_s32_true_update
3+
Checking anyof_icmp_s16_true_update
4+
Checking anyof_icmp_s32_false_update
5+
Checking anyof_fcmp_s32_false_update
6+
Checking anyof_icmp_s16_false_update
7+
Checking anyof_icmp_u32_start_TC
8+
Checking anyof_fcmp_u32_start_TC
9+
Checking anyof_icmp_u16_start_TC
10+
Checking anyof_icmp_u32_update_by_TC
11+
Checking anyof_fcmp_u32_update_by_TC
12+
Checking anyof_icmp_u16_update_by_TC
13+
exit 0

0 commit comments

Comments
 (0)