compact_ids_test.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // Copyright (c) 2017 Google 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 <memory>
  15. #include <string>
  16. #include <vector>
  17. #include "gmock/gmock.h"
  18. #include "spirv-tools/libspirv.hpp"
  19. #include "spirv-tools/optimizer.hpp"
  20. #include "test/opt/pass_fixture.h"
  21. #include "test/opt/pass_utils.h"
  22. namespace spvtools {
  23. namespace opt {
  24. namespace {
  25. using CompactIdsTest = PassTest<::testing::Test>;
  26. TEST_F(CompactIdsTest, PassOff) {
  27. const std::string before =
  28. R"(OpCapability Addresses
  29. OpCapability Kernel
  30. OpCapability GenericPointer
  31. OpCapability Linkage
  32. OpMemoryModel Physical32 OpenCL
  33. %99 = OpTypeInt 32 0
  34. %10 = OpTypeVector %99 2
  35. %20 = OpConstant %99 2
  36. %30 = OpTypeArray %99 %20
  37. )";
  38. const std::string after = before;
  39. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  40. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  41. SinglePassRunAndCheck<NullPass>(before, after, false, false);
  42. }
  43. TEST_F(CompactIdsTest, PassOn) {
  44. const std::string before =
  45. R"(OpCapability Addresses
  46. OpCapability Kernel
  47. OpCapability GenericPointer
  48. OpCapability Linkage
  49. OpMemoryModel Physical32 OpenCL
  50. OpEntryPoint Kernel %3 "simple_kernel"
  51. %99 = OpTypeInt 32 0
  52. %10 = OpTypeVector %99 2
  53. %20 = OpConstant %99 2
  54. %30 = OpTypeArray %99 %20
  55. %40 = OpTypeVoid
  56. %50 = OpTypeFunction %40
  57. %3 = OpFunction %40 None %50
  58. %70 = OpLabel
  59. OpReturn
  60. OpFunctionEnd
  61. )";
  62. const std::string after =
  63. R"(OpCapability Addresses
  64. OpCapability Kernel
  65. OpCapability GenericPointer
  66. OpCapability Linkage
  67. OpMemoryModel Physical32 OpenCL
  68. OpEntryPoint Kernel %1 "simple_kernel"
  69. %2 = OpTypeInt 32 0
  70. %3 = OpTypeVector %2 2
  71. %4 = OpConstant %2 2
  72. %5 = OpTypeArray %2 %4
  73. %6 = OpTypeVoid
  74. %7 = OpTypeFunction %6
  75. %1 = OpFunction %6 None %7
  76. %8 = OpLabel
  77. OpReturn
  78. OpFunctionEnd
  79. )";
  80. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  81. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  82. SinglePassRunAndCheck<CompactIdsPass>(before, after, false, false);
  83. }
  84. TEST(CompactIds, InstructionResultIsUpdated) {
  85. // For https://github.com/KhronosGroup/SPIRV-Tools/issues/827
  86. // In that bug, the compact Ids pass was directly updating the result Id
  87. // word for an OpFunction instruction, but not updating the cached
  88. // result_id_ in that Instruction object.
  89. //
  90. // This test is a bit cheesy. We don't expose internal interfaces enough
  91. // to see the inconsistency. So reproduce the original scenario, with
  92. // compact ids followed by a pass that trips up on the inconsistency.
  93. const std::string input(R"(OpCapability Shader
  94. OpMemoryModel Logical Simple
  95. OpEntryPoint GLCompute %100 "main"
  96. %200 = OpTypeVoid
  97. %300 = OpTypeFunction %200
  98. %100 = OpFunction %200 None %300
  99. %400 = OpLabel
  100. OpReturn
  101. OpFunctionEnd
  102. )");
  103. std::vector<uint32_t> binary;
  104. const spv_target_env env = SPV_ENV_UNIVERSAL_1_0;
  105. spvtools::SpirvTools tools(env);
  106. auto assembled = tools.Assemble(
  107. input, &binary, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  108. EXPECT_TRUE(assembled);
  109. spvtools::Optimizer optimizer(env);
  110. optimizer.RegisterPass(CreateCompactIdsPass());
  111. // The exhaustive inliner will use the result_id
  112. optimizer.RegisterPass(CreateInlineExhaustivePass());
  113. // This should not crash!
  114. optimizer.Run(binary.data(), binary.size(), &binary);
  115. std::string disassembly;
  116. tools.Disassemble(binary, &disassembly, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  117. const std::string expected(R"(OpCapability Shader
  118. OpMemoryModel Logical Simple
  119. OpEntryPoint GLCompute %1 "main"
  120. %2 = OpTypeVoid
  121. %3 = OpTypeFunction %2
  122. %1 = OpFunction %2 None %3
  123. %4 = OpLabel
  124. OpReturn
  125. OpFunctionEnd
  126. )");
  127. EXPECT_THAT(disassembly, ::testing::Eq(expected));
  128. }
  129. TEST(CompactIds, HeaderIsUpdated) {
  130. const std::string input(R"(OpCapability Shader
  131. OpMemoryModel Logical Simple
  132. OpEntryPoint GLCompute %100 "main"
  133. %200 = OpTypeVoid
  134. %300 = OpTypeFunction %200
  135. %100 = OpFunction %200 None %300
  136. %400 = OpLabel
  137. OpReturn
  138. OpFunctionEnd
  139. )");
  140. std::vector<uint32_t> binary;
  141. const spv_target_env env = SPV_ENV_UNIVERSAL_1_0;
  142. spvtools::SpirvTools tools(env);
  143. auto assembled = tools.Assemble(
  144. input, &binary, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  145. EXPECT_TRUE(assembled);
  146. spvtools::Optimizer optimizer(env);
  147. optimizer.RegisterPass(CreateCompactIdsPass());
  148. // The exhaustive inliner will use the result_id
  149. optimizer.RegisterPass(CreateInlineExhaustivePass());
  150. // This should not crash!
  151. optimizer.Run(binary.data(), binary.size(), &binary);
  152. std::string disassembly;
  153. tools.Disassemble(binary, &disassembly, SPV_BINARY_TO_TEXT_OPTION_NONE);
  154. const std::string expected(R"(; SPIR-V
  155. ; Version: 1.0
  156. ; Generator: Khronos SPIR-V Tools Assembler; 0
  157. ; Bound: 5
  158. ; Schema: 0
  159. OpCapability Shader
  160. OpMemoryModel Logical Simple
  161. OpEntryPoint GLCompute %1 "main"
  162. %2 = OpTypeVoid
  163. %3 = OpTypeFunction %2
  164. %1 = OpFunction %2 None %3
  165. %4 = OpLabel
  166. OpReturn
  167. OpFunctionEnd
  168. )");
  169. EXPECT_THAT(disassembly, ::testing::Eq(expected));
  170. }
  171. // Test context consistency check after invalidating
  172. // CFG and others by compact IDs Pass.
  173. // Uses a GLSL shader with named labels for variety
  174. TEST(CompactIds, ConsistentCheck) {
  175. const std::string input(R"(OpCapability Shader
  176. OpMemoryModel Logical GLSL450
  177. OpEntryPoint Fragment %main "main" %in_var_A %out_var_SV_TARGET
  178. OpExecutionMode %main OriginUpperLeft
  179. OpSource HLSL 600
  180. OpName %main "main"
  181. OpName %in_var_A "in.var.A"
  182. OpName %out_var_SV_TARGET "out.var.SV_TARGET"
  183. OpDecorate %in_var_A Location 0
  184. OpDecorate %out_var_SV_TARGET Location 0
  185. %void = OpTypeVoid
  186. %3 = OpTypeFunction %void
  187. %float = OpTypeFloat 32
  188. %v4float = OpTypeVector %float 4
  189. %_ptr_Input_v4float = OpTypePointer Input %v4float
  190. %_ptr_Output_v4float = OpTypePointer Output %v4float
  191. %in_var_A = OpVariable %_ptr_Input_v4float Input
  192. %out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output
  193. %main = OpFunction %void None %3
  194. %5 = OpLabel
  195. %12 = OpLoad %v4float %in_var_A
  196. %23 = OpVectorShuffle %v4float %12 %12 0 0 0 1
  197. OpStore %out_var_SV_TARGET %23
  198. OpReturn
  199. OpFunctionEnd
  200. )");
  201. spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_1);
  202. std::unique_ptr<IRContext> context =
  203. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, input,
  204. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  205. ASSERT_NE(context, nullptr);
  206. CompactIdsPass compact_id_pass;
  207. context->BuildInvalidAnalyses(compact_id_pass.GetPreservedAnalyses());
  208. const auto status = compact_id_pass.Run(context.get());
  209. ASSERT_NE(status, Pass::Status::Failure);
  210. EXPECT_TRUE(context->IsConsistent());
  211. // Test output just in case
  212. std::vector<uint32_t> binary;
  213. context->module()->ToBinary(&binary, false);
  214. std::string disassembly;
  215. tools.Disassemble(binary, &disassembly,
  216. SpirvTools::kDefaultDisassembleOption);
  217. const std::string expected(R"(OpCapability Shader
  218. OpMemoryModel Logical GLSL450
  219. OpEntryPoint Fragment %main "main" %in_var_A %out_var_SV_TARGET
  220. OpExecutionMode %main OriginUpperLeft
  221. OpSource HLSL 600
  222. OpName %main "main"
  223. OpName %in_var_A "in.var.A"
  224. OpName %out_var_SV_TARGET "out.var.SV_TARGET"
  225. OpDecorate %in_var_A Location 0
  226. OpDecorate %out_var_SV_TARGET Location 0
  227. %void = OpTypeVoid
  228. %5 = OpTypeFunction %void
  229. %float = OpTypeFloat 32
  230. %v4float = OpTypeVector %float 4
  231. %_ptr_Input_v4float = OpTypePointer Input %v4float
  232. %_ptr_Output_v4float = OpTypePointer Output %v4float
  233. %in_var_A = OpVariable %_ptr_Input_v4float Input
  234. %out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output
  235. %main = OpFunction %void None %5
  236. %10 = OpLabel
  237. %11 = OpLoad %v4float %in_var_A
  238. %12 = OpVectorShuffle %v4float %11 %11 0 0 0 1
  239. OpStore %out_var_SV_TARGET %12
  240. OpReturn
  241. OpFunctionEnd
  242. )");
  243. EXPECT_THAT(disassembly, ::testing::Eq(expected));
  244. }
  245. } // namespace
  246. } // namespace opt
  247. } // namespace spvtools