operand_to_constant_test.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  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 "source/reduce/operand_to_const_reduction_opportunity_finder.h"
  15. #include "source/opt/build_module.h"
  16. #include "source/reduce/reduction_opportunity.h"
  17. #include "test/reduce/reduce_test_util.h"
  18. namespace spvtools {
  19. namespace reduce {
  20. namespace {
  21. TEST(OperandToConstantReductionPassTest, BasicCheck) {
  22. std::string prologue = R"(
  23. OpCapability Shader
  24. %1 = OpExtInstImport "GLSL.std.450"
  25. OpMemoryModel Logical GLSL450
  26. OpEntryPoint Fragment %4 "main" %37
  27. OpExecutionMode %4 OriginUpperLeft
  28. OpSource ESSL 310
  29. OpName %4 "main"
  30. OpName %9 "buf1"
  31. OpMemberName %9 0 "f"
  32. OpName %11 ""
  33. OpName %24 "buf2"
  34. OpMemberName %24 0 "i"
  35. OpName %26 ""
  36. OpName %37 "_GLF_color"
  37. OpMemberDecorate %9 0 Offset 0
  38. OpDecorate %9 Block
  39. OpDecorate %11 DescriptorSet 0
  40. OpDecorate %11 Binding 1
  41. OpMemberDecorate %24 0 Offset 0
  42. OpDecorate %24 Block
  43. OpDecorate %26 DescriptorSet 0
  44. OpDecorate %26 Binding 2
  45. OpDecorate %37 Location 0
  46. %2 = OpTypeVoid
  47. %3 = OpTypeFunction %2
  48. %6 = OpTypeFloat 32
  49. %9 = OpTypeStruct %6
  50. %10 = OpTypePointer Uniform %9
  51. %11 = OpVariable %10 Uniform
  52. %12 = OpTypeInt 32 1
  53. %13 = OpConstant %12 0
  54. %14 = OpTypePointer Uniform %6
  55. %20 = OpConstant %6 2
  56. %24 = OpTypeStruct %12
  57. %25 = OpTypePointer Uniform %24
  58. %26 = OpVariable %25 Uniform
  59. %27 = OpTypePointer Uniform %12
  60. %33 = OpConstant %12 3
  61. %35 = OpTypeVector %6 4
  62. %36 = OpTypePointer Output %35
  63. %37 = OpVariable %36 Output
  64. %4 = OpFunction %2 None %3
  65. %5 = OpLabel
  66. %15 = OpAccessChain %14 %11 %13
  67. %16 = OpLoad %6 %15
  68. %19 = OpFAdd %6 %16 %16
  69. %21 = OpFAdd %6 %19 %20
  70. %28 = OpAccessChain %27 %26 %13
  71. %29 = OpLoad %12 %28
  72. )";
  73. std::string epilogue = R"(
  74. %45 = OpConvertSToF %6 %34
  75. %46 = OpCompositeConstruct %35 %16 %21 %43 %45
  76. OpStore %37 %46
  77. OpReturn
  78. OpFunctionEnd
  79. )";
  80. std::string original = prologue + R"(
  81. %32 = OpIAdd %12 %29 %29
  82. %34 = OpIAdd %12 %32 %33
  83. %43 = OpConvertSToF %6 %29
  84. )" + epilogue;
  85. std::string expected = prologue + R"(
  86. %32 = OpIAdd %12 %13 %13 ; %29 -> %13 x 2
  87. %34 = OpIAdd %12 %13 %33 ; %32 -> %13
  88. %43 = OpConvertSToF %6 %13 ; %29 -> %13
  89. )" + epilogue;
  90. const auto env = SPV_ENV_UNIVERSAL_1_3;
  91. const auto consumer = nullptr;
  92. const auto context =
  93. BuildModule(env, consumer, original, kReduceAssembleOption);
  94. const auto ops =
  95. OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
  96. context.get(), 0);
  97. ASSERT_EQ(17, ops.size());
  98. ASSERT_TRUE(ops[0]->PreconditionHolds());
  99. ops[0]->TryToApply();
  100. ASSERT_TRUE(ops[1]->PreconditionHolds());
  101. ops[1]->TryToApply();
  102. ASSERT_TRUE(ops[2]->PreconditionHolds());
  103. ops[2]->TryToApply();
  104. ASSERT_TRUE(ops[3]->PreconditionHolds());
  105. ops[3]->TryToApply();
  106. CheckEqual(env, expected, context.get());
  107. }
  108. TEST(OperandToConstantReductionPassTest, WithCalledFunction) {
  109. std::string shader = R"(
  110. OpCapability Shader
  111. %1 = OpExtInstImport "GLSL.std.450"
  112. OpMemoryModel Logical GLSL450
  113. OpEntryPoint Fragment %4 "main" %10 %12
  114. OpExecutionMode %4 OriginUpperLeft
  115. OpSource ESSL 310
  116. %2 = OpTypeVoid
  117. %3 = OpTypeFunction %2
  118. %6 = OpTypeFloat 32
  119. %7 = OpTypeVector %6 4
  120. %8 = OpTypeFunction %7
  121. %9 = OpTypePointer Output %7
  122. %10 = OpVariable %9 Output
  123. %11 = OpTypePointer Input %7
  124. %12 = OpVariable %11 Input
  125. %13 = OpConstant %6 0
  126. %14 = OpConstantComposite %7 %13 %13 %13 %13
  127. %4 = OpFunction %2 None %3
  128. %5 = OpLabel
  129. %15 = OpFunctionCall %7 %16
  130. OpReturn
  131. OpFunctionEnd
  132. %16 = OpFunction %7 None %8
  133. %17 = OpLabel
  134. OpReturnValue %14
  135. OpFunctionEnd
  136. )";
  137. const auto env = SPV_ENV_UNIVERSAL_1_3;
  138. const auto consumer = nullptr;
  139. const auto context =
  140. BuildModule(env, consumer, shader, kReduceAssembleOption);
  141. const auto ops =
  142. OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
  143. context.get(), 0);
  144. ASSERT_EQ(0, ops.size());
  145. }
  146. TEST(OperandToConstantReductionPassTest, TargetSpecificFunction) {
  147. std::string shader = R"(
  148. OpCapability Shader
  149. %1 = OpExtInstImport "GLSL.std.450"
  150. OpMemoryModel Logical GLSL450
  151. OpEntryPoint Fragment %4 "main"
  152. OpExecutionMode %4 OriginUpperLeft
  153. OpSource ESSL 320
  154. %2 = OpTypeVoid
  155. %3 = OpTypeFunction %2
  156. %6 = OpTypeInt 32 1
  157. %7 = OpTypePointer Function %6
  158. %8 = OpTypeFunction %6 %7
  159. %17 = OpConstant %6 1
  160. %20 = OpConstant %6 2
  161. %23 = OpConstant %6 0
  162. %24 = OpTypeBool
  163. %35 = OpConstant %6 3
  164. %53 = OpConstant %6 10
  165. %4 = OpFunction %2 None %3
  166. %5 = OpLabel
  167. %65 = OpVariable %7 Function
  168. %68 = OpVariable %7 Function
  169. %73 = OpVariable %7 Function
  170. OpStore %65 %35
  171. %66 = OpLoad %6 %65
  172. %67 = OpIAdd %6 %66 %17
  173. OpStore %65 %67
  174. %69 = OpLoad %6 %65
  175. OpStore %68 %69
  176. %70 = OpFunctionCall %6 %13 %68
  177. %71 = OpLoad %6 %65
  178. %72 = OpIAdd %6 %71 %70
  179. OpStore %65 %72
  180. %74 = OpLoad %6 %65
  181. OpStore %73 %74
  182. %75 = OpFunctionCall %6 %10 %73
  183. %76 = OpLoad %6 %65
  184. %77 = OpIAdd %6 %76 %75
  185. OpStore %65 %77
  186. OpReturn
  187. OpFunctionEnd
  188. %10 = OpFunction %6 None %8
  189. %9 = OpFunctionParameter %7
  190. %11 = OpLabel
  191. %15 = OpVariable %7 Function
  192. %16 = OpLoad %6 %9
  193. %18 = OpIAdd %6 %16 %17
  194. OpStore %15 %18
  195. %19 = OpLoad %6 %15
  196. %21 = OpIAdd %6 %19 %20
  197. OpStore %15 %21
  198. %22 = OpLoad %6 %15
  199. %25 = OpSGreaterThan %24 %22 %23
  200. OpSelectionMerge %27 None
  201. OpBranchConditional %25 %26 %27
  202. %26 = OpLabel
  203. %28 = OpLoad %6 %9
  204. OpReturnValue %28
  205. %27 = OpLabel
  206. %30 = OpLoad %6 %9
  207. %31 = OpIAdd %6 %30 %17
  208. OpReturnValue %31
  209. OpFunctionEnd
  210. %13 = OpFunction %6 None %8
  211. %12 = OpFunctionParameter %7
  212. %14 = OpLabel
  213. %41 = OpVariable %7 Function
  214. %46 = OpVariable %7 Function
  215. %55 = OpVariable %7 Function
  216. %34 = OpLoad %6 %12
  217. %36 = OpIEqual %24 %34 %35
  218. OpSelectionMerge %38 None
  219. OpBranchConditional %36 %37 %38
  220. %37 = OpLabel
  221. %39 = OpLoad %6 %12
  222. %40 = OpIMul %6 %20 %39
  223. OpStore %41 %40
  224. %42 = OpFunctionCall %6 %10 %41
  225. OpReturnValue %42
  226. %38 = OpLabel
  227. %44 = OpLoad %6 %12
  228. %45 = OpIAdd %6 %44 %17
  229. OpStore %12 %45
  230. OpStore %46 %23
  231. OpBranch %47
  232. %47 = OpLabel
  233. OpLoopMerge %49 %50 None
  234. OpBranch %51
  235. %51 = OpLabel
  236. %52 = OpLoad %6 %46
  237. %54 = OpSLessThan %24 %52 %53
  238. OpBranchConditional %54 %48 %49
  239. %48 = OpLabel
  240. %56 = OpLoad %6 %12
  241. OpStore %55 %56
  242. %57 = OpFunctionCall %6 %10 %55
  243. %58 = OpLoad %6 %12
  244. %59 = OpIAdd %6 %58 %57
  245. OpStore %12 %59
  246. OpBranch %50
  247. %50 = OpLabel
  248. %60 = OpLoad %6 %46
  249. %61 = OpIAdd %6 %60 %17
  250. OpStore %46 %61
  251. OpBranch %47
  252. %49 = OpLabel
  253. %62 = OpLoad %6 %12
  254. OpReturnValue %62
  255. OpFunctionEnd
  256. )";
  257. const auto env = SPV_ENV_UNIVERSAL_1_3;
  258. const auto consumer = nullptr;
  259. const auto context =
  260. BuildModule(env, consumer, shader, kReduceAssembleOption);
  261. // Targeting all functions, there are quite a few opportunities. To avoid
  262. // making the test too sensitive, we check that there are more than a number
  263. // somewhat lower than the real number.
  264. const auto all_ops =
  265. OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
  266. context.get(), 0);
  267. ASSERT_TRUE(all_ops.size() > 100);
  268. // Targeting individual functions, there are fewer opportunities. Again, we
  269. // avoid checking against an exact number so that the test is not too
  270. // sensitive.
  271. const auto ops_for_function_4 =
  272. OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
  273. context.get(), 4);
  274. const auto ops_for_function_10 =
  275. OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
  276. context.get(), 10);
  277. const auto ops_for_function_13 =
  278. OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
  279. context.get(), 13);
  280. ASSERT_TRUE(ops_for_function_4.size() < 60);
  281. ASSERT_TRUE(ops_for_function_10.size() < 50);
  282. ASSERT_TRUE(ops_for_function_13.size() < 80);
  283. // The total number of opportunities should be the sum of the per-function
  284. // opportunities.
  285. ASSERT_EQ(all_ops.size(), ops_for_function_4.size() +
  286. ops_for_function_10.size() +
  287. ops_for_function_13.size());
  288. }
  289. } // namespace
  290. } // namespace reduce
  291. } // namespace spvtools