1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2022 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #include "Reactor.hpp"
16*03ce13f7SAndroid Build Coastguard Worker #include "SIMD.hpp"
17*03ce13f7SAndroid Build Coastguard Worker
18*03ce13f7SAndroid Build Coastguard Worker #include "gtest/gtest.h"
19*03ce13f7SAndroid Build Coastguard Worker
20*03ce13f7SAndroid Build Coastguard Worker using namespace rr;
21*03ce13f7SAndroid Build Coastguard Worker
testName()22*03ce13f7SAndroid Build Coastguard Worker static std::string testName()
23*03ce13f7SAndroid Build Coastguard Worker {
24*03ce13f7SAndroid Build Coastguard Worker auto info = ::testing::UnitTest::GetInstance()->current_test_info();
25*03ce13f7SAndroid Build Coastguard Worker return std::string{ info->test_suite_name() } + "_" + info->name();
26*03ce13f7SAndroid Build Coastguard Worker }
27*03ce13f7SAndroid Build Coastguard Worker
TEST(ReactorSIMD,Add)28*03ce13f7SAndroid Build Coastguard Worker TEST(ReactorSIMD, Add)
29*03ce13f7SAndroid Build Coastguard Worker {
30*03ce13f7SAndroid Build Coastguard Worker ASSERT_GE(SIMD::Width, 4);
31*03ce13f7SAndroid Build Coastguard Worker
32*03ce13f7SAndroid Build Coastguard Worker constexpr int arrayLength = 1024;
33*03ce13f7SAndroid Build Coastguard Worker
34*03ce13f7SAndroid Build Coastguard Worker FunctionT<void(int *, int *, int *)> function;
35*03ce13f7SAndroid Build Coastguard Worker {
36*03ce13f7SAndroid Build Coastguard Worker Pointer<Int> r = Pointer<Int>(function.Arg<0>());
37*03ce13f7SAndroid Build Coastguard Worker Pointer<Int> a = Pointer<Int>(function.Arg<1>());
38*03ce13f7SAndroid Build Coastguard Worker Pointer<Int> b = Pointer<Int>(function.Arg<2>());
39*03ce13f7SAndroid Build Coastguard Worker
40*03ce13f7SAndroid Build Coastguard Worker For(Int i = 0, i < arrayLength, i += SIMD::Width)
41*03ce13f7SAndroid Build Coastguard Worker {
42*03ce13f7SAndroid Build Coastguard Worker SIMD::Int x = *Pointer<SIMD::Int>(&a[i]);
43*03ce13f7SAndroid Build Coastguard Worker SIMD::Int y = *Pointer<SIMD::Int>(&b[i]);
44*03ce13f7SAndroid Build Coastguard Worker
45*03ce13f7SAndroid Build Coastguard Worker SIMD::Int z = x + y;
46*03ce13f7SAndroid Build Coastguard Worker
47*03ce13f7SAndroid Build Coastguard Worker *Pointer<SIMD::Int>(&r[i]) = z;
48*03ce13f7SAndroid Build Coastguard Worker }
49*03ce13f7SAndroid Build Coastguard Worker }
50*03ce13f7SAndroid Build Coastguard Worker
51*03ce13f7SAndroid Build Coastguard Worker auto routine = function(testName().c_str());
52*03ce13f7SAndroid Build Coastguard Worker
53*03ce13f7SAndroid Build Coastguard Worker int r[arrayLength] = {};
54*03ce13f7SAndroid Build Coastguard Worker int a[arrayLength];
55*03ce13f7SAndroid Build Coastguard Worker int b[arrayLength];
56*03ce13f7SAndroid Build Coastguard Worker
57*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < arrayLength; i++)
58*03ce13f7SAndroid Build Coastguard Worker {
59*03ce13f7SAndroid Build Coastguard Worker a[i] = i;
60*03ce13f7SAndroid Build Coastguard Worker b[i] = arrayLength + i;
61*03ce13f7SAndroid Build Coastguard Worker }
62*03ce13f7SAndroid Build Coastguard Worker
63*03ce13f7SAndroid Build Coastguard Worker routine(r, a, b);
64*03ce13f7SAndroid Build Coastguard Worker
65*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < arrayLength; i++)
66*03ce13f7SAndroid Build Coastguard Worker {
67*03ce13f7SAndroid Build Coastguard Worker ASSERT_EQ(r[i], arrayLength + 2 * i);
68*03ce13f7SAndroid Build Coastguard Worker }
69*03ce13f7SAndroid Build Coastguard Worker }
70*03ce13f7SAndroid Build Coastguard Worker
TEST(ReactorSIMD,Broadcast)71*03ce13f7SAndroid Build Coastguard Worker TEST(ReactorSIMD, Broadcast)
72*03ce13f7SAndroid Build Coastguard Worker {
73*03ce13f7SAndroid Build Coastguard Worker FunctionT<void(int *, int)> function;
74*03ce13f7SAndroid Build Coastguard Worker {
75*03ce13f7SAndroid Build Coastguard Worker Pointer<Int> r = Pointer<Int>(function.Arg<0>());
76*03ce13f7SAndroid Build Coastguard Worker Int a = function.Arg<1>();
77*03ce13f7SAndroid Build Coastguard Worker
78*03ce13f7SAndroid Build Coastguard Worker SIMD::Int x = a;
79*03ce13f7SAndroid Build Coastguard Worker
80*03ce13f7SAndroid Build Coastguard Worker *Pointer<SIMD::Int>(r) = x;
81*03ce13f7SAndroid Build Coastguard Worker }
82*03ce13f7SAndroid Build Coastguard Worker
83*03ce13f7SAndroid Build Coastguard Worker auto routine = function(testName().c_str());
84*03ce13f7SAndroid Build Coastguard Worker
85*03ce13f7SAndroid Build Coastguard Worker std::vector<int> r(SIMD::Width);
86*03ce13f7SAndroid Build Coastguard Worker
87*03ce13f7SAndroid Build Coastguard Worker for(int a = -2; a <= 2; a++)
88*03ce13f7SAndroid Build Coastguard Worker {
89*03ce13f7SAndroid Build Coastguard Worker routine(r.data(), a);
90*03ce13f7SAndroid Build Coastguard Worker
91*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < SIMD::Width; i++)
92*03ce13f7SAndroid Build Coastguard Worker {
93*03ce13f7SAndroid Build Coastguard Worker ASSERT_EQ(r[i], a);
94*03ce13f7SAndroid Build Coastguard Worker }
95*03ce13f7SAndroid Build Coastguard Worker }
96*03ce13f7SAndroid Build Coastguard Worker }
97*03ce13f7SAndroid Build Coastguard Worker
TEST(ReactorSIMD,InsertExtract128)98*03ce13f7SAndroid Build Coastguard Worker TEST(ReactorSIMD, InsertExtract128)
99*03ce13f7SAndroid Build Coastguard Worker {
100*03ce13f7SAndroid Build Coastguard Worker FunctionT<void(int *, int *)> function;
101*03ce13f7SAndroid Build Coastguard Worker {
102*03ce13f7SAndroid Build Coastguard Worker Pointer<Int> r = Pointer<Int>(function.Arg<0>());
103*03ce13f7SAndroid Build Coastguard Worker Pointer<Int> a = Pointer<Int>(function.Arg<1>());
104*03ce13f7SAndroid Build Coastguard Worker
105*03ce13f7SAndroid Build Coastguard Worker SIMD::Int x = *Pointer<SIMD::Int>(a);
106*03ce13f7SAndroid Build Coastguard Worker SIMD::Int y = *Pointer<SIMD::Int>(r);
107*03ce13f7SAndroid Build Coastguard Worker
108*03ce13f7SAndroid Build Coastguard Worker x -= y;
109*03ce13f7SAndroid Build Coastguard Worker
110*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < SIMD::Width / 4; i++)
111*03ce13f7SAndroid Build Coastguard Worker {
112*03ce13f7SAndroid Build Coastguard Worker y = Insert128(y, Extract128(x, i) << (i + 1), i);
113*03ce13f7SAndroid Build Coastguard Worker }
114*03ce13f7SAndroid Build Coastguard Worker
115*03ce13f7SAndroid Build Coastguard Worker *Pointer<SIMD::Int>(r) = y;
116*03ce13f7SAndroid Build Coastguard Worker }
117*03ce13f7SAndroid Build Coastguard Worker
118*03ce13f7SAndroid Build Coastguard Worker auto routine = function(testName().c_str());
119*03ce13f7SAndroid Build Coastguard Worker
120*03ce13f7SAndroid Build Coastguard Worker std::vector<int> r(SIMD::Width);
121*03ce13f7SAndroid Build Coastguard Worker std::vector<int> a(SIMD::Width);
122*03ce13f7SAndroid Build Coastguard Worker
123*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < SIMD::Width; i++)
124*03ce13f7SAndroid Build Coastguard Worker {
125*03ce13f7SAndroid Build Coastguard Worker r[i] = 0;
126*03ce13f7SAndroid Build Coastguard Worker a[i] = 1 + i;
127*03ce13f7SAndroid Build Coastguard Worker }
128*03ce13f7SAndroid Build Coastguard Worker
129*03ce13f7SAndroid Build Coastguard Worker routine(r.data(), a.data());
130*03ce13f7SAndroid Build Coastguard Worker
131*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < SIMD::Width; i++)
132*03ce13f7SAndroid Build Coastguard Worker {
133*03ce13f7SAndroid Build Coastguard Worker ASSERT_EQ(r[i], a[i] << (i / 4 + 1));
134*03ce13f7SAndroid Build Coastguard Worker }
135*03ce13f7SAndroid Build Coastguard Worker }
136*03ce13f7SAndroid Build Coastguard Worker
TEST(ReactorSIMD,Intrinsics_Scatter)137*03ce13f7SAndroid Build Coastguard Worker TEST(ReactorSIMD, Intrinsics_Scatter)
138*03ce13f7SAndroid Build Coastguard Worker {
139*03ce13f7SAndroid Build Coastguard Worker Function<Void(Pointer<Float> base, Pointer<SIMD::Float> val, Pointer<SIMD::Int> offsets)> function;
140*03ce13f7SAndroid Build Coastguard Worker {
141*03ce13f7SAndroid Build Coastguard Worker Pointer<Float> base = function.Arg<0>();
142*03ce13f7SAndroid Build Coastguard Worker Pointer<SIMD::Float> val = function.Arg<1>();
143*03ce13f7SAndroid Build Coastguard Worker Pointer<SIMD::Int> offsets = function.Arg<2>();
144*03ce13f7SAndroid Build Coastguard Worker
145*03ce13f7SAndroid Build Coastguard Worker SIMD::Int mask = ~0;
146*03ce13f7SAndroid Build Coastguard Worker unsigned int alignment = 1;
147*03ce13f7SAndroid Build Coastguard Worker Scatter(base, *val, *offsets, mask, alignment);
148*03ce13f7SAndroid Build Coastguard Worker }
149*03ce13f7SAndroid Build Coastguard Worker
150*03ce13f7SAndroid Build Coastguard Worker std::vector<float> buffer(10 + 10 * SIMD::Width);
151*03ce13f7SAndroid Build Coastguard Worker std::vector<int> offsets(SIMD::Width);
152*03ce13f7SAndroid Build Coastguard Worker std::vector<float> val(SIMD::Width);
153*03ce13f7SAndroid Build Coastguard Worker
154*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < SIMD::Width; i++)
155*03ce13f7SAndroid Build Coastguard Worker {
156*03ce13f7SAndroid Build Coastguard Worker offsets[i] = (3 + 7 * i) * sizeof(float);
157*03ce13f7SAndroid Build Coastguard Worker val[i] = 13.0f + 17.0f * i;
158*03ce13f7SAndroid Build Coastguard Worker }
159*03ce13f7SAndroid Build Coastguard Worker
160*03ce13f7SAndroid Build Coastguard Worker auto routine = function(testName().c_str());
161*03ce13f7SAndroid Build Coastguard Worker auto entry = (void (*)(float *, float *, int *))routine->getEntry();
162*03ce13f7SAndroid Build Coastguard Worker
163*03ce13f7SAndroid Build Coastguard Worker entry(buffer.data(), val.data(), offsets.data());
164*03ce13f7SAndroid Build Coastguard Worker
165*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < SIMD::Width; i++)
166*03ce13f7SAndroid Build Coastguard Worker {
167*03ce13f7SAndroid Build Coastguard Worker EXPECT_EQ(buffer[offsets[i] / sizeof(float)], val[i]);
168*03ce13f7SAndroid Build Coastguard Worker }
169*03ce13f7SAndroid Build Coastguard Worker }
170*03ce13f7SAndroid Build Coastguard Worker
TEST(ReactorSIMD,Intrinsics_Gather)171*03ce13f7SAndroid Build Coastguard Worker TEST(ReactorSIMD, Intrinsics_Gather)
172*03ce13f7SAndroid Build Coastguard Worker {
173*03ce13f7SAndroid Build Coastguard Worker Function<Void(Pointer<Float> base, Pointer<SIMD::Int> offsets, Pointer<SIMD::Float> result)> function;
174*03ce13f7SAndroid Build Coastguard Worker {
175*03ce13f7SAndroid Build Coastguard Worker Pointer<Float> base = function.Arg<0>();
176*03ce13f7SAndroid Build Coastguard Worker Pointer<SIMD::Int> offsets = function.Arg<1>();
177*03ce13f7SAndroid Build Coastguard Worker Pointer<SIMD::Float> result = function.Arg<2>();
178*03ce13f7SAndroid Build Coastguard Worker
179*03ce13f7SAndroid Build Coastguard Worker SIMD::Int mask = ~0;
180*03ce13f7SAndroid Build Coastguard Worker unsigned int alignment = 1;
181*03ce13f7SAndroid Build Coastguard Worker bool zeroMaskedLanes = true;
182*03ce13f7SAndroid Build Coastguard Worker *result = Gather(base, *offsets, mask, alignment, zeroMaskedLanes);
183*03ce13f7SAndroid Build Coastguard Worker }
184*03ce13f7SAndroid Build Coastguard Worker
185*03ce13f7SAndroid Build Coastguard Worker std::vector<float> buffer(10 + 10 * SIMD::Width);
186*03ce13f7SAndroid Build Coastguard Worker std::vector<int> offsets(SIMD::Width);
187*03ce13f7SAndroid Build Coastguard Worker
188*03ce13f7SAndroid Build Coastguard Worker std::vector<float> val(SIMD::Width);
189*03ce13f7SAndroid Build Coastguard Worker
190*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < SIMD::Width; i++)
191*03ce13f7SAndroid Build Coastguard Worker {
192*03ce13f7SAndroid Build Coastguard Worker offsets[i] = (3 + 7 * i) * sizeof(float);
193*03ce13f7SAndroid Build Coastguard Worker val[i] = 13.0f + 17.0f * i;
194*03ce13f7SAndroid Build Coastguard Worker
195*03ce13f7SAndroid Build Coastguard Worker buffer[offsets[i] / sizeof(float)] = val[i];
196*03ce13f7SAndroid Build Coastguard Worker }
197*03ce13f7SAndroid Build Coastguard Worker
198*03ce13f7SAndroid Build Coastguard Worker auto routine = function(testName().c_str());
199*03ce13f7SAndroid Build Coastguard Worker auto entry = (void (*)(float *, int *, float *))routine->getEntry();
200*03ce13f7SAndroid Build Coastguard Worker
201*03ce13f7SAndroid Build Coastguard Worker std::vector<float> result(SIMD::Width);
202*03ce13f7SAndroid Build Coastguard Worker entry(buffer.data(), offsets.data(), result.data());
203*03ce13f7SAndroid Build Coastguard Worker
204*03ce13f7SAndroid Build Coastguard Worker for(int i = 0; i < SIMD::Width; i++)
205*03ce13f7SAndroid Build Coastguard Worker {
206*03ce13f7SAndroid Build Coastguard Worker EXPECT_EQ(result[i], val[i]);
207*03ce13f7SAndroid Build Coastguard Worker }
208*03ce13f7SAndroid Build Coastguard Worker }
209