remove_selection_test.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. // Copyright (c) 2019 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_selection_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(RemoveSelectionTest, OpportunityBecauseSameTargetBlock) {
  22. // A test with the following structure. The OpSelectionMerge instruction
  23. // should be removed.
  24. //
  25. // header
  26. // ||
  27. // block
  28. // |
  29. // merge
  30. std::string shader = 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 ESSL 310
  37. OpName %2 "main"
  38. %3 = OpTypeVoid
  39. %4 = OpTypeFunction %3
  40. %5 = OpTypeInt 32 1
  41. %6 = OpTypePointer Function %5
  42. %7 = OpTypeBool
  43. %8 = OpConstantTrue %7
  44. %2 = OpFunction %3 None %4
  45. %9 = OpLabel
  46. OpSelectionMerge %10 None
  47. OpBranchConditional %8 %11 %11
  48. %11 = OpLabel
  49. OpBranch %10
  50. %10 = OpLabel
  51. OpReturn
  52. OpFunctionEnd
  53. )";
  54. const auto env = SPV_ENV_UNIVERSAL_1_3;
  55. const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
  56. auto ops =
  57. RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  58. context.get(), 0);
  59. ASSERT_EQ(1, ops.size());
  60. ASSERT_TRUE(ops[0]->PreconditionHolds());
  61. ops[0]->TryToApply();
  62. CheckValid(env, context.get());
  63. std::string after = R"(
  64. OpCapability Shader
  65. %1 = OpExtInstImport "GLSL.std.450"
  66. OpMemoryModel Logical GLSL450
  67. OpEntryPoint Fragment %2 "main"
  68. OpExecutionMode %2 OriginUpperLeft
  69. OpSource ESSL 310
  70. OpName %2 "main"
  71. %3 = OpTypeVoid
  72. %4 = OpTypeFunction %3
  73. %5 = OpTypeInt 32 1
  74. %6 = OpTypePointer Function %5
  75. %7 = OpTypeBool
  76. %8 = OpConstantTrue %7
  77. %2 = OpFunction %3 None %4
  78. %9 = OpLabel
  79. OpBranchConditional %8 %11 %11
  80. %11 = OpLabel
  81. OpBranch %10
  82. %10 = OpLabel
  83. OpReturn
  84. OpFunctionEnd
  85. )";
  86. CheckEqual(env, after, context.get());
  87. ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  88. context.get(), 0);
  89. ASSERT_EQ(0, ops.size());
  90. }
  91. TEST(RemoveSelectionTest, OpportunityBecauseSameTargetBlockMerge) {
  92. // A test with the following structure. The OpSelectionMerge instruction
  93. // should be removed.
  94. //
  95. // header
  96. // ||
  97. // merge
  98. std::string shader = R"(
  99. OpCapability Shader
  100. %1 = OpExtInstImport "GLSL.std.450"
  101. OpMemoryModel Logical GLSL450
  102. OpEntryPoint Fragment %2 "main"
  103. OpExecutionMode %2 OriginUpperLeft
  104. OpSource ESSL 310
  105. OpName %2 "main"
  106. %3 = OpTypeVoid
  107. %4 = OpTypeFunction %3
  108. %5 = OpTypeInt 32 1
  109. %6 = OpTypePointer Function %5
  110. %7 = OpTypeBool
  111. %8 = OpConstantTrue %7
  112. %2 = OpFunction %3 None %4
  113. %9 = OpLabel
  114. OpSelectionMerge %10 None
  115. OpBranchConditional %8 %10 %10
  116. %10 = OpLabel
  117. OpReturn
  118. OpFunctionEnd
  119. )";
  120. const auto env = SPV_ENV_UNIVERSAL_1_3;
  121. const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
  122. auto ops =
  123. RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  124. context.get(), 0);
  125. ASSERT_EQ(1, ops.size());
  126. ASSERT_TRUE(ops[0]->PreconditionHolds());
  127. ops[0]->TryToApply();
  128. CheckValid(env, context.get());
  129. std::string after = R"(
  130. OpCapability Shader
  131. %1 = OpExtInstImport "GLSL.std.450"
  132. OpMemoryModel Logical GLSL450
  133. OpEntryPoint Fragment %2 "main"
  134. OpExecutionMode %2 OriginUpperLeft
  135. OpSource ESSL 310
  136. OpName %2 "main"
  137. %3 = OpTypeVoid
  138. %4 = OpTypeFunction %3
  139. %5 = OpTypeInt 32 1
  140. %6 = OpTypePointer Function %5
  141. %7 = OpTypeBool
  142. %8 = OpConstantTrue %7
  143. %2 = OpFunction %3 None %4
  144. %9 = OpLabel
  145. OpBranchConditional %8 %10 %10
  146. %10 = OpLabel
  147. OpReturn
  148. OpFunctionEnd
  149. )";
  150. CheckEqual(env, after, context.get());
  151. ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  152. context.get(), 0);
  153. ASSERT_EQ(0, ops.size());
  154. }
  155. TEST(RemoveSelectionTest, NoOpportunityBecauseDifferentTargetBlocksOneMerge) {
  156. // A test with the following structure. The OpSelectionMerge instruction
  157. // should NOT be removed.
  158. //
  159. // header
  160. // | |
  161. // | block
  162. // | |
  163. // merge
  164. std::string shader = R"(
  165. OpCapability Shader
  166. %1 = OpExtInstImport "GLSL.std.450"
  167. OpMemoryModel Logical GLSL450
  168. OpEntryPoint Fragment %2 "main"
  169. OpExecutionMode %2 OriginUpperLeft
  170. OpSource ESSL 310
  171. OpName %2 "main"
  172. %3 = OpTypeVoid
  173. %4 = OpTypeFunction %3
  174. %5 = OpTypeInt 32 1
  175. %6 = OpTypePointer Function %5
  176. %7 = OpTypeBool
  177. %8 = OpConstantTrue %7
  178. %2 = OpFunction %3 None %4
  179. %9 = OpLabel
  180. OpSelectionMerge %10 None
  181. OpBranchConditional %8 %10 %11
  182. %11 = OpLabel
  183. OpBranch %10
  184. %10 = OpLabel
  185. OpReturn
  186. OpFunctionEnd
  187. )";
  188. const auto env = SPV_ENV_UNIVERSAL_1_3;
  189. const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
  190. auto ops =
  191. RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  192. context.get(), 0);
  193. ASSERT_EQ(0, ops.size());
  194. }
  195. TEST(RemoveSelectionTest, NoOpportunityBecauseDifferentTargetBlocks) {
  196. // A test with the following structure. The OpSelectionMerge instruction
  197. // should NOT be removed.
  198. //
  199. // header
  200. // | |
  201. // b b
  202. // | |
  203. // merge
  204. std::string shader = R"(
  205. OpCapability Shader
  206. %1 = OpExtInstImport "GLSL.std.450"
  207. OpMemoryModel Logical GLSL450
  208. OpEntryPoint Fragment %2 "main"
  209. OpExecutionMode %2 OriginUpperLeft
  210. OpSource ESSL 310
  211. OpName %2 "main"
  212. %3 = OpTypeVoid
  213. %4 = OpTypeFunction %3
  214. %5 = OpTypeInt 32 1
  215. %6 = OpTypePointer Function %5
  216. %7 = OpTypeBool
  217. %8 = OpConstantTrue %7
  218. %2 = OpFunction %3 None %4
  219. %9 = OpLabel
  220. OpSelectionMerge %10 None
  221. OpBranchConditional %8 %11 %12
  222. %11 = OpLabel
  223. OpBranch %10
  224. %12 = OpLabel
  225. OpBranch %10
  226. %10 = OpLabel
  227. OpReturn
  228. OpFunctionEnd
  229. )";
  230. const auto env = SPV_ENV_UNIVERSAL_1_3;
  231. const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
  232. auto ops =
  233. RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  234. context.get(), 0);
  235. ASSERT_EQ(0, ops.size());
  236. }
  237. TEST(RemoveSelectionTest, NoOpportunityBecauseMergeUsed) {
  238. // A test with the following structure. The OpSelectionMerge instruction
  239. // should NOT be removed.
  240. //
  241. // header
  242. // ||
  243. // block
  244. // | |
  245. // | block
  246. // | |
  247. // merge
  248. std::string shader = R"(
  249. OpCapability Shader
  250. %1 = OpExtInstImport "GLSL.std.450"
  251. OpMemoryModel Logical GLSL450
  252. OpEntryPoint Fragment %2 "main"
  253. OpExecutionMode %2 OriginUpperLeft
  254. OpSource ESSL 310
  255. OpName %2 "main"
  256. %3 = OpTypeVoid
  257. %4 = OpTypeFunction %3
  258. %5 = OpTypeInt 32 1
  259. %6 = OpTypePointer Function %5
  260. %7 = OpTypeBool
  261. %8 = OpConstantTrue %7
  262. %2 = OpFunction %3 None %4
  263. %9 = OpLabel
  264. OpSelectionMerge %10 None
  265. OpBranchConditional %8 %11 %12
  266. %11 = OpLabel
  267. OpBranchConditional %8 %10 %12
  268. %12 = OpLabel
  269. OpBranch %10
  270. %10 = OpLabel
  271. OpReturn
  272. OpFunctionEnd
  273. )";
  274. const auto env = SPV_ENV_UNIVERSAL_1_3;
  275. const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
  276. auto ops =
  277. RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  278. context.get(), 0);
  279. ASSERT_EQ(0, ops.size());
  280. }
  281. TEST(RemoveSelectionTest, OpportunityBecauseLoopMergeUsed) {
  282. // A test with the following structure. The OpSelectionMerge instruction
  283. // should be removed.
  284. //
  285. // loop header
  286. // |
  287. // |
  288. // s.header
  289. // ||
  290. // block
  291. // | |
  292. // | |
  293. // | | ^ (to loop header)
  294. // s.merge | |
  295. // | / loop continue target (unreachable)
  296. // loop merge
  297. //
  298. //
  299. // which becomes:
  300. //
  301. // loop header
  302. // |
  303. // |
  304. // block
  305. // ||
  306. // block
  307. // | |
  308. // | |
  309. // | | ^ (to loop header)
  310. // block | |
  311. // | / loop continue target (unreachable)
  312. // loop merge
  313. std::string shader = R"(
  314. OpCapability Shader
  315. %1 = OpExtInstImport "GLSL.std.450"
  316. OpMemoryModel Logical GLSL450
  317. OpEntryPoint Fragment %2 "main"
  318. OpExecutionMode %2 OriginUpperLeft
  319. OpSource ESSL 310
  320. OpName %2 "main"
  321. %3 = OpTypeVoid
  322. %4 = OpTypeFunction %3
  323. %5 = OpTypeInt 32 1
  324. %6 = OpTypePointer Function %5
  325. %7 = OpTypeBool
  326. %8 = OpConstantTrue %7
  327. %2 = OpFunction %3 None %4
  328. %9 = OpLabel
  329. OpBranch %10
  330. %10 = OpLabel
  331. OpLoopMerge %11 %12 None
  332. OpBranch %13
  333. %13 = OpLabel
  334. OpSelectionMerge %14 None
  335. OpBranchConditional %8 %15 %15
  336. %15 = OpLabel
  337. OpBranchConditional %8 %14 %11
  338. %14 = OpLabel
  339. OpBranch %11
  340. %12 = OpLabel
  341. OpBranch %10
  342. %11 = OpLabel
  343. OpReturn
  344. OpFunctionEnd
  345. )";
  346. const auto env = SPV_ENV_UNIVERSAL_1_3;
  347. const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
  348. CheckValid(env, context.get());
  349. auto ops =
  350. RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  351. context.get(), 0);
  352. ASSERT_EQ(1, ops.size());
  353. ASSERT_TRUE(ops[0]->PreconditionHolds());
  354. ops[0]->TryToApply();
  355. CheckValid(env, context.get());
  356. std::string after = R"(
  357. OpCapability Shader
  358. %1 = OpExtInstImport "GLSL.std.450"
  359. OpMemoryModel Logical GLSL450
  360. OpEntryPoint Fragment %2 "main"
  361. OpExecutionMode %2 OriginUpperLeft
  362. OpSource ESSL 310
  363. OpName %2 "main"
  364. %3 = OpTypeVoid
  365. %4 = OpTypeFunction %3
  366. %5 = OpTypeInt 32 1
  367. %6 = OpTypePointer Function %5
  368. %7 = OpTypeBool
  369. %8 = OpConstantTrue %7
  370. %2 = OpFunction %3 None %4
  371. %9 = OpLabel
  372. OpBranch %10
  373. %10 = OpLabel
  374. OpLoopMerge %11 %12 None
  375. OpBranch %13
  376. %13 = OpLabel
  377. OpBranchConditional %8 %15 %15
  378. %15 = OpLabel
  379. OpBranchConditional %8 %14 %11
  380. %14 = OpLabel
  381. OpBranch %11
  382. %12 = OpLabel
  383. OpBranch %10
  384. %11 = OpLabel
  385. OpReturn
  386. OpFunctionEnd
  387. )";
  388. CheckEqual(env, after, context.get());
  389. ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  390. context.get(), 0);
  391. ASSERT_EQ(0, ops.size());
  392. }
  393. TEST(RemoveSelectionTest, OpportunityBecauseLoopContinueUsed) {
  394. // A test with the following structure. The OpSelectionMerge instruction
  395. // should be removed.
  396. //
  397. // loop header
  398. // |
  399. // |
  400. // s.header
  401. // ||
  402. // block
  403. // | |
  404. // | |
  405. // | | ^ (to loop header)
  406. // s.merge | |
  407. // | loop continue target
  408. // loop merge
  409. //
  410. //
  411. // which becomes:
  412. //
  413. // loop header
  414. // |
  415. // |
  416. // block
  417. // ||
  418. // block
  419. // | |
  420. // | |
  421. // | | ^ (to loop header)
  422. // block | |
  423. // | loop continue target
  424. // loop merge
  425. std::string shader = R"(
  426. OpCapability Shader
  427. %1 = OpExtInstImport "GLSL.std.450"
  428. OpMemoryModel Logical GLSL450
  429. OpEntryPoint Fragment %2 "main"
  430. OpExecutionMode %2 OriginUpperLeft
  431. OpSource ESSL 310
  432. OpName %2 "main"
  433. %3 = OpTypeVoid
  434. %4 = OpTypeFunction %3
  435. %5 = OpTypeInt 32 1
  436. %6 = OpTypePointer Function %5
  437. %7 = OpTypeBool
  438. %8 = OpConstantTrue %7
  439. %2 = OpFunction %3 None %4
  440. %9 = OpLabel
  441. OpBranch %10
  442. %10 = OpLabel
  443. OpLoopMerge %11 %12 None
  444. OpBranch %13
  445. %13 = OpLabel
  446. OpSelectionMerge %14 None
  447. OpBranchConditional %8 %15 %15
  448. %15 = OpLabel
  449. OpBranchConditional %8 %14 %12
  450. %14 = OpLabel
  451. OpBranch %11
  452. %12 = OpLabel
  453. OpBranch %10
  454. %11 = OpLabel
  455. OpReturn
  456. OpFunctionEnd
  457. )";
  458. const auto env = SPV_ENV_UNIVERSAL_1_3;
  459. const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
  460. CheckValid(env, context.get());
  461. auto ops =
  462. RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  463. context.get(), 0);
  464. ASSERT_EQ(1, ops.size());
  465. ASSERT_TRUE(ops[0]->PreconditionHolds());
  466. ops[0]->TryToApply();
  467. CheckValid(env, context.get());
  468. std::string after = R"(
  469. OpCapability Shader
  470. %1 = OpExtInstImport "GLSL.std.450"
  471. OpMemoryModel Logical GLSL450
  472. OpEntryPoint Fragment %2 "main"
  473. OpExecutionMode %2 OriginUpperLeft
  474. OpSource ESSL 310
  475. OpName %2 "main"
  476. %3 = OpTypeVoid
  477. %4 = OpTypeFunction %3
  478. %5 = OpTypeInt 32 1
  479. %6 = OpTypePointer Function %5
  480. %7 = OpTypeBool
  481. %8 = OpConstantTrue %7
  482. %2 = OpFunction %3 None %4
  483. %9 = OpLabel
  484. OpBranch %10
  485. %10 = OpLabel
  486. OpLoopMerge %11 %12 None
  487. OpBranch %13
  488. %13 = OpLabel
  489. OpBranchConditional %8 %15 %15
  490. %15 = OpLabel
  491. OpBranchConditional %8 %14 %12
  492. %14 = OpLabel
  493. OpBranch %11
  494. %12 = OpLabel
  495. OpBranch %10
  496. %11 = OpLabel
  497. OpReturn
  498. OpFunctionEnd
  499. )";
  500. CheckEqual(env, after, context.get());
  501. ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
  502. context.get(), 0);
  503. ASSERT_EQ(0, ops.size());
  504. }
  505. } // namespace
  506. } // namespace reduce
  507. } // namespace spvtools