redundancy_elimination_test.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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/build_module.h"
  17. #include "source/opt/value_number_table.h"
  18. #include "test/opt/assembly_builder.h"
  19. #include "test/opt/pass_fixture.h"
  20. #include "test/opt/pass_utils.h"
  21. namespace spvtools {
  22. namespace opt {
  23. namespace {
  24. using ::testing::HasSubstr;
  25. using ::testing::MatchesRegex;
  26. using RedundancyEliminationTest = PassTest<::testing::Test>;
  27. // Test that it can get a simple case of local redundancy elimination.
  28. // The rest of the test check for extra functionality.
  29. TEST_F(RedundancyEliminationTest, RemoveRedundantLocalAdd) {
  30. const std::string text = R"(
  31. OpCapability Shader
  32. %1 = OpExtInstImport "GLSL.std.450"
  33. OpMemoryModel Logical GLSL450
  34. OpEntryPoint Fragment %2 "main"
  35. OpExecutionMode %2 OriginUpperLeft
  36. OpSource GLSL 430
  37. %3 = OpTypeVoid
  38. %4 = OpTypeFunction %3
  39. %5 = OpTypeFloat 32
  40. %6 = OpTypePointer Function %5
  41. %2 = OpFunction %3 None %4
  42. %7 = OpLabel
  43. %8 = OpVariable %6 Function
  44. %9 = OpLoad %5 %8
  45. %10 = OpFAdd %5 %9 %9
  46. ; CHECK: OpFAdd
  47. ; CHECK-NOT: OpFAdd
  48. %11 = OpFAdd %5 %9 %9
  49. OpReturn
  50. OpFunctionEnd
  51. )";
  52. SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
  53. }
  54. // Remove a redundant add across basic blocks.
  55. TEST_F(RedundancyEliminationTest, RemoveRedundantAdd) {
  56. const std::string text = R"(
  57. OpCapability Shader
  58. %1 = OpExtInstImport "GLSL.std.450"
  59. OpMemoryModel Logical GLSL450
  60. OpEntryPoint Fragment %2 "main"
  61. OpExecutionMode %2 OriginUpperLeft
  62. OpSource GLSL 430
  63. %3 = OpTypeVoid
  64. %4 = OpTypeFunction %3
  65. %5 = OpTypeFloat 32
  66. %6 = OpTypePointer Function %5
  67. %2 = OpFunction %3 None %4
  68. %7 = OpLabel
  69. %8 = OpVariable %6 Function
  70. %9 = OpLoad %5 %8
  71. %10 = OpFAdd %5 %9 %9
  72. OpBranch %11
  73. %11 = OpLabel
  74. ; CHECK: OpFAdd
  75. ; CHECK-NOT: OpFAdd
  76. %12 = OpFAdd %5 %9 %9
  77. OpReturn
  78. OpFunctionEnd
  79. )";
  80. SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
  81. }
  82. // Remove a redundant add going through a multiple basic blocks.
  83. TEST_F(RedundancyEliminationTest, RemoveRedundantAddDiamond) {
  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 Function %5
  95. %7 = OpTypeBool
  96. %8 = OpConstantTrue %7
  97. %2 = OpFunction %3 None %4
  98. %9 = OpLabel
  99. %10 = OpVariable %6 Function
  100. %11 = OpLoad %5 %10
  101. %12 = OpFAdd %5 %11 %11
  102. ; CHECK: OpFAdd
  103. ; CHECK-NOT: OpFAdd
  104. OpBranchConditional %8 %13 %14
  105. %13 = OpLabel
  106. OpBranch %15
  107. %14 = OpLabel
  108. OpBranch %15
  109. %15 = OpLabel
  110. %16 = OpFAdd %5 %11 %11
  111. OpReturn
  112. OpFunctionEnd
  113. )";
  114. SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
  115. }
  116. // Remove a redundant add in a side node.
  117. TEST_F(RedundancyEliminationTest, RemoveRedundantAddInSideNode) {
  118. const std::string text = R"(
  119. OpCapability Shader
  120. %1 = OpExtInstImport "GLSL.std.450"
  121. OpMemoryModel Logical GLSL450
  122. OpEntryPoint Fragment %2 "main"
  123. OpExecutionMode %2 OriginUpperLeft
  124. OpSource GLSL 430
  125. %3 = OpTypeVoid
  126. %4 = OpTypeFunction %3
  127. %5 = OpTypeFloat 32
  128. %6 = OpTypePointer Function %5
  129. %7 = OpTypeBool
  130. %8 = OpConstantTrue %7
  131. %2 = OpFunction %3 None %4
  132. %9 = OpLabel
  133. %10 = OpVariable %6 Function
  134. %11 = OpLoad %5 %10
  135. %12 = OpFAdd %5 %11 %11
  136. ; CHECK: OpFAdd
  137. ; CHECK-NOT: OpFAdd
  138. OpBranchConditional %8 %13 %14
  139. %13 = OpLabel
  140. OpBranch %15
  141. %14 = OpLabel
  142. %16 = OpFAdd %5 %11 %11
  143. OpBranch %15
  144. %15 = OpLabel
  145. OpReturn
  146. OpFunctionEnd
  147. )";
  148. SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
  149. }
  150. // Remove a redundant add whose value is in the result of a phi node.
  151. TEST_F(RedundancyEliminationTest, RemoveRedundantAddWithPhi) {
  152. const std::string text = R"(
  153. OpCapability Shader
  154. %1 = OpExtInstImport "GLSL.std.450"
  155. OpMemoryModel Logical GLSL450
  156. OpEntryPoint Fragment %2 "main"
  157. OpExecutionMode %2 OriginUpperLeft
  158. OpSource GLSL 430
  159. %3 = OpTypeVoid
  160. %4 = OpTypeFunction %3
  161. %5 = OpTypeFloat 32
  162. %6 = OpTypePointer Function %5
  163. %7 = OpTypeBool
  164. %8 = OpConstantTrue %7
  165. %2 = OpFunction %3 None %4
  166. %9 = OpLabel
  167. %10 = OpVariable %6 Function
  168. %11 = OpLoad %5 %10
  169. OpBranchConditional %8 %13 %14
  170. %13 = OpLabel
  171. %add1 = OpFAdd %5 %11 %11
  172. ; CHECK: OpFAdd
  173. OpBranch %15
  174. %14 = OpLabel
  175. %add2 = OpFAdd %5 %11 %11
  176. ; CHECK: OpFAdd
  177. OpBranch %15
  178. %15 = OpLabel
  179. ; CHECK: OpPhi
  180. %phi = OpPhi %5 %add1 %13 %add2 %14
  181. ; CHECK-NOT: OpFAdd
  182. %16 = OpFAdd %5 %11 %11
  183. OpReturn
  184. OpFunctionEnd
  185. )";
  186. SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
  187. }
  188. // Keep the add because it is redundant on some paths, but not all paths.
  189. TEST_F(RedundancyEliminationTest, KeepPartiallyRedundantAdd) {
  190. const std::string text = R"(
  191. OpCapability Shader
  192. %1 = OpExtInstImport "GLSL.std.450"
  193. OpMemoryModel Logical GLSL450
  194. OpEntryPoint Fragment %2 "main"
  195. OpExecutionMode %2 OriginUpperLeft
  196. OpSource GLSL 430
  197. %3 = OpTypeVoid
  198. %4 = OpTypeFunction %3
  199. %5 = OpTypeFloat 32
  200. %6 = OpTypePointer Function %5
  201. %7 = OpTypeBool
  202. %8 = OpConstantTrue %7
  203. %2 = OpFunction %3 None %4
  204. %9 = OpLabel
  205. %10 = OpVariable %6 Function
  206. %11 = OpLoad %5 %10
  207. OpBranchConditional %8 %13 %14
  208. %13 = OpLabel
  209. %add = OpFAdd %5 %11 %11
  210. OpBranch %15
  211. %14 = OpLabel
  212. OpBranch %15
  213. %15 = OpLabel
  214. %16 = OpFAdd %5 %11 %11
  215. OpReturn
  216. OpFunctionEnd
  217. )";
  218. auto result = SinglePassRunAndDisassemble<RedundancyEliminationPass>(
  219. text, /* skip_nop = */ true, /* do_validation = */ false);
  220. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  221. }
  222. // Keep the add. Even if it is redundant on all paths, there is no single id
  223. // whose definition dominates the add and contains the same value.
  224. TEST_F(RedundancyEliminationTest, KeepRedundantAddWithoutPhi) {
  225. const std::string text = R"(
  226. OpCapability Shader
  227. %1 = OpExtInstImport "GLSL.std.450"
  228. OpMemoryModel Logical GLSL450
  229. OpEntryPoint Fragment %2 "main"
  230. OpExecutionMode %2 OriginUpperLeft
  231. OpSource GLSL 430
  232. %3 = OpTypeVoid
  233. %4 = OpTypeFunction %3
  234. %5 = OpTypeFloat 32
  235. %6 = OpTypePointer Function %5
  236. %7 = OpTypeBool
  237. %8 = OpConstantTrue %7
  238. %2 = OpFunction %3 None %4
  239. %9 = OpLabel
  240. %10 = OpVariable %6 Function
  241. %11 = OpLoad %5 %10
  242. OpBranchConditional %8 %13 %14
  243. %13 = OpLabel
  244. %add1 = OpFAdd %5 %11 %11
  245. OpBranch %15
  246. %14 = OpLabel
  247. %add2 = OpFAdd %5 %11 %11
  248. OpBranch %15
  249. %15 = OpLabel
  250. %16 = OpFAdd %5 %11 %11
  251. OpReturn
  252. OpFunctionEnd
  253. )";
  254. auto result = SinglePassRunAndDisassemble<RedundancyEliminationPass>(
  255. text, /* skip_nop = */ true, /* do_validation = */ false);
  256. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  257. }
  258. } // namespace
  259. } // namespace opt
  260. } // namespace spvtools