xref: /aosp_15_r20/external/swiftshader/tests/ReactorUnitTests/ReactorSIMD.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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