simplification_test.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // Copyright (c) 2018 Google LLC
  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 "gmock/gmock.h"
  16. #include "source/opt/simplification_pass.h"
  17. #include "test/opt/assembly_builder.h"
  18. #include "test/opt/pass_fixture.h"
  19. namespace spvtools {
  20. namespace opt {
  21. namespace {
  22. using SimplificationTest = PassTest<::testing::Test>;
  23. TEST_F(SimplificationTest, StraightLineTest) {
  24. // Testing that folding rules are combined in simple straight line code.
  25. const std::string text = R"(OpCapability Shader
  26. %1 = OpExtInstImport "GLSL.std.450"
  27. OpMemoryModel Logical GLSL450
  28. OpEntryPoint Fragment %main "main" %i %o
  29. OpExecutionMode %main OriginUpperLeft
  30. OpSource GLSL 430
  31. OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
  32. OpSourceExtension "GL_GOOGLE_include_directive"
  33. OpName %main "main"
  34. OpName %i "i"
  35. OpName %o "o"
  36. OpDecorate %i Flat
  37. OpDecorate %i Location 0
  38. OpDecorate %o Location 0
  39. %void = OpTypeVoid
  40. %8 = OpTypeFunction %void
  41. %int = OpTypeInt 32 1
  42. %v4int = OpTypeVector %int 4
  43. %int_0 = OpConstant %int 0
  44. %13 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
  45. %int_1 = OpConstant %int 1
  46. %_ptr_Input_v4int = OpTypePointer Input %v4int
  47. %i = OpVariable %_ptr_Input_v4int Input
  48. %_ptr_Output_int = OpTypePointer Output %int
  49. %o = OpVariable %_ptr_Output_int Output
  50. %main = OpFunction %void None %8
  51. %21 = OpLabel
  52. %31 = OpCompositeInsert %v4int %int_1 %13 0
  53. ; CHECK: [[load:%[a-zA-Z_\d]+]] = OpLoad
  54. %23 = OpLoad %v4int %i
  55. %33 = OpCompositeInsert %v4int %int_0 %23 0
  56. %35 = OpCompositeExtract %int %31 0
  57. ; CHECK: [[extract:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 1
  58. %37 = OpCompositeExtract %int %33 1
  59. ; CHECK: [[add:%[a-zA-Z_\d]+]] = OpIAdd %int %int_1 [[extract]]
  60. %29 = OpIAdd %int %35 %37
  61. OpStore %o %29
  62. OpReturn
  63. OpFunctionEnd
  64. )";
  65. SinglePassRunAndMatch<SimplificationPass>(text, false);
  66. }
  67. TEST_F(SimplificationTest, NewInstructionTest) {
  68. // Testing that new instructions are simplified. Specifically,
  69. // that the new add instruction generated by FactorAddMul is
  70. // further simplified by MergeGenericAddSub.
  71. const std::string text = R"(OpCapability Shader
  72. %1 = OpExtInstImport "GLSL.std.450"
  73. OpMemoryModel Logical GLSL450
  74. OpEntryPoint Fragment %main "main"
  75. OpExecutionMode %main OriginUpperLeft
  76. OpSource GLSL 430
  77. OpName %main "main"
  78. %void = OpTypeVoid
  79. %4 = OpTypeFunction %void
  80. %int = OpTypeInt 32 1
  81. %_ptr_int = OpTypePointer Function %int
  82. ; CHECK: [[mul:%[a-zA-Z_\d]+]] = OpIMul %int %13 %11
  83. %main = OpFunction %void None %4
  84. %7 = OpLabel
  85. %8 = OpVariable %_ptr_int Function
  86. %9 = OpVariable %_ptr_int Function
  87. %10 = OpVariable %_ptr_int Function
  88. %11 = OpLoad %int %8
  89. %12 = OpLoad %int %9
  90. %13 = OpLoad %int %10
  91. %14 = OpISub %int %11 %12
  92. %15 = OpIMul %int %13 %11
  93. %16 = OpIMul %int %13 %12
  94. %17 = OpIAdd %int %14 %15
  95. OpReturn
  96. OpFunctionEnd
  97. )";
  98. SinglePassRunAndMatch<SimplificationPass>(text, false);
  99. }
  100. TEST_F(SimplificationTest, AcrossBasicBlocks) {
  101. // Testing that folding rules are combined across basic blocks.
  102. const std::string text = R"(OpCapability Shader
  103. %1 = OpExtInstImport "GLSL.std.450"
  104. OpMemoryModel Logical GLSL450
  105. OpEntryPoint Fragment %main "main" %i %o
  106. OpExecutionMode %main OriginUpperLeft
  107. OpSource GLSL 430
  108. OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
  109. OpSourceExtension "GL_GOOGLE_include_directive"
  110. OpName %main "main"
  111. OpName %i "i"
  112. OpName %o "o"
  113. OpDecorate %i Flat
  114. OpDecorate %i Location 0
  115. OpDecorate %o Location 0
  116. %void = OpTypeVoid
  117. %8 = OpTypeFunction %void
  118. %int = OpTypeInt 32 1
  119. %v4int = OpTypeVector %int 4
  120. %int_0 = OpConstant %int 0
  121. %_ptr_Input_v4int = OpTypePointer Input %v4int
  122. %i = OpVariable %_ptr_Input_v4int Input
  123. %uint = OpTypeInt 32 0
  124. %uint_0 = OpConstant %uint 0
  125. %_ptr_Input_int = OpTypePointer Input %int
  126. %int_10 = OpConstant %int 10
  127. %bool = OpTypeBool
  128. %int_1 = OpConstant %int 1
  129. %_ptr_Output_int = OpTypePointer Output %int
  130. %o = OpVariable %_ptr_Output_int Output
  131. %main = OpFunction %void None %8
  132. %24 = OpLabel
  133. ; CHECK: [[load:%[a-zA-Z_\d]+]] = OpLoad %v4int %i
  134. %25 = OpLoad %v4int %i
  135. %41 = OpCompositeInsert %v4int %int_0 %25 0
  136. %27 = OpAccessChain %_ptr_Input_int %i %uint_0
  137. %28 = OpLoad %int %27
  138. %29 = OpSGreaterThan %bool %28 %int_10
  139. OpSelectionMerge %30 None
  140. OpBranchConditional %29 %31 %32
  141. %31 = OpLabel
  142. %43 = OpCopyObject %v4int %25
  143. OpBranch %30
  144. %32 = OpLabel
  145. %45 = OpCopyObject %v4int %25
  146. OpBranch %30
  147. %30 = OpLabel
  148. %50 = OpPhi %v4int %43 %31 %45 %32
  149. ; CHECK: [[extract1:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 0
  150. %47 = OpCompositeExtract %int %50 0
  151. ; CHECK: [[extract2:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 1
  152. %49 = OpCompositeExtract %int %41 1
  153. ; CHECK: [[add:%[a-zA-Z_\d]+]] = OpIAdd %int [[extract1]] [[extract2]]
  154. %39 = OpIAdd %int %47 %49
  155. OpStore %o %39
  156. OpReturn
  157. OpFunctionEnd
  158. )";
  159. SinglePassRunAndMatch<SimplificationPass>(text, false);
  160. }
  161. TEST_F(SimplificationTest, ThroughLoops) {
  162. // Testing that folding rules are applied multiple times to instructions
  163. // to be able to propagate across loop iterations.
  164. const std::string text = R"(
  165. OpCapability Shader
  166. %1 = OpExtInstImport "GLSL.std.450"
  167. OpMemoryModel Logical GLSL450
  168. OpEntryPoint Fragment %main "main" %o %i
  169. OpExecutionMode %main OriginUpperLeft
  170. OpSource GLSL 430
  171. OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
  172. OpSourceExtension "GL_GOOGLE_include_directive"
  173. OpName %main "main"
  174. OpName %o "o"
  175. OpName %i "i"
  176. OpDecorate %o Location 0
  177. OpDecorate %i Flat
  178. OpDecorate %i Location 0
  179. %void = OpTypeVoid
  180. %8 = OpTypeFunction %void
  181. %int = OpTypeInt 32 1
  182. %v4int = OpTypeVector %int 4
  183. %int_0 = OpConstant %int 0
  184. ; CHECK: [[constant:%[a-zA-Z_\d]+]] = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
  185. %13 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
  186. %bool = OpTypeBool
  187. %_ptr_Output_int = OpTypePointer Output %int
  188. %o = OpVariable %_ptr_Output_int Output
  189. %_ptr_Input_v4int = OpTypePointer Input %v4int
  190. %i = OpVariable %_ptr_Input_v4int Input
  191. %68 = OpUndef %v4int
  192. %main = OpFunction %void None %8
  193. %23 = OpLabel
  194. ; CHECK: [[load:%[a-zA-Z_\d]+]] = OpLoad %v4int %i
  195. %load = OpLoad %v4int %i
  196. OpBranch %24
  197. %24 = OpLabel
  198. %67 = OpPhi %v4int %load %23 %64 %26
  199. ; CHECK: OpLoopMerge [[merge_lab:%[a-zA-Z_\d]+]]
  200. OpLoopMerge %25 %26 None
  201. OpBranch %27
  202. %27 = OpLabel
  203. %48 = OpCompositeExtract %int %67 0
  204. %30 = OpIEqual %bool %48 %int_0
  205. OpBranchConditional %30 %31 %25
  206. %31 = OpLabel
  207. %50 = OpCompositeExtract %int %67 0
  208. %54 = OpCompositeExtract %int %67 1
  209. %58 = OpCompositeExtract %int %67 2
  210. %62 = OpCompositeExtract %int %67 3
  211. %64 = OpCompositeConstruct %v4int %50 %54 %58 %62
  212. OpBranch %26
  213. %26 = OpLabel
  214. OpBranch %24
  215. %25 = OpLabel
  216. ; CHECK: [[merge_lab]] = OpLabel
  217. ; CHECK: [[extract:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 0
  218. %66 = OpCompositeExtract %int %67 0
  219. ; CHECK-NEXT: OpStore %o [[extract]]
  220. OpStore %o %66
  221. OpReturn
  222. OpFunctionEnd
  223. )";
  224. SinglePassRunAndMatch<SimplificationPass>(text, false);
  225. }
  226. TEST_F(SimplificationTest, CopyObjectWithDecorations1) {
  227. // Don't simplify OpCopyObject if the result id has a decoration that the
  228. // operand does not.
  229. const std::string text = R"(OpCapability Shader
  230. OpCapability ShaderNonUniform
  231. %1 = OpExtInstImport "GLSL.std.450"
  232. OpMemoryModel Logical GLSL450
  233. OpEntryPoint Fragment %2 "main"
  234. OpExecutionMode %2 OriginUpperLeft
  235. OpSource GLSL 430
  236. OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
  237. OpSourceExtension "GL_GOOGLE_include_directive"
  238. OpDecorate %3 NonUniform
  239. %void = OpTypeVoid
  240. %5 = OpTypeFunction %void
  241. %int = OpTypeInt 32 1
  242. %2 = OpFunction %void None %5
  243. %7 = OpLabel
  244. %8 = OpUndef %int
  245. %3 = OpCopyObject %int %8
  246. %9 = OpIAdd %int %3 %3
  247. OpReturn
  248. OpFunctionEnd
  249. )";
  250. SinglePassRunAndCheck<SimplificationPass>(text, text, false);
  251. }
  252. TEST_F(SimplificationTest, CopyObjectWithDecorations2) {
  253. // Simplify OpCopyObject if the result id is a subset of the decorations of
  254. // the operand.
  255. const std::string before = R"(OpCapability Shader
  256. OpCapability ShaderNonUniform
  257. %1 = OpExtInstImport "GLSL.std.450"
  258. OpMemoryModel Logical GLSL450
  259. OpEntryPoint Fragment %2 "main"
  260. OpExecutionMode %2 OriginUpperLeft
  261. OpSource GLSL 430
  262. OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
  263. OpSourceExtension "GL_GOOGLE_include_directive"
  264. OpDecorate %3 NonUniform
  265. %void = OpTypeVoid
  266. %5 = OpTypeFunction %void
  267. %int = OpTypeInt 32 1
  268. %2 = OpFunction %void None %5
  269. %7 = OpLabel
  270. %3 = OpUndef %int
  271. %8 = OpCopyObject %int %3
  272. %9 = OpIAdd %int %8 %8
  273. OpReturn
  274. OpFunctionEnd
  275. )";
  276. const std::string after = R"(OpCapability Shader
  277. OpCapability ShaderNonUniform
  278. %1 = OpExtInstImport "GLSL.std.450"
  279. OpMemoryModel Logical GLSL450
  280. OpEntryPoint Fragment %2 "main"
  281. OpExecutionMode %2 OriginUpperLeft
  282. OpSource GLSL 430
  283. OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
  284. OpSourceExtension "GL_GOOGLE_include_directive"
  285. OpDecorate %3 NonUniform
  286. %void = OpTypeVoid
  287. %5 = OpTypeFunction %void
  288. %int = OpTypeInt 32 1
  289. %2 = OpFunction %void None %5
  290. %7 = OpLabel
  291. %3 = OpUndef %int
  292. %9 = OpIAdd %int %3 %3
  293. OpReturn
  294. OpFunctionEnd
  295. )";
  296. SinglePassRunAndCheck<SimplificationPass>(before, after, false);
  297. }
  298. TEST_F(SimplificationTest, DontMoveDecorations) {
  299. const std::string spirv = R"(
  300. ; CHECK-NOT: RelaxedPrecision
  301. ; CHECK: [[sub:%\w+]] = OpFSub
  302. ; CHECK: OpStore {{.*}} [[sub]]
  303. OpCapability Shader
  304. OpMemoryModel Logical GLSL450
  305. OpEntryPoint GLCompute %main "main"
  306. OpExecutionMode %main LocalSize 1 1 1
  307. OpDecorate %add RelaxedPrecision
  308. OpDecorate %block Block
  309. OpMemberDecorate %block 0 Offset 0
  310. OpMemberDecorate %block 1 Offset 4
  311. OpDecorate %in DescriptorSet 0
  312. OpDecorate %in Binding 0
  313. OpDecorate %out DescriptorSet 0
  314. OpDecorate %out Binding 1
  315. %void = OpTypeVoid
  316. %float = OpTypeFloat 32
  317. %void_fn = OpTypeFunction %void
  318. %block = OpTypeStruct %float %float
  319. %ptr_ssbo_block = OpTypePointer StorageBuffer %block
  320. %in = OpVariable %ptr_ssbo_block StorageBuffer
  321. %out = OpVariable %ptr_ssbo_block StorageBuffer
  322. %ptr_ssbo_float = OpTypePointer StorageBuffer %float
  323. %int = OpTypeInt 32 0
  324. %int_0 = OpConstant %int 0
  325. %int_1 = OpConstant %int 1
  326. %float_0 = OpConstant %float 0
  327. %main = OpFunction %void None %void_fn
  328. %entry = OpLabel
  329. %in_gep_0 = OpAccessChain %ptr_ssbo_float %in %int_0
  330. %in_gep_1 = OpAccessChain %ptr_ssbo_float %in %int_1
  331. %load_0 = OpLoad %float %in_gep_0
  332. %load_1 = OpLoad %float %in_gep_1
  333. %sub = OpFSub %float %load_0 %load_1
  334. %add = OpFAdd %float %float_0 %sub
  335. %out_gep_0 = OpAccessChain %ptr_ssbo_float %out %int_0
  336. OpStore %out_gep_0 %add
  337. OpReturn
  338. OpFunctionEnd
  339. )";
  340. SinglePassRunAndMatch<SimplificationPass>(spirv, true);
  341. }
  342. TEST_F(SimplificationTest, FunctionDeclaration) {
  343. // Make sure the pass works with a function declaration that is called.
  344. const std::string text = R"(OpCapability Addresses
  345. OpCapability Linkage
  346. OpCapability Kernel
  347. OpCapability Int8
  348. %1 = OpExtInstImport "OpenCL.std"
  349. OpMemoryModel Physical64 OpenCL
  350. OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
  351. OpExecutionMode %2 ContractionOff
  352. OpSource Unknown 0
  353. OpDecorate %3 LinkageAttributes "julia_error_7712" Import
  354. %void = OpTypeVoid
  355. %5 = OpTypeFunction %void
  356. %3 = OpFunction %void None %5
  357. OpFunctionEnd
  358. %2 = OpFunction %void None %5
  359. %6 = OpLabel
  360. %7 = OpFunctionCall %void %3
  361. OpReturn
  362. OpFunctionEnd
  363. )";
  364. SinglePassRunAndCheck<SimplificationPass>(text, text, false);
  365. }
  366. } // namespace
  367. } // namespace opt
  368. } // namespace spvtools