transformation_merge_blocks_test.cpp 25 KB

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