local_redundancy_elimination_test.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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 <string>
  15. #include "gmock/gmock.h"
  16. #include "source/opt/value_number_table.h"
  17. #include "test/opt/pass_fixture.h"
  18. #include "test/opt/pass_utils.h"
  19. namespace spvtools {
  20. namespace opt {
  21. namespace {
  22. using ::testing::HasSubstr;
  23. using ::testing::MatchesRegex;
  24. using LocalRedundancyEliminationTest = PassTest<::testing::Test>;
  25. // Remove an instruction when it was already computed.
  26. TEST_F(LocalRedundancyEliminationTest, RemoveRedundantAdd) {
  27. const std::string text = R"(
  28. OpCapability Shader
  29. %1 = OpExtInstImport "GLSL.std.450"
  30. OpMemoryModel Logical GLSL450
  31. OpEntryPoint Fragment %2 "main"
  32. OpExecutionMode %2 OriginUpperLeft
  33. OpSource GLSL 430
  34. %3 = OpTypeVoid
  35. %4 = OpTypeFunction %3
  36. %5 = OpTypeFloat 32
  37. %6 = OpTypePointer Function %5
  38. %2 = OpFunction %3 None %4
  39. %7 = OpLabel
  40. %8 = OpVariable %6 Function
  41. %9 = OpLoad %5 %8
  42. %10 = OpFAdd %5 %9 %9
  43. ; CHECK: OpFAdd
  44. ; CHECK-NOT: OpFAdd
  45. %11 = OpFAdd %5 %9 %9
  46. OpReturn
  47. OpFunctionEnd
  48. )";
  49. SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
  50. }
  51. // Make sure we keep instruction that are different, but look similar.
  52. TEST_F(LocalRedundancyEliminationTest, KeepDifferentAdd) {
  53. const std::string text = R"(
  54. OpCapability Shader
  55. %1 = OpExtInstImport "GLSL.std.450"
  56. OpMemoryModel Logical GLSL450
  57. OpEntryPoint Fragment %2 "main"
  58. OpExecutionMode %2 OriginUpperLeft
  59. OpSource GLSL 430
  60. %3 = OpTypeVoid
  61. %4 = OpTypeFunction %3
  62. %5 = OpTypeFloat 32
  63. %6 = OpTypePointer Function %5
  64. %2 = OpFunction %3 None %4
  65. %7 = OpLabel
  66. %8 = OpVariable %6 Function
  67. %9 = OpLoad %5 %8
  68. %10 = OpFAdd %5 %9 %9
  69. ; CHECK: OpFAdd
  70. OpStore %8 %10
  71. %11 = OpLoad %5 %8
  72. ; CHECK: %11 = OpLoad
  73. %12 = OpFAdd %5 %11 %11
  74. ; CHECK: OpFAdd [[:%\w+]] %11 %11
  75. OpReturn
  76. OpFunctionEnd
  77. )";
  78. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  79. SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
  80. }
  81. // This test is check that the values are being propagated properly, and that
  82. // we are able to identify sequences of instruction that are not needed.
  83. TEST_F(LocalRedundancyEliminationTest, RemoveMultipleInstructions) {
  84. const std::string text = R"(
  85. OpCapability Shader
  86. %1 = OpExtInstImport "GLSL.std.450"
  87. OpMemoryModel Logical GLSL450
  88. OpEntryPoint Fragment %2 "main"
  89. OpExecutionMode %2 OriginUpperLeft
  90. OpSource GLSL 430
  91. %3 = OpTypeVoid
  92. %4 = OpTypeFunction %3
  93. %5 = OpTypeFloat 32
  94. %6 = OpTypePointer Uniform %5
  95. %8 = OpVariable %6 Uniform
  96. %2 = OpFunction %3 None %4
  97. %7 = OpLabel
  98. ; CHECK: [[r1:%\w+]] = OpLoad
  99. %9 = OpLoad %5 %8
  100. ; CHECK-NEXT: [[r2:%\w+]] = OpFAdd [[:%\w+]] [[r1]] [[r1]]
  101. %10 = OpFAdd %5 %9 %9
  102. ; CHECK-NEXT: [[r3:%\w+]] = OpFMul [[:%\w+]] [[r2]] [[r1]]
  103. %11 = OpFMul %5 %10 %9
  104. ; CHECK-NOT: OpLoad
  105. %12 = OpLoad %5 %8
  106. ; CHECK-NOT: OpFAdd [[:\w+]] %12 %12
  107. %13 = OpFAdd %5 %12 %12
  108. ; CHECK-NOT: OpFMul
  109. %14 = OpFMul %5 %13 %12
  110. ; CHECK-NEXT: [[:%\w+]] = OpFAdd [[:%\w+]] [[r3]] [[r3]]
  111. %15 = OpFAdd %5 %14 %11
  112. OpReturn
  113. OpFunctionEnd
  114. )";
  115. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  116. SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
  117. }
  118. // Redundant instructions in different blocks should be kept.
  119. TEST_F(LocalRedundancyEliminationTest, KeepInstructionsInDifferentBlocks) {
  120. const std::string text = R"(
  121. OpCapability Shader
  122. %1 = OpExtInstImport "GLSL.std.450"
  123. OpMemoryModel Logical GLSL450
  124. OpEntryPoint Fragment %2 "main"
  125. OpExecutionMode %2 OriginUpperLeft
  126. OpSource GLSL 430
  127. %3 = OpTypeVoid
  128. %4 = OpTypeFunction %3
  129. %5 = OpTypeFloat 32
  130. %6 = OpTypePointer Function %5
  131. %2 = OpFunction %3 None %4
  132. %bb1 = OpLabel
  133. %8 = OpVariable %6 Function
  134. %9 = OpLoad %5 %8
  135. %10 = OpFAdd %5 %9 %9
  136. ; CHECK: OpFAdd
  137. OpBranch %bb2
  138. %bb2 = OpLabel
  139. ; CHECK: OpFAdd
  140. %11 = OpFAdd %5 %9 %9
  141. OpReturn
  142. OpFunctionEnd
  143. )";
  144. SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
  145. }
  146. TEST_F(LocalRedundancyEliminationTest, StorageBufferIdentification) {
  147. const std::string text = R"(
  148. ; CHECK: [[gep:%\w+]] = OpAccessChain
  149. ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[gep]]
  150. ; CHECK: [[add:%\w+]] = OpIAdd {{%\w+}} [[ld]]
  151. ; CHECK: OpStore [[gep]] [[add]]
  152. ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[gep]]
  153. ; CHECK: [[add:%\w+]] = OpIAdd {{%\w+}} [[ld]]
  154. ; CHECK: OpStore [[gep]] [[add]]
  155. OpCapability Shader
  156. OpCapability Linkage
  157. OpMemoryModel Logical GLSL450
  158. OpDecorate %block BufferBlock
  159. OpMemberDecorate %block 0 Offset 0
  160. %void = OpTypeVoid
  161. %int = OpTypeInt 32 0
  162. %int_0 = OpConstant %int 0
  163. %int_1 = OpConstant %int 1
  164. %block = OpTypeStruct %int
  165. %array = OpTypeArray %block %int_1
  166. %ptr_ssbo_array = OpTypePointer Uniform %array
  167. %ptr_ssbo_int = OpTypePointer Uniform %int
  168. %var = OpVariable %ptr_ssbo_array Uniform
  169. %void_fn = OpTypeFunction %void
  170. %fn = OpFunction %void None %void_fn
  171. %entry = OpLabel
  172. %gep1 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
  173. %ld1 = OpLoad %int %gep1
  174. %add1 = OpIAdd %int %ld1 %int_1
  175. %gep2 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
  176. OpStore %gep2 %add1
  177. %gep3 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
  178. %ld3 = OpLoad %int %gep3
  179. %add3 = OpIAdd %int %ld3 %int_1
  180. %gep4 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
  181. OpStore %gep4 %add3
  182. OpReturn
  183. OpFunctionEnd
  184. )";
  185. SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, true);
  186. }
  187. } // namespace
  188. } // namespace opt
  189. } // namespace spvtools