1 // Copyright (c) 2015-2016 The Khronos Group Inc.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include "unit_spirv.h"
17 #include <gmock/gmock.h>
18 #include "test_fixture.h"
19 #include "spirv/1.0/OpenCL.std.h"
23 using spvtest::Concatenate;
24 using spvtest::MakeInstruction;
25 using spvtest::MakeVector;
26 using spvtest::TextToBinaryTest;
29 struct InstructionCase {
33 std::vector<uint32_t> expected_operands;
36 using ExtInstOpenCLStdRoundTripTest =
37 spvtest::TextToBinaryTestBase<::testing::TestWithParam<InstructionCase>>;
39 TEST_P(ExtInstOpenCLStdRoundTripTest, ParameterizedExtInst) {
40 // This example should not validate.
41 const std::string input =
42 "%1 = OpExtInstImport \"OpenCL.std\"\n"
43 "%3 = OpExtInst %2 %1 " +
44 GetParam().name + " " + GetParam().operands + "\n";
45 // First make sure it assembles correctly.
47 CompiledInstructions(input),
49 {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("OpenCL.std")),
50 MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode},
51 GetParam().expected_operands)})))
53 // Now check the round trip through the disassembler.
54 EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
57 #define CASE1(Enum, Name) \
59 uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4", { 4 } \
61 #define CASE2(Enum, Name) \
63 uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5", { 4, 5 } \
65 #define CASE3(Enum, Name) \
67 uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6", { 4, 5, 6 } \
69 #define CASE4(Enum, Name) \
71 uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6 %7", { \
75 #define CASE2Lit(Enum, Name, LiteralNumber) \
77 uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 " #LiteralNumber, { \
81 #define CASE3Round(Enum, Name, Mode) \
83 uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6 " #Mode, { \
84 4, 5, 6, uint32_t(SpvFPRoundingMode##Mode) \
89 // OpenCL.std: 2.1 Math extended instructions
90 INSTANTIATE_TEST_CASE_P(
91 OpenCLMath, ExtInstOpenCLStdRoundTripTest,
92 ::testing::ValuesIn(std::vector<InstructionCase>({
93 // We are only testing the correctness of encoding and decoding here.
94 // Semantic correctness should be the responsibility of validator.
95 CASE1(Acos, acos), // enum value 0
97 CASE1(Acospi, acospi),
101 CASE1(Asinpi, asinpi),
105 CASE1(Atanpi, atanpi),
106 CASE2(Atan2pi, atan2pi),
110 CASE2(Copysign, copysign),
132 CASE1(Lgamma, lgamma),
133 CASE2(Lgamma_r, lgamma_r),
139 CASE2(Maxmag, maxmag),
140 CASE2(Minmag, minmag),
143 CASE2(Nextafter, nextafter),
147 CASE2(Remainder, remainder),
148 CASE3(Remquo, remquo),
154 CASE2(Sincos, sincos),
161 CASE1(Tgamma, tgamma),
163 CASE1(Half_cos, half_cos),
164 CASE2(Half_divide, half_divide),
165 CASE1(Half_exp, half_exp),
166 CASE1(Half_exp2, half_exp2),
167 CASE1(Half_exp10, half_exp10),
168 CASE1(Half_log, half_log),
169 CASE1(Half_log2, half_log2),
170 CASE1(Half_log10, half_log10),
171 CASE2(Half_powr, half_powr),
172 CASE1(Half_recip, half_recip),
173 CASE1(Half_rsqrt, half_rsqrt),
174 CASE1(Half_sin, half_sin),
175 CASE1(Half_sqrt, half_sqrt),
176 CASE1(Half_tan, half_tan),
177 CASE1(Native_cos, native_cos),
178 CASE2(Native_divide, native_divide),
179 CASE1(Native_exp, native_exp),
180 CASE1(Native_exp2, native_exp2),
181 CASE1(Native_exp10, native_exp10),
182 CASE1(Native_log, native_log),
183 CASE1(Native_log10, native_log10),
184 CASE2(Native_powr, native_powr),
185 CASE1(Native_recip, native_recip),
186 CASE1(Native_rsqrt, native_rsqrt),
187 CASE1(Native_sin, native_sin),
188 CASE1(Native_sqrt, native_sqrt),
189 CASE1(Native_tan, native_tan), // enum value 94
192 // OpenCL.std: 2.1 Integer instructions
193 INSTANTIATE_TEST_CASE_P(
194 OpenCLInteger, ExtInstOpenCLStdRoundTripTest,
195 ::testing::ValuesIn(std::vector<InstructionCase>({
196 CASE1(SAbs, s_abs), // enum value 141
197 CASE2(SAbs_diff, s_abs_diff),
198 CASE2(SAdd_sat, s_add_sat),
199 CASE2(UAdd_sat, u_add_sat),
200 CASE2(SHadd, s_hadd),
201 CASE2(UHadd, u_hadd),
202 CASE2(SRhadd, s_rhadd),
203 CASE2(SRhadd, s_rhadd),
204 CASE3(SClamp, s_clamp),
205 CASE3(UClamp, u_clamp),
208 CASE3(SMad_hi, s_mad_hi),
209 CASE3(UMad_sat, u_mad_sat),
210 CASE3(SMad_sat, s_mad_sat),
215 CASE2(SMul_hi, s_mul_hi),
216 CASE2(Rotate, rotate),
217 CASE2(SSub_sat, s_sub_sat),
218 CASE2(USub_sat, u_sub_sat),
219 CASE2(U_Upsample, u_upsample),
220 CASE2(S_Upsample, s_upsample),
221 CASE1(Popcount, popcount),
222 CASE3(SMad24, s_mad24),
223 CASE3(UMad24, u_mad24),
224 CASE2(SMul24, s_mul24),
225 CASE2(UMul24, u_mul24), // enum value 170
226 CASE1(UAbs, u_abs), // enum value 201
227 CASE2(UAbs_diff, u_abs_diff),
228 CASE2(UMul_hi, u_mul_hi),
229 CASE3(UMad_hi, u_mad_hi), // enum value 204
232 // OpenCL.std: 2.3 Common instrucitons
233 INSTANTIATE_TEST_CASE_P(
234 OpenCLCommon, ExtInstOpenCLStdRoundTripTest,
235 ::testing::ValuesIn(std::vector<InstructionCase>({
236 CASE3(FClamp, fclamp), // enum value 95
237 CASE1(Degrees, degrees),
238 CASE2(FMax_common, fmax_common),
239 CASE2(FMin_common, fmin_common),
241 CASE1(Radians, radians),
243 CASE3(Smoothstep, smoothstep),
244 CASE1(Sign, sign), // enum value 103
247 // OpenCL.std: 2.4 Geometric instructions
248 INSTANTIATE_TEST_CASE_P(
249 OpenCLGeometric, ExtInstOpenCLStdRoundTripTest,
250 ::testing::ValuesIn(std::vector<InstructionCase>({
251 CASE2(Cross, cross), // enum value 104
252 CASE2(Distance, distance),
253 CASE1(Length, length),
254 CASE1(Normalize, normalize),
255 CASE2(Fast_distance, fast_distance),
256 CASE1(Fast_length, fast_length),
257 CASE1(Fast_normalize, fast_normalize), // enum value 110
260 // OpenCL.std: 2.5 Relational instructions
261 INSTANTIATE_TEST_CASE_P(
262 OpenCLRelational, ExtInstOpenCLStdRoundTripTest,
263 ::testing::ValuesIn(std::vector<InstructionCase>({
264 CASE3(Bitselect, bitselect), // enum value 186
265 CASE3(Select, select), // enum value 187
268 // OpenCL.std: 2.6 Vector data load and store instructions
269 INSTANTIATE_TEST_CASE_P(
270 OpenCLVectorLoadStore, ExtInstOpenCLStdRoundTripTest,
271 ::testing::ValuesIn(std::vector<InstructionCase>({
272 // The last argument to Vloadn must be one of 2, 3, 4, 8, 16.
273 CASE2Lit(Vloadn, vloadn, 2),
274 CASE2Lit(Vloadn, vloadn, 3),
275 CASE2Lit(Vloadn, vloadn, 4),
276 CASE2Lit(Vloadn, vloadn, 8),
277 CASE2Lit(Vloadn, vloadn, 16),
278 CASE3(Vstoren, vstoren),
279 CASE2(Vload_half, vload_half),
280 CASE2Lit(Vload_halfn, vload_halfn, 2),
281 CASE2Lit(Vload_halfn, vload_halfn, 3),
282 CASE2Lit(Vload_halfn, vload_halfn, 4),
283 CASE2Lit(Vload_halfn, vload_halfn, 8),
284 CASE2Lit(Vload_halfn, vload_halfn, 16),
285 CASE3(Vstore_half, vstore_half),
286 // Try all the rounding modes.
287 CASE3Round(Vstore_half_r, vstore_half_r, RTE),
288 CASE3Round(Vstore_half_r, vstore_half_r, RTZ),
289 CASE3Round(Vstore_half_r, vstore_half_r, RTP),
290 CASE3Round(Vstore_half_r, vstore_half_r, RTN),
291 CASE3(Vstore_halfn, vstore_halfn),
292 CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTE),
293 CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTZ),
294 CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTP),
295 CASE3Round(Vstore_halfn_r, vstore_halfn_r, RTN),
296 CASE2Lit(Vloada_halfn, vloada_halfn, 2),
297 CASE2Lit(Vloada_halfn, vloada_halfn, 3),
298 CASE2Lit(Vloada_halfn, vloada_halfn, 4),
299 CASE2Lit(Vloada_halfn, vloada_halfn, 8),
300 CASE2Lit(Vloada_halfn, vloada_halfn, 16),
301 CASE3(Vstorea_halfn, vstorea_halfn),
302 CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTE),
303 CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTZ),
304 CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTP),
305 CASE3Round(Vstorea_halfn_r, vstorea_halfn_r, RTN),
308 // OpenCL.std: 2.7 Miscellaneous vector instructions
309 INSTANTIATE_TEST_CASE_P(
310 OpenCLMiscellaneousVector, ExtInstOpenCLStdRoundTripTest,
311 ::testing::ValuesIn(std::vector<InstructionCase>({
312 CASE2(Shuffle, shuffle),
313 CASE3(Shuffle2, shuffle2),
316 // OpenCL.std: 2.8 Miscellaneous instructions
318 #define PREFIX uint32_t(OpenCLLIB::Entrypoints::Printf), "printf"
319 INSTANTIATE_TEST_CASE_P(
320 OpenCLMiscPrintf, ExtInstOpenCLStdRoundTripTest,
321 ::testing::ValuesIn(std::vector<InstructionCase>({
322 // Printf is interesting because it takes a variable number of arguments.
323 // Start with zero optional arguments.
325 {PREFIX, "%4 %5", {4, 5}},
326 {PREFIX, "%4 %5 %6", {4, 5, 6}},
327 {PREFIX, "%4 %5 %6 %7", {4, 5, 6, 7}},
328 {PREFIX, "%4 %5 %6 %7 %8", {4, 5, 6, 7, 8}},
329 {PREFIX, "%4 %5 %6 %7 %8 %9", {4, 5, 6, 7, 8, 9}},
330 {PREFIX, "%4 %5 %6 %7 %8 %9 %10", {4, 5, 6, 7, 8, 9, 10}},
331 {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11", {4, 5, 6, 7, 8, 9, 10, 11}},
332 {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12",
333 {4, 5, 6, 7, 8, 9, 10, 11, 12}},
334 {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12 %13",
335 {4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
336 {PREFIX, "%4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14",
337 {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}},
341 INSTANTIATE_TEST_CASE_P(
342 OpenCLMiscPrefetch, ExtInstOpenCLStdRoundTripTest,
343 ::testing::ValuesIn(std::vector<InstructionCase>({
344 CASE2(Prefetch, prefetch),
347 // OpenCL.std: 2.9.1 Image encoding
348 // No new instructions defined in this section.
350 // OpenCL.std: 2.9.2 Sampler encoding
351 // No new instructions defined in this section.
353 // OpenCL.std: 2.9.3 Image read
354 // No new instructions defined in this section.
355 // Use core instruction OpImageSampleExplicitLod instead.
357 // OpenCL.std: 2.9.4 Image write
358 // No new instructions defined in this section.
369 } // anonymous namespace