ext_inst.opencl_test.cpp 14 KB

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