merge_blocks_test.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  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/merge_blocks_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(MergeBlocksReductionPassTest, BasicCheck) {
  22. std::string shader = R"(
  23. OpCapability Shader
  24. %1 = OpExtInstImport "GLSL.std.450"
  25. OpMemoryModel Logical GLSL450
  26. OpEntryPoint Fragment %4 "main"
  27. OpExecutionMode %4 OriginUpperLeft
  28. OpSource ESSL 310
  29. OpName %4 "main"
  30. OpName %8 "x"
  31. %2 = OpTypeVoid
  32. %3 = OpTypeFunction %2
  33. %6 = OpTypeInt 32 1
  34. %7 = OpTypePointer Function %6
  35. %9 = OpConstant %6 1
  36. %10 = OpConstant %6 2
  37. %11 = OpConstant %6 3
  38. %12 = OpConstant %6 4
  39. %4 = OpFunction %2 None %3
  40. %5 = OpLabel
  41. %8 = OpVariable %7 Function
  42. OpBranch %13
  43. %13 = OpLabel
  44. OpStore %8 %9
  45. OpBranch %14
  46. %14 = OpLabel
  47. OpStore %8 %10
  48. OpBranch %15
  49. %15 = OpLabel
  50. OpStore %8 %11
  51. OpBranch %16
  52. %16 = OpLabel
  53. OpStore %8 %12
  54. OpBranch %17
  55. %17 = OpLabel
  56. OpReturn
  57. OpFunctionEnd
  58. )";
  59. const auto env = SPV_ENV_UNIVERSAL_1_3;
  60. const auto consumer = nullptr;
  61. const auto context =
  62. BuildModule(env, consumer, shader, kReduceAssembleOption);
  63. const auto ops =
  64. MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
  65. context.get(), 0);
  66. ASSERT_EQ(5, ops.size());
  67. // Try order 3, 0, 2, 4, 1
  68. ASSERT_TRUE(ops[3]->PreconditionHolds());
  69. ops[3]->TryToApply();
  70. std::string after_op_3 = R"(
  71. OpCapability Shader
  72. %1 = OpExtInstImport "GLSL.std.450"
  73. OpMemoryModel Logical GLSL450
  74. OpEntryPoint Fragment %4 "main"
  75. OpExecutionMode %4 OriginUpperLeft
  76. OpSource ESSL 310
  77. OpName %4 "main"
  78. OpName %8 "x"
  79. %2 = OpTypeVoid
  80. %3 = OpTypeFunction %2
  81. %6 = OpTypeInt 32 1
  82. %7 = OpTypePointer Function %6
  83. %9 = OpConstant %6 1
  84. %10 = OpConstant %6 2
  85. %11 = OpConstant %6 3
  86. %12 = OpConstant %6 4
  87. %4 = OpFunction %2 None %3
  88. %5 = OpLabel
  89. %8 = OpVariable %7 Function
  90. OpBranch %13
  91. %13 = OpLabel
  92. OpStore %8 %9
  93. OpBranch %14
  94. %14 = OpLabel
  95. OpStore %8 %10
  96. OpBranch %15
  97. %15 = OpLabel
  98. OpStore %8 %11
  99. OpStore %8 %12
  100. OpBranch %17
  101. %17 = OpLabel
  102. OpReturn
  103. OpFunctionEnd
  104. )";
  105. CheckEqual(env, after_op_3, context.get());
  106. ASSERT_TRUE(ops[0]->PreconditionHolds());
  107. ops[0]->TryToApply();
  108. std::string after_op_0 = R"(
  109. OpCapability Shader
  110. %1 = OpExtInstImport "GLSL.std.450"
  111. OpMemoryModel Logical GLSL450
  112. OpEntryPoint Fragment %4 "main"
  113. OpExecutionMode %4 OriginUpperLeft
  114. OpSource ESSL 310
  115. OpName %4 "main"
  116. OpName %8 "x"
  117. %2 = OpTypeVoid
  118. %3 = OpTypeFunction %2
  119. %6 = OpTypeInt 32 1
  120. %7 = OpTypePointer Function %6
  121. %9 = OpConstant %6 1
  122. %10 = OpConstant %6 2
  123. %11 = OpConstant %6 3
  124. %12 = OpConstant %6 4
  125. %4 = OpFunction %2 None %3
  126. %5 = OpLabel
  127. %8 = OpVariable %7 Function
  128. OpStore %8 %9
  129. OpBranch %14
  130. %14 = OpLabel
  131. OpStore %8 %10
  132. OpBranch %15
  133. %15 = OpLabel
  134. OpStore %8 %11
  135. OpStore %8 %12
  136. OpBranch %17
  137. %17 = OpLabel
  138. OpReturn
  139. OpFunctionEnd
  140. )";
  141. CheckEqual(env, after_op_0, context.get());
  142. ASSERT_TRUE(ops[2]->PreconditionHolds());
  143. ops[2]->TryToApply();
  144. std::string after_op_2 = R"(
  145. OpCapability Shader
  146. %1 = OpExtInstImport "GLSL.std.450"
  147. OpMemoryModel Logical GLSL450
  148. OpEntryPoint Fragment %4 "main"
  149. OpExecutionMode %4 OriginUpperLeft
  150. OpSource ESSL 310
  151. OpName %4 "main"
  152. OpName %8 "x"
  153. %2 = OpTypeVoid
  154. %3 = OpTypeFunction %2
  155. %6 = OpTypeInt 32 1
  156. %7 = OpTypePointer Function %6
  157. %9 = OpConstant %6 1
  158. %10 = OpConstant %6 2
  159. %11 = OpConstant %6 3
  160. %12 = OpConstant %6 4
  161. %4 = OpFunction %2 None %3
  162. %5 = OpLabel
  163. %8 = OpVariable %7 Function
  164. OpStore %8 %9
  165. OpBranch %14
  166. %14 = OpLabel
  167. OpStore %8 %10
  168. OpStore %8 %11
  169. OpStore %8 %12
  170. OpBranch %17
  171. %17 = OpLabel
  172. OpReturn
  173. OpFunctionEnd
  174. )";
  175. CheckEqual(env, after_op_2, context.get());
  176. ASSERT_TRUE(ops[4]->PreconditionHolds());
  177. ops[4]->TryToApply();
  178. std::string after_op_4 = R"(
  179. OpCapability Shader
  180. %1 = OpExtInstImport "GLSL.std.450"
  181. OpMemoryModel Logical GLSL450
  182. OpEntryPoint Fragment %4 "main"
  183. OpExecutionMode %4 OriginUpperLeft
  184. OpSource ESSL 310
  185. OpName %4 "main"
  186. OpName %8 "x"
  187. %2 = OpTypeVoid
  188. %3 = OpTypeFunction %2
  189. %6 = OpTypeInt 32 1
  190. %7 = OpTypePointer Function %6
  191. %9 = OpConstant %6 1
  192. %10 = OpConstant %6 2
  193. %11 = OpConstant %6 3
  194. %12 = OpConstant %6 4
  195. %4 = OpFunction %2 None %3
  196. %5 = OpLabel
  197. %8 = OpVariable %7 Function
  198. OpStore %8 %9
  199. OpBranch %14
  200. %14 = OpLabel
  201. OpStore %8 %10
  202. OpStore %8 %11
  203. OpStore %8 %12
  204. OpReturn
  205. OpFunctionEnd
  206. )";
  207. CheckEqual(env, after_op_4, context.get());
  208. ASSERT_TRUE(ops[1]->PreconditionHolds());
  209. ops[1]->TryToApply();
  210. std::string after_op_1 = R"(
  211. OpCapability Shader
  212. %1 = OpExtInstImport "GLSL.std.450"
  213. OpMemoryModel Logical GLSL450
  214. OpEntryPoint Fragment %4 "main"
  215. OpExecutionMode %4 OriginUpperLeft
  216. OpSource ESSL 310
  217. OpName %4 "main"
  218. OpName %8 "x"
  219. %2 = OpTypeVoid
  220. %3 = OpTypeFunction %2
  221. %6 = OpTypeInt 32 1
  222. %7 = OpTypePointer Function %6
  223. %9 = OpConstant %6 1
  224. %10 = OpConstant %6 2
  225. %11 = OpConstant %6 3
  226. %12 = OpConstant %6 4
  227. %4 = OpFunction %2 None %3
  228. %5 = OpLabel
  229. %8 = OpVariable %7 Function
  230. OpStore %8 %9
  231. OpStore %8 %10
  232. OpStore %8 %11
  233. OpStore %8 %12
  234. OpReturn
  235. OpFunctionEnd
  236. )";
  237. CheckEqual(env, after_op_1, context.get());
  238. }
  239. TEST(MergeBlocksReductionPassTest, Loops) {
  240. std::string shader = R"(
  241. OpCapability Shader
  242. %1 = OpExtInstImport "GLSL.std.450"
  243. OpMemoryModel Logical GLSL450
  244. OpEntryPoint Fragment %4 "main"
  245. OpExecutionMode %4 OriginUpperLeft
  246. OpSource ESSL 310
  247. OpName %4 "main"
  248. OpName %8 "x"
  249. OpName %10 "i"
  250. OpName %29 "i"
  251. %2 = OpTypeVoid
  252. %3 = OpTypeFunction %2
  253. %6 = OpTypeInt 32 1
  254. %7 = OpTypePointer Function %6
  255. %9 = OpConstant %6 1
  256. %11 = OpConstant %6 0
  257. %18 = OpConstant %6 10
  258. %19 = OpTypeBool
  259. %4 = OpFunction %2 None %3
  260. %5 = OpLabel
  261. %8 = OpVariable %7 Function
  262. %10 = OpVariable %7 Function
  263. %29 = OpVariable %7 Function
  264. OpStore %8 %9
  265. OpBranch %45
  266. %45 = OpLabel
  267. OpStore %10 %11
  268. OpBranch %12
  269. %12 = OpLabel
  270. OpLoopMerge %14 %15 None
  271. OpBranch %16
  272. %16 = OpLabel
  273. %17 = OpLoad %6 %10
  274. OpBranch %46
  275. %46 = OpLabel
  276. %20 = OpSLessThan %19 %17 %18
  277. OpBranchConditional %20 %13 %14
  278. %13 = OpLabel
  279. %21 = OpLoad %6 %10
  280. OpBranch %47
  281. %47 = OpLabel
  282. %22 = OpLoad %6 %8
  283. %23 = OpIAdd %6 %22 %21
  284. OpStore %8 %23
  285. %24 = OpLoad %6 %10
  286. %25 = OpLoad %6 %8
  287. %26 = OpIAdd %6 %25 %24
  288. OpStore %8 %26
  289. OpBranch %48
  290. %48 = OpLabel
  291. OpBranch %15
  292. %15 = OpLabel
  293. %27 = OpLoad %6 %10
  294. %28 = OpIAdd %6 %27 %9
  295. OpStore %10 %28
  296. OpBranch %12
  297. %14 = OpLabel
  298. OpStore %29 %11
  299. OpBranch %49
  300. %49 = OpLabel
  301. OpBranch %30
  302. %30 = OpLabel
  303. OpLoopMerge %32 %33 None
  304. OpBranch %34
  305. %34 = OpLabel
  306. %35 = OpLoad %6 %29
  307. %36 = OpSLessThan %19 %35 %18
  308. OpBranch %50
  309. %50 = OpLabel
  310. OpBranchConditional %36 %31 %32
  311. %31 = OpLabel
  312. %37 = OpLoad %6 %29
  313. %38 = OpLoad %6 %8
  314. %39 = OpIAdd %6 %38 %37
  315. OpStore %8 %39
  316. %40 = OpLoad %6 %29
  317. %41 = OpLoad %6 %8
  318. %42 = OpIAdd %6 %41 %40
  319. OpStore %8 %42
  320. OpBranch %33
  321. %33 = OpLabel
  322. %43 = OpLoad %6 %29
  323. %44 = OpIAdd %6 %43 %9
  324. OpBranch %51
  325. %51 = OpLabel
  326. OpStore %29 %44
  327. OpBranch %30
  328. %32 = OpLabel
  329. OpReturn
  330. OpFunctionEnd
  331. )";
  332. const auto env = SPV_ENV_UNIVERSAL_1_3;
  333. const auto consumer = nullptr;
  334. const auto context =
  335. BuildModule(env, consumer, shader, kReduceAssembleOption);
  336. const auto ops =
  337. MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
  338. context.get(), 0);
  339. ASSERT_EQ(11, ops.size());
  340. for (auto& ri : ops) {
  341. ASSERT_TRUE(ri->PreconditionHolds());
  342. ri->TryToApply();
  343. }
  344. std::string after = R"(
  345. OpCapability Shader
  346. %1 = OpExtInstImport "GLSL.std.450"
  347. OpMemoryModel Logical GLSL450
  348. OpEntryPoint Fragment %4 "main"
  349. OpExecutionMode %4 OriginUpperLeft
  350. OpSource ESSL 310
  351. OpName %4 "main"
  352. OpName %8 "x"
  353. OpName %10 "i"
  354. OpName %29 "i"
  355. %2 = OpTypeVoid
  356. %3 = OpTypeFunction %2
  357. %6 = OpTypeInt 32 1
  358. %7 = OpTypePointer Function %6
  359. %9 = OpConstant %6 1
  360. %11 = OpConstant %6 0
  361. %18 = OpConstant %6 10
  362. %19 = OpTypeBool
  363. %4 = OpFunction %2 None %3
  364. %5 = OpLabel
  365. %8 = OpVariable %7 Function
  366. %10 = OpVariable %7 Function
  367. %29 = OpVariable %7 Function
  368. OpStore %8 %9
  369. OpStore %10 %11
  370. OpBranch %12
  371. %12 = OpLabel
  372. %17 = OpLoad %6 %10
  373. %20 = OpSLessThan %19 %17 %18
  374. OpLoopMerge %14 %13 None
  375. OpBranchConditional %20 %13 %14
  376. %13 = OpLabel
  377. %21 = OpLoad %6 %10
  378. %22 = OpLoad %6 %8
  379. %23 = OpIAdd %6 %22 %21
  380. OpStore %8 %23
  381. %24 = OpLoad %6 %10
  382. %25 = OpLoad %6 %8
  383. %26 = OpIAdd %6 %25 %24
  384. OpStore %8 %26
  385. %27 = OpLoad %6 %10
  386. %28 = OpIAdd %6 %27 %9
  387. OpStore %10 %28
  388. OpBranch %12
  389. %14 = OpLabel
  390. OpStore %29 %11
  391. OpBranch %30
  392. %30 = OpLabel
  393. %35 = OpLoad %6 %29
  394. %36 = OpSLessThan %19 %35 %18
  395. OpLoopMerge %32 %31 None
  396. OpBranchConditional %36 %31 %32
  397. %31 = OpLabel
  398. %37 = OpLoad %6 %29
  399. %38 = OpLoad %6 %8
  400. %39 = OpIAdd %6 %38 %37
  401. OpStore %8 %39
  402. %40 = OpLoad %6 %29
  403. %41 = OpLoad %6 %8
  404. %42 = OpIAdd %6 %41 %40
  405. OpStore %8 %42
  406. %43 = OpLoad %6 %29
  407. %44 = OpIAdd %6 %43 %9
  408. OpStore %29 %44
  409. OpBranch %30
  410. %32 = OpLabel
  411. OpReturn
  412. OpFunctionEnd
  413. )";
  414. CheckEqual(env, after, context.get());
  415. }
  416. TEST(MergeBlocksReductionPassTest, MergeWithOpPhi) {
  417. std::string shader = R"(
  418. OpCapability Shader
  419. %1 = OpExtInstImport "GLSL.std.450"
  420. OpMemoryModel Logical GLSL450
  421. OpEntryPoint Fragment %4 "main"
  422. OpExecutionMode %4 OriginUpperLeft
  423. OpSource ESSL 310
  424. OpName %4 "main"
  425. OpName %8 "x"
  426. OpName %10 "y"
  427. %2 = OpTypeVoid
  428. %3 = OpTypeFunction %2
  429. %6 = OpTypeInt 32 1
  430. %7 = OpTypePointer Function %6
  431. %9 = OpConstant %6 1
  432. %4 = OpFunction %2 None %3
  433. %5 = OpLabel
  434. %8 = OpVariable %7 Function
  435. %10 = OpVariable %7 Function
  436. OpStore %8 %9
  437. %11 = OpLoad %6 %8
  438. OpBranch %12
  439. %12 = OpLabel
  440. %13 = OpPhi %6 %11 %5
  441. OpStore %10 %13
  442. OpReturn
  443. OpFunctionEnd
  444. )";
  445. const auto env = SPV_ENV_UNIVERSAL_1_3;
  446. const auto consumer = nullptr;
  447. const auto context =
  448. BuildModule(env, consumer, shader, kReduceAssembleOption);
  449. const auto ops =
  450. MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
  451. context.get(), 0);
  452. ASSERT_EQ(1, ops.size());
  453. ASSERT_TRUE(ops[0]->PreconditionHolds());
  454. ops[0]->TryToApply();
  455. std::string after = R"(
  456. OpCapability Shader
  457. %1 = OpExtInstImport "GLSL.std.450"
  458. OpMemoryModel Logical GLSL450
  459. OpEntryPoint Fragment %4 "main"
  460. OpExecutionMode %4 OriginUpperLeft
  461. OpSource ESSL 310
  462. OpName %4 "main"
  463. OpName %8 "x"
  464. OpName %10 "y"
  465. %2 = OpTypeVoid
  466. %3 = OpTypeFunction %2
  467. %6 = OpTypeInt 32 1
  468. %7 = OpTypePointer Function %6
  469. %9 = OpConstant %6 1
  470. %4 = OpFunction %2 None %3
  471. %5 = OpLabel
  472. %8 = OpVariable %7 Function
  473. %10 = OpVariable %7 Function
  474. OpStore %8 %9
  475. %11 = OpLoad %6 %8
  476. OpStore %10 %11
  477. OpReturn
  478. OpFunctionEnd
  479. )";
  480. CheckEqual(env, after, context.get());
  481. }
  482. void MergeBlocksReductionPassTest_LoopReturn_Helper(bool reverse) {
  483. // A merge block opportunity stores a block that can be merged with its
  484. // predecessor.
  485. // Given blocks A -> B -> C:
  486. // This test demonstrates how merging B->C can invalidate
  487. // the opportunity of merging A->B, and vice-versa. E.g.
  488. // B->C are merged: B is now terminated with OpReturn.
  489. // A->B can now no longer be merged because A is a loop header, which
  490. // cannot be terminated with OpReturn.
  491. std::string shader = R"(
  492. OpCapability Shader
  493. %1 = OpExtInstImport "GLSL.std.450"
  494. OpMemoryModel Logical GLSL450
  495. OpEntryPoint Fragment %2 "main"
  496. OpExecutionMode %2 OriginUpperLeft
  497. OpSource ESSL 310
  498. OpName %2 "main"
  499. %3 = OpTypeVoid
  500. %4 = OpTypeFunction %3
  501. %5 = OpTypeInt 32 1
  502. %6 = OpTypePointer Function %5
  503. %7 = OpTypeBool
  504. %8 = OpConstantFalse %7
  505. %2 = OpFunction %3 None %4
  506. %9 = OpLabel
  507. OpBranch %10
  508. %10 = OpLabel ; A (loop header)
  509. OpLoopMerge %13 %12 None
  510. OpBranch %11
  511. %12 = OpLabel ; (unreachable continue block)
  512. OpBranch %10
  513. %11 = OpLabel ; B
  514. OpBranch %15
  515. %15 = OpLabel ; C
  516. OpReturn
  517. %13 = OpLabel ; (unreachable merge block)
  518. OpReturn
  519. OpFunctionEnd
  520. )";
  521. const auto env = SPV_ENV_UNIVERSAL_1_3;
  522. const auto consumer = nullptr;
  523. const auto context =
  524. BuildModule(env, consumer, shader, kReduceAssembleOption);
  525. ASSERT_NE(context.get(), nullptr);
  526. auto opportunities =
  527. MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
  528. context.get(), 0);
  529. // A->B and B->C
  530. ASSERT_EQ(opportunities.size(), 2);
  531. // Test applying opportunities in both orders.
  532. if (reverse) {
  533. std::reverse(opportunities.begin(), opportunities.end());
  534. }
  535. size_t num_applied = 0;
  536. for (auto& ri : opportunities) {
  537. if (ri->PreconditionHolds()) {
  538. ri->TryToApply();
  539. ++num_applied;
  540. }
  541. }
  542. // Only 1 opportunity can be applied, as both disable each other.
  543. ASSERT_EQ(num_applied, 1);
  544. std::string after = R"(
  545. OpCapability Shader
  546. %1 = OpExtInstImport "GLSL.std.450"
  547. OpMemoryModel Logical GLSL450
  548. OpEntryPoint Fragment %2 "main"
  549. OpExecutionMode %2 OriginUpperLeft
  550. OpSource ESSL 310
  551. OpName %2 "main"
  552. %3 = OpTypeVoid
  553. %4 = OpTypeFunction %3
  554. %5 = OpTypeInt 32 1
  555. %6 = OpTypePointer Function %5
  556. %7 = OpTypeBool
  557. %8 = OpConstantFalse %7
  558. %2 = OpFunction %3 None %4
  559. %9 = OpLabel
  560. OpBranch %10
  561. %10 = OpLabel ; A-B (loop header)
  562. OpLoopMerge %13 %12 None
  563. OpBranch %15
  564. %12 = OpLabel ; (unreachable continue block)
  565. OpBranch %10
  566. %15 = OpLabel ; C
  567. OpReturn
  568. %13 = OpLabel ; (unreachable merge block)
  569. OpReturn
  570. OpFunctionEnd
  571. )";
  572. // The only difference is the labels.
  573. std::string after_reversed = R"(
  574. OpCapability Shader
  575. %1 = OpExtInstImport "GLSL.std.450"
  576. OpMemoryModel Logical GLSL450
  577. OpEntryPoint Fragment %2 "main"
  578. OpExecutionMode %2 OriginUpperLeft
  579. OpSource ESSL 310
  580. OpName %2 "main"
  581. %3 = OpTypeVoid
  582. %4 = OpTypeFunction %3
  583. %5 = OpTypeInt 32 1
  584. %6 = OpTypePointer Function %5
  585. %7 = OpTypeBool
  586. %8 = OpConstantFalse %7
  587. %2 = OpFunction %3 None %4
  588. %9 = OpLabel
  589. OpBranch %10
  590. %10 = OpLabel ; A (loop header)
  591. OpLoopMerge %13 %12 None
  592. OpBranch %11
  593. %12 = OpLabel ; (unreachable continue block)
  594. OpBranch %10
  595. %11 = OpLabel ; B-C
  596. OpReturn
  597. %13 = OpLabel ; (unreachable merge block)
  598. OpReturn
  599. OpFunctionEnd
  600. )";
  601. CheckEqual(env, reverse ? after_reversed : after, context.get());
  602. }
  603. TEST(MergeBlocksReductionPassTest, LoopReturn) {
  604. MergeBlocksReductionPassTest_LoopReturn_Helper(false);
  605. }
  606. TEST(MergeBlocksReductionPassTest, LoopReturnReverse) {
  607. MergeBlocksReductionPassTest_LoopReturn_Helper(true);
  608. }
  609. TEST(MergeBlocksReductionPassTest, MergeUnreachable) {
  610. std::string shader = R"(
  611. OpCapability Shader
  612. %1 = OpExtInstImport "GLSL.std.450"
  613. OpMemoryModel Logical GLSL450
  614. OpEntryPoint Fragment %4 "main"
  615. OpExecutionMode %4 OriginUpperLeft
  616. OpSource ESSL 320
  617. OpName %4 "main"
  618. %2 = OpTypeVoid
  619. %3 = OpTypeFunction %2
  620. %11 = OpTypeBool
  621. %12 = OpConstantFalse %11
  622. %4 = OpFunction %2 None %3
  623. %5 = OpLabel
  624. OpReturn
  625. %9 = OpLabel
  626. OpBranch %100
  627. %100 = OpLabel
  628. OpReturn
  629. OpFunctionEnd
  630. )";
  631. const auto env = SPV_ENV_UNIVERSAL_1_3;
  632. const auto consumer = nullptr;
  633. const auto context =
  634. BuildModule(env, consumer, shader, kReduceAssembleOption);
  635. const auto ops =
  636. MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
  637. context.get(), 0);
  638. ASSERT_EQ(1, ops.size());
  639. ASSERT_TRUE(ops[0]->PreconditionHolds());
  640. ops[0]->TryToApply();
  641. std::string after = R"(
  642. OpCapability Shader
  643. %1 = OpExtInstImport "GLSL.std.450"
  644. OpMemoryModel Logical GLSL450
  645. OpEntryPoint Fragment %4 "main"
  646. OpExecutionMode %4 OriginUpperLeft
  647. OpSource ESSL 320
  648. OpName %4 "main"
  649. %2 = OpTypeVoid
  650. %3 = OpTypeFunction %2
  651. %11 = OpTypeBool
  652. %12 = OpConstantFalse %11
  653. %4 = OpFunction %2 None %3
  654. %5 = OpLabel
  655. OpReturn
  656. %9 = OpLabel
  657. OpReturn
  658. OpFunctionEnd
  659. )";
  660. CheckEqual(env, after, context.get());
  661. }
  662. } // namespace
  663. } // namespace reduce
  664. } // namespace spvtools