remove_unused_instruction_test.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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/remove_unused_instruction_reduction_opportunity_finder.h"
  15. #include "source/opt/build_module.h"
  16. #include "source/reduce/reduction_opportunity.h"
  17. #include "source/util/make_unique.h"
  18. #include "test/reduce/reduce_test_util.h"
  19. namespace spvtools {
  20. namespace reduce {
  21. namespace {
  22. const spv_target_env kEnv = SPV_ENV_UNIVERSAL_1_3;
  23. TEST(RemoveUnusedInstructionReductionPassTest, RemoveStores) {
  24. // A module with some unused instructions, including some unused OpStore
  25. // instructions.
  26. RemoveUnusedInstructionReductionOpportunityFinder finder(true);
  27. const std::string original = R"(
  28. OpCapability Shader
  29. %1 = OpExtInstImport "GLSL.std.450"
  30. OpMemoryModel Logical GLSL450
  31. OpEntryPoint Fragment %4 "main"
  32. OpExecutionMode %4 OriginUpperLeft
  33. OpSource ESSL 310 ; 0
  34. OpName %4 "main" ; 1
  35. OpName %8 "a" ; 2
  36. OpName %10 "b" ; 3
  37. OpName %12 "c" ; 4
  38. OpName %14 "d" ; 5
  39. %2 = OpTypeVoid
  40. %3 = OpTypeFunction %2
  41. %6 = OpTypeInt 32 1
  42. %7 = OpTypePointer Function %6
  43. %9 = OpConstant %6 10
  44. %11 = OpConstant %6 20
  45. %13 = OpConstant %6 30
  46. %4 = OpFunction %2 None %3
  47. %5 = OpLabel
  48. %8 = OpVariable %7 Function
  49. %10 = OpVariable %7 Function
  50. %12 = OpVariable %7 Function
  51. %14 = OpVariable %7 Function
  52. OpStore %8 %9 ; 6
  53. OpStore %10 %11 ; 7
  54. OpStore %12 %13 ; 8
  55. %15 = OpLoad %6 %8
  56. OpStore %14 %15 ; 9
  57. OpReturn
  58. OpFunctionEnd
  59. )";
  60. const MessageConsumer consumer = nullptr;
  61. const auto context =
  62. BuildModule(kEnv, consumer, original, kReduceAssembleOption);
  63. CheckValid(kEnv, context.get());
  64. auto ops = finder.GetAvailableOpportunities(context.get(), 0);
  65. ASSERT_EQ(10, ops.size());
  66. for (auto& op : ops) {
  67. ASSERT_TRUE(op->PreconditionHolds());
  68. op->TryToApply();
  69. CheckValid(kEnv, context.get());
  70. }
  71. const std::string step_2 = R"(
  72. OpCapability Shader
  73. %1 = OpExtInstImport "GLSL.std.450"
  74. OpMemoryModel Logical GLSL450
  75. OpEntryPoint Fragment %4 "main"
  76. OpExecutionMode %4 OriginUpperLeft
  77. %2 = OpTypeVoid
  78. %3 = OpTypeFunction %2
  79. %6 = OpTypeInt 32 1
  80. %7 = OpTypePointer Function %6
  81. %9 = OpConstant %6 10 ; 0
  82. %11 = OpConstant %6 20 ; 1
  83. %13 = OpConstant %6 30 ; 2
  84. %4 = OpFunction %2 None %3
  85. %5 = OpLabel
  86. %8 = OpVariable %7 Function
  87. %10 = OpVariable %7 Function ; 3
  88. %12 = OpVariable %7 Function ; 4
  89. %14 = OpVariable %7 Function ; 5
  90. %15 = OpLoad %6 %8 ; 6
  91. OpReturn
  92. OpFunctionEnd
  93. )";
  94. CheckEqual(kEnv, step_2, context.get());
  95. ops = finder.GetAvailableOpportunities(context.get(), 0);
  96. ASSERT_EQ(7, ops.size());
  97. for (auto& op : ops) {
  98. ASSERT_TRUE(op->PreconditionHolds());
  99. op->TryToApply();
  100. CheckValid(kEnv, context.get());
  101. }
  102. const std::string step_3 = R"(
  103. OpCapability Shader
  104. %1 = OpExtInstImport "GLSL.std.450"
  105. OpMemoryModel Logical GLSL450
  106. OpEntryPoint Fragment %4 "main"
  107. OpExecutionMode %4 OriginUpperLeft
  108. %2 = OpTypeVoid
  109. %3 = OpTypeFunction %2
  110. %6 = OpTypeInt 32 1
  111. %7 = OpTypePointer Function %6
  112. %4 = OpFunction %2 None %3
  113. %5 = OpLabel
  114. %8 = OpVariable %7 Function ; 0
  115. OpReturn
  116. OpFunctionEnd
  117. )";
  118. CheckEqual(kEnv, step_3, context.get());
  119. ops = finder.GetAvailableOpportunities(context.get(), 0);
  120. ASSERT_EQ(1, ops.size());
  121. for (auto& op : ops) {
  122. ASSERT_TRUE(op->PreconditionHolds());
  123. op->TryToApply();
  124. CheckValid(kEnv, context.get());
  125. }
  126. const std::string step_4 = R"(
  127. OpCapability Shader
  128. %1 = OpExtInstImport "GLSL.std.450"
  129. OpMemoryModel Logical GLSL450
  130. OpEntryPoint Fragment %4 "main"
  131. OpExecutionMode %4 OriginUpperLeft
  132. %2 = OpTypeVoid
  133. %3 = OpTypeFunction %2
  134. %6 = OpTypeInt 32 1
  135. %7 = OpTypePointer Function %6 ; 0
  136. %4 = OpFunction %2 None %3
  137. %5 = OpLabel
  138. OpReturn
  139. OpFunctionEnd
  140. )";
  141. CheckEqual(kEnv, step_4, context.get());
  142. ops = finder.GetAvailableOpportunities(context.get(), 0);
  143. ASSERT_EQ(1, ops.size());
  144. for (auto& op : ops) {
  145. ASSERT_TRUE(op->PreconditionHolds());
  146. op->TryToApply();
  147. CheckValid(kEnv, context.get());
  148. }
  149. const std::string step_5 = R"(
  150. OpCapability Shader
  151. %1 = OpExtInstImport "GLSL.std.450"
  152. OpMemoryModel Logical GLSL450
  153. OpEntryPoint Fragment %4 "main"
  154. OpExecutionMode %4 OriginUpperLeft
  155. %2 = OpTypeVoid
  156. %3 = OpTypeFunction %2
  157. %6 = OpTypeInt 32 1 ; 0
  158. %4 = OpFunction %2 None %3
  159. %5 = OpLabel
  160. OpReturn
  161. OpFunctionEnd
  162. )";
  163. CheckEqual(kEnv, step_5, context.get());
  164. ops = finder.GetAvailableOpportunities(context.get(), 0);
  165. ASSERT_EQ(1, ops.size());
  166. for (auto& op : ops) {
  167. ASSERT_TRUE(op->PreconditionHolds());
  168. op->TryToApply();
  169. CheckValid(kEnv, context.get());
  170. }
  171. const std::string step_6 = R"(
  172. OpCapability Shader
  173. %1 = OpExtInstImport "GLSL.std.450"
  174. OpMemoryModel Logical GLSL450
  175. OpEntryPoint Fragment %4 "main"
  176. OpExecutionMode %4 OriginUpperLeft
  177. %2 = OpTypeVoid
  178. %3 = OpTypeFunction %2
  179. %4 = OpFunction %2 None %3
  180. %5 = OpLabel
  181. OpReturn
  182. OpFunctionEnd
  183. )";
  184. CheckEqual(kEnv, step_6, context.get());
  185. ops = finder.GetAvailableOpportunities(context.get(), 0);
  186. ASSERT_EQ(0, ops.size());
  187. }
  188. TEST(RemoveUnusedInstructionReductionPassTest, Referenced) {
  189. // A module with some unused global variables, constants, and types. Some will
  190. // not be removed initially because of the OpDecorate instructions.
  191. RemoveUnusedInstructionReductionOpportunityFinder finder(true);
  192. const std::string shader = R"(
  193. OpCapability Shader
  194. %1 = OpExtInstImport "GLSL.std.450"
  195. OpMemoryModel Logical GLSL450
  196. OpEntryPoint Fragment %4 "main"
  197. OpExecutionMode %4 OriginUpperLeft
  198. OpSource ESSL 310 ; 1
  199. OpName %4 "main" ; 2
  200. OpName %12 "a" ; 3
  201. OpDecorate %12 RelaxedPrecision ; 4
  202. OpDecorate %13 RelaxedPrecision ; 5
  203. %2 = OpTypeVoid
  204. %3 = OpTypeFunction %2
  205. %6 = OpTypeBool
  206. %7 = OpConstantTrue %6 ; 6
  207. %10 = OpTypeInt 32 1
  208. %11 = OpTypePointer Private %10
  209. %12 = OpVariable %11 Private
  210. %13 = OpConstant %10 1
  211. %4 = OpFunction %2 None %3
  212. %5 = OpLabel
  213. OpReturn
  214. OpFunctionEnd
  215. )";
  216. auto context = BuildModule(kEnv, nullptr, shader, kReduceAssembleOption);
  217. CheckValid(kEnv, context.get());
  218. auto ops = finder.GetAvailableOpportunities(context.get(), 0);
  219. ASSERT_EQ(6, ops.size());
  220. for (auto& op : ops) {
  221. ASSERT_TRUE(op->PreconditionHolds());
  222. op->TryToApply();
  223. CheckValid(kEnv, context.get());
  224. }
  225. std::string after = R"(
  226. OpCapability Shader
  227. %1 = OpExtInstImport "GLSL.std.450"
  228. OpMemoryModel Logical GLSL450
  229. OpEntryPoint Fragment %4 "main"
  230. OpExecutionMode %4 OriginUpperLeft
  231. %2 = OpTypeVoid
  232. %3 = OpTypeFunction %2
  233. %6 = OpTypeBool ; 1
  234. %10 = OpTypeInt 32 1
  235. %11 = OpTypePointer Private %10
  236. %12 = OpVariable %11 Private ; 2
  237. %13 = OpConstant %10 1 ; 3
  238. %4 = OpFunction %2 None %3
  239. %5 = OpLabel
  240. OpReturn
  241. OpFunctionEnd
  242. )";
  243. CheckEqual(kEnv, after, context.get());
  244. ops = finder.GetAvailableOpportunities(context.get(), 0);
  245. ASSERT_EQ(3, ops.size());
  246. for (auto& op : ops) {
  247. ASSERT_TRUE(op->PreconditionHolds());
  248. op->TryToApply();
  249. CheckValid(kEnv, context.get());
  250. }
  251. std::string after_2 = R"(
  252. OpCapability Shader
  253. %1 = OpExtInstImport "GLSL.std.450"
  254. OpMemoryModel Logical GLSL450
  255. OpEntryPoint Fragment %4 "main"
  256. OpExecutionMode %4 OriginUpperLeft
  257. %2 = OpTypeVoid
  258. %3 = OpTypeFunction %2
  259. %10 = OpTypeInt 32 1
  260. %11 = OpTypePointer Private %10 ; 1
  261. %4 = OpFunction %2 None %3
  262. %5 = OpLabel
  263. OpReturn
  264. OpFunctionEnd
  265. )";
  266. CheckEqual(kEnv, after_2, context.get());
  267. ops = finder.GetAvailableOpportunities(context.get(), 0);
  268. ASSERT_EQ(1, ops.size());
  269. for (auto& op : ops) {
  270. ASSERT_TRUE(op->PreconditionHolds());
  271. op->TryToApply();
  272. CheckValid(kEnv, context.get());
  273. }
  274. std::string after_3 = R"(
  275. OpCapability Shader
  276. %1 = OpExtInstImport "GLSL.std.450"
  277. OpMemoryModel Logical GLSL450
  278. OpEntryPoint Fragment %4 "main"
  279. OpExecutionMode %4 OriginUpperLeft
  280. %2 = OpTypeVoid
  281. %3 = OpTypeFunction %2
  282. %10 = OpTypeInt 32 1 ; 1
  283. %4 = OpFunction %2 None %3
  284. %5 = OpLabel
  285. OpReturn
  286. OpFunctionEnd
  287. )";
  288. CheckEqual(kEnv, after_3, context.get());
  289. ops = finder.GetAvailableOpportunities(context.get(), 0);
  290. ASSERT_EQ(1, ops.size());
  291. for (auto& op : ops) {
  292. ASSERT_TRUE(op->PreconditionHolds());
  293. op->TryToApply();
  294. CheckValid(kEnv, context.get());
  295. }
  296. std::string after_4 = R"(
  297. OpCapability Shader
  298. %1 = OpExtInstImport "GLSL.std.450"
  299. OpMemoryModel Logical GLSL450
  300. OpEntryPoint Fragment %4 "main"
  301. OpExecutionMode %4 OriginUpperLeft
  302. %2 = OpTypeVoid
  303. %3 = OpTypeFunction %2
  304. %4 = OpFunction %2 None %3
  305. %5 = OpLabel
  306. OpReturn
  307. OpFunctionEnd
  308. )";
  309. CheckEqual(kEnv, after_4, context.get());
  310. ops = finder.GetAvailableOpportunities(context.get(), 0);
  311. ASSERT_EQ(0, ops.size());
  312. }
  313. TEST(RemoveUnusedResourceVariableTest, RemoveUnusedResourceVariables) {
  314. std::string shader = R"(
  315. OpCapability Shader
  316. %1 = OpExtInstImport "GLSL.std.450"
  317. OpMemoryModel Logical GLSL450
  318. OpEntryPoint GLCompute %4 "main"
  319. OpExecutionMode %4 LocalSize 1 1 1
  320. OpMemberDecorate %9 0 Offset 0
  321. OpDecorate %9 Block
  322. OpDecorate %11 DescriptorSet 0
  323. OpDecorate %11 Binding 1
  324. OpMemberDecorate %16 0 Offset 0
  325. OpMemberDecorate %16 1 Offset 4
  326. OpDecorate %16 Block
  327. OpDecorate %18 DescriptorSet 0
  328. OpDecorate %18 Binding 0
  329. OpMemberDecorate %19 0 Offset 0
  330. OpDecorate %19 BufferBlock
  331. OpDecorate %21 DescriptorSet 1
  332. OpDecorate %21 Binding 0
  333. OpMemberDecorate %22 0 Offset 0
  334. OpDecorate %22 Block
  335. OpDecorate %29 DescriptorSet 1
  336. OpDecorate %29 Binding 1
  337. OpDecorate %32 DescriptorSet 1
  338. OpDecorate %32 Binding 2
  339. OpDecorate %32 NonReadable
  340. %2 = OpTypeVoid
  341. %3 = OpTypeFunction %2
  342. %6 = OpTypeInt 32 1
  343. %9 = OpTypeStruct %6
  344. %10 = OpTypePointer Uniform %9
  345. %11 = OpVariable %10 Uniform
  346. %13 = OpTypePointer Uniform %6
  347. %16 = OpTypeStruct %6 %6
  348. %17 = OpTypePointer Uniform %16
  349. %18 = OpVariable %17 Uniform
  350. %19 = OpTypeStruct %6
  351. %20 = OpTypePointer Uniform %19
  352. %21 = OpVariable %20 Uniform
  353. %22 = OpTypeStruct %6
  354. %23 = OpTypePointer PushConstant %22
  355. %24 = OpVariable %23 PushConstant
  356. %25 = OpTypeFloat 32
  357. %26 = OpTypeImage %25 2D 0 0 0 1 Unknown
  358. %27 = OpTypeSampledImage %26
  359. %28 = OpTypePointer UniformConstant %27
  360. %29 = OpVariable %28 UniformConstant
  361. %30 = OpTypeImage %25 2D 0 0 0 2 Unknown
  362. %31 = OpTypePointer UniformConstant %30
  363. %32 = OpVariable %31 UniformConstant
  364. %4 = OpFunction %2 None %3
  365. %5 = OpLabel
  366. OpReturn
  367. OpFunctionEnd
  368. )";
  369. const auto env = SPV_ENV_UNIVERSAL_1_3;
  370. const auto consumer = nullptr;
  371. const auto context =
  372. BuildModule(env, consumer, shader, kReduceAssembleOption);
  373. auto ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
  374. .GetAvailableOpportunities(context.get(), 0);
  375. ASSERT_EQ(7, ops.size());
  376. for (auto& op : ops) {
  377. ASSERT_TRUE(op->PreconditionHolds());
  378. op->TryToApply();
  379. }
  380. std::string expected_1 = R"(
  381. OpCapability Shader
  382. %1 = OpExtInstImport "GLSL.std.450"
  383. OpMemoryModel Logical GLSL450
  384. OpEntryPoint GLCompute %4 "main"
  385. OpExecutionMode %4 LocalSize 1 1 1
  386. OpMemberDecorate %9 0 Offset 0
  387. OpDecorate %9 Block
  388. OpMemberDecorate %16 0 Offset 0
  389. OpMemberDecorate %16 1 Offset 4
  390. OpDecorate %16 Block
  391. OpMemberDecorate %19 0 Offset 0
  392. OpDecorate %19 BufferBlock
  393. OpMemberDecorate %22 0 Offset 0
  394. OpDecorate %22 Block
  395. %2 = OpTypeVoid
  396. %3 = OpTypeFunction %2
  397. %6 = OpTypeInt 32 1
  398. %9 = OpTypeStruct %6
  399. %10 = OpTypePointer Uniform %9
  400. %16 = OpTypeStruct %6 %6
  401. %17 = OpTypePointer Uniform %16
  402. %19 = OpTypeStruct %6
  403. %20 = OpTypePointer Uniform %19
  404. %22 = OpTypeStruct %6
  405. %23 = OpTypePointer PushConstant %22
  406. %25 = OpTypeFloat 32
  407. %26 = OpTypeImage %25 2D 0 0 0 1 Unknown
  408. %27 = OpTypeSampledImage %26
  409. %28 = OpTypePointer UniformConstant %27
  410. %30 = OpTypeImage %25 2D 0 0 0 2 Unknown
  411. %31 = OpTypePointer UniformConstant %30
  412. %4 = OpFunction %2 None %3
  413. %5 = OpLabel
  414. OpReturn
  415. OpFunctionEnd
  416. )";
  417. CheckEqual(env, expected_1, context.get());
  418. ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
  419. .GetAvailableOpportunities(context.get(), 0);
  420. ASSERT_EQ(6, ops.size());
  421. for (auto& op : ops) {
  422. ASSERT_TRUE(op->PreconditionHolds());
  423. op->TryToApply();
  424. }
  425. std::string expected_2 = R"(
  426. OpCapability Shader
  427. %1 = OpExtInstImport "GLSL.std.450"
  428. OpMemoryModel Logical GLSL450
  429. OpEntryPoint GLCompute %4 "main"
  430. OpExecutionMode %4 LocalSize 1 1 1
  431. OpMemberDecorate %9 0 Offset 0
  432. OpDecorate %9 Block
  433. OpMemberDecorate %16 0 Offset 0
  434. OpMemberDecorate %16 1 Offset 4
  435. OpDecorate %16 Block
  436. OpMemberDecorate %19 0 Offset 0
  437. OpDecorate %19 BufferBlock
  438. OpMemberDecorate %22 0 Offset 0
  439. OpDecorate %22 Block
  440. %2 = OpTypeVoid
  441. %3 = OpTypeFunction %2
  442. %6 = OpTypeInt 32 1
  443. %9 = OpTypeStruct %6
  444. %16 = OpTypeStruct %6 %6
  445. %19 = OpTypeStruct %6
  446. %22 = OpTypeStruct %6
  447. %25 = OpTypeFloat 32
  448. %26 = OpTypeImage %25 2D 0 0 0 1 Unknown
  449. %27 = OpTypeSampledImage %26
  450. %30 = OpTypeImage %25 2D 0 0 0 2 Unknown
  451. %4 = OpFunction %2 None %3
  452. %5 = OpLabel
  453. OpReturn
  454. OpFunctionEnd
  455. )";
  456. CheckEqual(env, expected_2, context.get());
  457. ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
  458. .GetAvailableOpportunities(context.get(), 0);
  459. ASSERT_EQ(6, ops.size());
  460. for (auto& op : ops) {
  461. ASSERT_TRUE(op->PreconditionHolds());
  462. op->TryToApply();
  463. }
  464. std::string expected_3 = R"(
  465. OpCapability Shader
  466. %1 = OpExtInstImport "GLSL.std.450"
  467. OpMemoryModel Logical GLSL450
  468. OpEntryPoint GLCompute %4 "main"
  469. OpExecutionMode %4 LocalSize 1 1 1
  470. %2 = OpTypeVoid
  471. %3 = OpTypeFunction %2
  472. %6 = OpTypeInt 32 1
  473. %25 = OpTypeFloat 32
  474. %26 = OpTypeImage %25 2D 0 0 0 1 Unknown
  475. %4 = OpFunction %2 None %3
  476. %5 = OpLabel
  477. OpReturn
  478. OpFunctionEnd
  479. )";
  480. CheckEqual(env, expected_3, context.get());
  481. }
  482. } // namespace
  483. } // namespace reduce
  484. } // namespace spvtools