transformation_move_block_down_test.cpp 30 KB

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