xref: /aosp_15_r20/external/swiftshader/third_party/SPIRV-Tools/test/ext_inst.opencl_test.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 // Copyright (c) 2015-2016 The Khronos Group Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <string>
16 #include <vector>
17 
18 #include "gmock/gmock.h"
19 #include "source/latest_version_opencl_std_header.h"
20 #include "source/util/string_utils.h"
21 #include "test/test_fixture.h"
22 #include "test/unit_spirv.h"
23 
24 namespace spvtools {
25 namespace {
26 
27 using spvtest::Concatenate;
28 using spvtest::MakeInstruction;
29 using utils::MakeVector;
30 using spvtest::TextToBinaryTest;
31 using testing::Eq;
32 
33 struct InstructionCase {
34   uint32_t opcode;
35   std::string name;
36   std::string operands;
37   std::vector<uint32_t> expected_operands;
38 };
39 
40 using ExtInstOpenCLStdRoundTripTest =
41     spvtest::TextToBinaryTestBase<::testing::TestWithParam<InstructionCase>>;
42 
TEST_P(ExtInstOpenCLStdRoundTripTest,ParameterizedExtInst)43 TEST_P(ExtInstOpenCLStdRoundTripTest, ParameterizedExtInst) {
44   // This example should not validate.
45   const std::string input =
46       "%1 = OpExtInstImport \"OpenCL.std\"\n"
47       "%3 = OpExtInst %2 %1 " +
48       GetParam().name + " " + GetParam().operands + "\n";
49   // First make sure it assembles correctly.
50   EXPECT_THAT(CompiledInstructions(input),
51               Eq(Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
52                                               MakeVector("OpenCL.std")),
53                               MakeInstruction(spv::Op::OpExtInst,
54                                               {2, 3, 1, GetParam().opcode},
55                                               GetParam().expected_operands)})))
56       << input;
57   // Now check the round trip through the disassembler.
58   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
59 }
60 
61 #define CASE1(Enum, Name)                                      \
62   {                                                            \
63     uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4", { 4 } \
64   }
65 #define CASE2(Enum, Name)                                            \
66   {                                                                  \
67     uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5", { 4, 5 } \
68   }
69 #define CASE3(Enum, Name)                                                  \
70   {                                                                        \
71     uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6", { 4, 5, 6 } \
72   }
73 #define CASE4(Enum, Name)                                           \
74   {                                                                 \
75     uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6 %7", { \
76       4, 5, 6, 7                                                    \
77     }                                                               \
78   }
79 #define CASE2Lit(Enum, Name, LiteralNumber)                                   \
80   {                                                                           \
81     uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 " #LiteralNumber, { \
82       4, 5, LiteralNumber                                                     \
83     }                                                                         \
84   }
85 #define CASE3Round(Enum, Name, Mode)                                    \
86   {                                                                     \
87     uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6 " #Mode, { \
88       4, 5, 6, uint32_t(spv::FPRoundingMode::Mode)                      \
89     }                                                                   \
90   }
91 
92 // clang-format off
93 // OpenCL.std: 2.1 Math extended instructions
94 INSTANTIATE_TEST_SUITE_P(
95     OpenCLMath, ExtInstOpenCLStdRoundTripTest,
96     ::testing::ValuesIn(std::vector<InstructionCase>({
97         // We are only testing the correctness of encoding and decoding here.
98         // Semantic correctness should be the responsibility of validator.
99         CASE1(Acos, acos), // enum value 0
100         CASE1(Acosh, acosh),
101         CASE1(Acospi, acospi),
102         CASE1(Asin, asin),
103         CASE1(Asinh, asinh),
104         CASE1(Asinh, asinh),
105         CASE1(Asinpi, asinpi),
106         CASE1(Atan, atan),
107         CASE2(Atan2, atan2),
108         CASE1(Atanh, atanh),
109         CASE1(Atanpi, atanpi),
110         CASE2(Atan2pi, atan2pi),
111         CASE1(Cbrt, cbrt),
112         CASE1(Ceil, ceil),
113         CASE1(Ceil, ceil),
114         CASE2(Copysign, copysign),
115         CASE1(Cos, cos),
116         CASE1(Cosh, cosh),
117         CASE1(Cospi, cospi),
118         CASE1(Erfc, erfc),
119         CASE1(Erf, erf),
120         CASE1(Exp, exp),
121         CASE1(Exp2, exp2),
122         CASE1(Exp10, exp10),
123         CASE1(Expm1, expm1),
124         CASE1(Fabs, fabs),
125         CASE2(Fdim, fdim),
126         CASE1(Floor, floor),
127         CASE3(Fma, fma),
128         CASE2(Fmax, fmax),
129         CASE2(Fmin, fmin),
130         CASE2(Fmod, fmod),
131         CASE2(Fract, fract),
132         CASE2(Frexp, frexp),
133         CASE2(Hypot, hypot),
134         CASE1(Ilogb, ilogb),
135         CASE2(Ldexp, ldexp),
136         CASE1(Lgamma, lgamma),
137         CASE2(Lgamma_r, lgamma_r),
138         CASE1(Log, log),
139         CASE1(Log2, log2),
140         CASE1(Log10, log10),
141         CASE1(Log1p, log1p),
142         CASE3(Mad, mad),
143         CASE2(Maxmag, maxmag),
144         CASE2(Minmag, minmag),
145         CASE2(Modf, modf),
146         CASE1(Nan, nan),
147         CASE2(Nextafter, nextafter),
148         CASE2(Pow, pow),
149         CASE2(Pown, pown),
150         CASE2(Powr, powr),
151         CASE2(Remainder, remainder),
152         CASE3(Remquo, remquo),
153         CASE1(Rint, rint),
154         CASE2(Rootn, rootn),
155         CASE1(Round, round),
156         CASE1(Rsqrt, rsqrt),
157         CASE1(Sin, sin),
158         CASE2(Sincos, sincos),
159         CASE1(Sinh, sinh),
160         CASE1(Sinpi, sinpi),
161         CASE1(Sqrt, sqrt),
162         CASE1(Tan, tan),
163         CASE1(Tanh, tanh),
164         CASE1(Tanpi, tanpi),
165         CASE1(Tgamma, tgamma),
166         CASE1(Trunc, trunc),
167         CASE1(Half_cos, half_cos),
168         CASE2(Half_divide, half_divide),
169         CASE1(Half_exp, half_exp),
170         CASE1(Half_exp2, half_exp2),
171         CASE1(Half_exp10, half_exp10),
172         CASE1(Half_log, half_log),
173         CASE1(Half_log2, half_log2),
174         CASE1(Half_log10, half_log10),
175         CASE2(Half_powr, half_powr),
176         CASE1(Half_recip, half_recip),
177         CASE1(Half_rsqrt, half_rsqrt),
178         CASE1(Half_sin, half_sin),
179         CASE1(Half_sqrt, half_sqrt),
180         CASE1(Half_tan, half_tan),
181         CASE1(Native_cos, native_cos),
182         CASE2(Native_divide, native_divide),
183         CASE1(Native_exp, native_exp),
184         CASE1(Native_exp2, native_exp2),
185         CASE1(Native_exp10, native_exp10),
186         CASE1(Native_log, native_log),
187         CASE1(Native_log10, native_log10),
188         CASE2(Native_powr, native_powr),
189         CASE1(Native_recip, native_recip),
190         CASE1(Native_rsqrt, native_rsqrt),
191         CASE1(Native_sin, native_sin),
192         CASE1(Native_sqrt, native_sqrt),
193         CASE1(Native_tan, native_tan), // enum value 94
194     })));
195 
196 // OpenCL.std: 2.1 Integer instructions
197 INSTANTIATE_TEST_SUITE_P(
198     OpenCLInteger, ExtInstOpenCLStdRoundTripTest,
199     ::testing::ValuesIn(std::vector<InstructionCase>({
200         CASE1(SAbs, s_abs), // enum value 141
201         CASE2(SAbs_diff, s_abs_diff),
202         CASE2(SAdd_sat, s_add_sat),
203         CASE2(UAdd_sat, u_add_sat),
204         CASE2(SHadd, s_hadd),
205         CASE2(UHadd, u_hadd),
206         CASE2(SRhadd, s_rhadd),
207         CASE2(SRhadd, s_rhadd),
208         CASE3(SClamp, s_clamp),
209         CASE3(UClamp, u_clamp),
210         CASE1(Clz, clz),
211         CASE1(Ctz, ctz),
212         CASE3(SMad_hi, s_mad_hi),
213         CASE3(UMad_sat, u_mad_sat),
214         CASE3(SMad_sat, s_mad_sat),
215         CASE2(SMax, s_max),
216         CASE2(UMax, u_max),
217         CASE2(SMin, s_min),
218         CASE2(UMin, u_min),
219         CASE2(SMul_hi, s_mul_hi),
220         CASE2(Rotate, rotate),
221         CASE2(SSub_sat, s_sub_sat),
222         CASE2(USub_sat, u_sub_sat),
223         CASE2(U_Upsample, u_upsample),
224         CASE2(S_Upsample, s_upsample),
225         CASE1(Popcount, popcount),
226         CASE3(SMad24, s_mad24),
227         CASE3(UMad24, u_mad24),
228         CASE2(SMul24, s_mul24),
229         CASE2(UMul24, u_mul24), // enum value 170
230         CASE1(UAbs, u_abs), // enum value 201
231         CASE2(UAbs_diff, u_abs_diff),
232         CASE2(UMul_hi, u_mul_hi),
233         CASE3(UMad_hi, u_mad_hi), // enum value 204
234     })));
235 
236 // OpenCL.std: 2.3 Common instructions
237 INSTANTIATE_TEST_SUITE_P(
238     OpenCLCommon, ExtInstOpenCLStdRoundTripTest,
239     ::testing::ValuesIn(std::vector<InstructionCase>({
240         CASE3(FClamp, fclamp), // enum value 95
241         CASE1(Degrees, degrees),
242         CASE2(FMax_common, fmax_common),
243         CASE2(FMin_common, fmin_common),
244         CASE3(Mix, mix),
245         CASE1(Radians, radians),
246         CASE2(Step, step),
247         CASE3(Smoothstep, smoothstep),
248         CASE1(Sign, sign), // enum value 103
249     })));
250 
251 // OpenCL.std: 2.4 Geometric instructions
252 INSTANTIATE_TEST_SUITE_P(
253     OpenCLGeometric, ExtInstOpenCLStdRoundTripTest,
254     ::testing::ValuesIn(std::vector<InstructionCase>({
255         CASE2(Cross, cross), // enum value 104
256         CASE2(Distance, distance),
257         CASE1(Length, length),
258         CASE1(Normalize, normalize),
259         CASE2(Fast_distance, fast_distance),
260         CASE1(Fast_length, fast_length),
261         CASE1(Fast_normalize, fast_normalize), // enum value 110
262     })));
263 
264 // OpenCL.std: 2.5 Relational instructions
265 INSTANTIATE_TEST_SUITE_P(
266     OpenCLRelational, ExtInstOpenCLStdRoundTripTest,
267     ::testing::ValuesIn(std::vector<InstructionCase>({
268         CASE3(Bitselect, bitselect), // enum value 186
269         CASE3(Select, select), // enum value 187
270     })));
271 
272 // OpenCL.std: 2.6 Vector data load and store instructions
273 INSTANTIATE_TEST_SUITE_P(
274     OpenCLVectorLoadStore, ExtInstOpenCLStdRoundTripTest,
275     ::testing::ValuesIn(std::vector<InstructionCase>({
276         // The last argument to Vloadn must be one of 2, 3, 4, 8, 16.
277         CASE2Lit(Vloadn, vloadn, 2),
278         CASE2Lit(Vloadn, vloadn, 3),
279         CASE2Lit(Vloadn, vloadn, 4),
280         CASE2Lit(Vloadn, vloadn, 8),
281         CASE2Lit(Vloadn, vloadn, 16),
282         CASE3(Vstoren, vstoren),
283         CASE2(Vload_half, vload_half),
284         CASE2Lit(Vload_halfn, vload_halfn, 2),
285         CASE2Lit(Vload_halfn, vload_halfn, 3),
286         CASE2Lit(Vload_halfn, vload_halfn, 4),
287         CASE2Lit(Vload_halfn, vload_halfn, 8),
288         CASE2Lit(Vload_halfn, vload_halfn, 16),
289         CASE3(Vstore_half, vstore_half),
290         // Try all the rounding modes.
291         CASE3Round(Vstore_half_r, vstore_half_r, RTE),
292         CASE3Round(Vstore_half_r, vstore_half_r, RTZ),
293         CASE3Round(Vstore_half_r, vstore_half_r, RTP),
294         CASE3Round(Vstore_half_r, vstore_half_r, RTN),
295         CASE3(Vstore_halfn, vstore_halfn),
296         CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTE),
297         CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTZ),
298         CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTP),
299         CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTN),
300         CASE2Lit(Vloada_halfn, vloada_halfn, 2),
301         CASE2Lit(Vloada_halfn, vloada_halfn, 3),
302         CASE2Lit(Vloada_halfn, vloada_halfn, 4),
303         CASE2Lit(Vloada_halfn, vloada_halfn, 8),
304         CASE2Lit(Vloada_halfn, vloada_halfn, 16),
305         CASE3(Vstorea_halfn, vstorea_halfn),
306         CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTE),
307         CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTZ),
308         CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTP),
309         CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTN),
310     })));
311 
312 // OpenCL.std: 2.7 Miscellaneous vector instructions
313 INSTANTIATE_TEST_SUITE_P(
314     OpenCLMiscellaneousVector, ExtInstOpenCLStdRoundTripTest,
315     ::testing::ValuesIn(std::vector<InstructionCase>({
316         CASE2(Shuffle, shuffle),
317         CASE3(Shuffle2, shuffle2),
318     })));
319 
320 // OpenCL.std: 2.8 Miscellaneous instructions
321 
322 #define PREFIX uint32_t(OpenCLLIB::Entrypoints::Printf), "printf"
323 INSTANTIATE_TEST_SUITE_P(
324     OpenCLMiscPrintf, ExtInstOpenCLStdRoundTripTest,
325     ::testing::ValuesIn(std::vector<InstructionCase>({
326       // Printf is interesting because it takes a variable number of arguments.
327       // Start with zero optional arguments.
328       {PREFIX, "%4", {4}},
329       {PREFIX, "%4 %5", {4, 5}},
330       {PREFIX, "%4 %5 %6", {4, 5, 6}},
331       {PREFIX, "%4 %5 %6 %7", {4, 5, 6, 7}},
332       {PREFIX, "%4 %5 %6 %7 %8", {4, 5, 6, 7, 8}},
333       {PREFIX, "%4 %5 %6 %7 %8 %9", {4, 5, 6, 7, 8, 9}},
334       {PREFIX, "%4 %5 %6 %7 %8 %9 %10", {4, 5, 6, 7, 8, 9, 10}},
335       {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11", {4, 5, 6, 7, 8, 9, 10, 11}},
336       {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12",
337         {4, 5, 6, 7, 8, 9, 10, 11, 12}},
338       {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12 %13",
339         {4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
340       {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14",
341         {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}},
342     })));
343 #undef PREFIX
344 
345 INSTANTIATE_TEST_SUITE_P(
346     OpenCLMiscPrefetch, ExtInstOpenCLStdRoundTripTest,
347     ::testing::ValuesIn(std::vector<InstructionCase>({
348         CASE2(Prefetch, prefetch),
349     })));
350 
351 // OpenCL.std: 2.9.1 Image encoding
352 // No new instructions defined in this section.
353 
354 // OpenCL.std: 2.9.2 Sampler encoding
355 // No new instructions defined in this section.
356 
357 // OpenCL.std: 2.9.3 Image read
358 // No new instructions defined in this section.
359 // Use core instruction OpImageSampleExplicitLod instead.
360 
361 // OpenCL.std: 2.9.4 Image write
362 // No new instructions defined in this section.
363 
364 // clang-format on
365 
366 #undef CASE1
367 #undef CASE2
368 #undef CASE3
369 #undef CASE4
370 #undef CASE2Lit
371 #undef CASE3Round
372 
373 }  // namespace
374 }  // namespace spvtools
375