transformation_propagate_instruction_up_test.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
  1. // Copyright (c) 2020 Vasyl Teliman
  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_propagate_instruction_up.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(TransformationPropagateInstructionUpTest, BasicTest) {
  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. %2 = OpTypeVoid
  30. %3 = OpTypeFunction %2
  31. %6 = OpTypeFloat 32
  32. %7 = OpTypePointer Function %6
  33. %9 = OpConstant %6 3.5
  34. %11 = OpConstant %6 3.4000001
  35. %12 = OpTypeBool
  36. %17 = OpConstant %6 4
  37. %20 = OpConstant %6 45
  38. %27 = OpTypePointer Function %6
  39. %4 = OpFunction %2 None %3
  40. %5 = OpLabel
  41. %26 = OpVariable %27 Function
  42. %13 = OpFOrdEqual %12 %9 %11
  43. OpSelectionMerge %15 None
  44. OpBranchConditional %13 %14 %19
  45. %14 = OpLabel
  46. %18 = OpFMod %6 %9 %17
  47. OpBranch %15
  48. %19 = OpLabel
  49. %22 = OpFAdd %6 %11 %20
  50. OpBranch %15
  51. %15 = OpLabel
  52. %21 = OpPhi %6 %18 %14 %22 %19
  53. %23 = OpFMul %6 %21 %21
  54. %24 = OpFDiv %6 %21 %23
  55. OpBranch %25
  56. %25 = OpLabel
  57. %28 = OpPhi %6 %20 %15
  58. OpStore %26 %28
  59. OpReturn
  60. OpFunctionEnd
  61. )";
  62. const auto env = SPV_ENV_UNIVERSAL_1_3;
  63. const auto consumer = nullptr;
  64. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  65. spvtools::ValidatorOptions validator_options;
  66. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  67. kConsoleMessageConsumer));
  68. TransformationContext transformation_context(
  69. MakeUnique<FactManager>(context.get()), validator_options);
  70. // |block_id| is invalid.
  71. ASSERT_FALSE(TransformationPropagateInstructionUp(40, {{}}).IsApplicable(
  72. context.get(), transformation_context));
  73. ASSERT_FALSE(TransformationPropagateInstructionUp(26, {{}}).IsApplicable(
  74. context.get(), transformation_context));
  75. // |block_id| has no predecessors.
  76. ASSERT_FALSE(TransformationPropagateInstructionUp(5, {{}}).IsApplicable(
  77. context.get(), transformation_context));
  78. // |block_id| has no valid instructions to propagate.
  79. ASSERT_FALSE(TransformationPropagateInstructionUp(25, {{{15, 40}}})
  80. .IsApplicable(context.get(), transformation_context));
  81. // Not all predecessors have fresh ids.
  82. ASSERT_FALSE(TransformationPropagateInstructionUp(15, {{{19, 40}, {40, 41}}})
  83. .IsApplicable(context.get(), transformation_context));
  84. // Not all ids are fresh.
  85. ASSERT_FALSE(
  86. TransformationPropagateInstructionUp(15, {{{19, 40}, {14, 14}, {40, 42}}})
  87. .IsApplicable(context.get(), transformation_context));
  88. ASSERT_FALSE(
  89. TransformationPropagateInstructionUp(15, {{{19, 19}, {14, 40}, {40, 42}}})
  90. .IsApplicable(context.get(), transformation_context));
  91. // Fresh ids have duplicates.
  92. ASSERT_FALSE(
  93. TransformationPropagateInstructionUp(15, {{{19, 40}, {14, 40}, {19, 41}}})
  94. .IsApplicable(context.get(), transformation_context));
  95. // Valid transformations.
  96. {
  97. TransformationPropagateInstructionUp transformation(14, {{{5, 40}}});
  98. ASSERT_TRUE(
  99. transformation.IsApplicable(context.get(), transformation_context));
  100. ApplyAndCheckFreshIds(transformation, context.get(),
  101. &transformation_context);
  102. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  103. context.get(), validator_options, kConsoleMessageConsumer));
  104. }
  105. {
  106. TransformationPropagateInstructionUp transformation(19, {{{5, 41}}});
  107. ASSERT_TRUE(
  108. transformation.IsApplicable(context.get(), transformation_context));
  109. ApplyAndCheckFreshIds(transformation, context.get(),
  110. &transformation_context);
  111. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  112. context.get(), validator_options, kConsoleMessageConsumer));
  113. }
  114. std::string after_transformation = R"(
  115. OpCapability Shader
  116. %1 = OpExtInstImport "GLSL.std.450"
  117. OpMemoryModel Logical GLSL450
  118. OpEntryPoint Fragment %4 "main"
  119. OpExecutionMode %4 OriginUpperLeft
  120. OpSource ESSL 310
  121. %2 = OpTypeVoid
  122. %3 = OpTypeFunction %2
  123. %6 = OpTypeFloat 32
  124. %7 = OpTypePointer Function %6
  125. %9 = OpConstant %6 3.5
  126. %11 = OpConstant %6 3.4000001
  127. %12 = OpTypeBool
  128. %17 = OpConstant %6 4
  129. %20 = OpConstant %6 45
  130. %27 = OpTypePointer Function %6
  131. %4 = OpFunction %2 None %3
  132. %5 = OpLabel
  133. %26 = OpVariable %27 Function
  134. %13 = OpFOrdEqual %12 %9 %11
  135. %40 = OpFMod %6 %9 %17 ; propagated from %14
  136. %41 = OpFAdd %6 %11 %20 ; propagated from %19
  137. OpSelectionMerge %15 None
  138. OpBranchConditional %13 %14 %19
  139. %14 = OpLabel
  140. %18 = OpPhi %6 %40 %5 ; propagated into %5
  141. OpBranch %15
  142. %19 = OpLabel
  143. %22 = OpPhi %6 %41 %5 ; propagated into %5
  144. OpBranch %15
  145. %15 = OpLabel
  146. %21 = OpPhi %6 %18 %14 %22 %19
  147. %23 = OpFMul %6 %21 %21
  148. %24 = OpFDiv %6 %21 %23
  149. OpBranch %25
  150. %25 = OpLabel
  151. %28 = OpPhi %6 %20 %15
  152. OpStore %26 %28
  153. OpReturn
  154. OpFunctionEnd
  155. )";
  156. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  157. {
  158. TransformationPropagateInstructionUp transformation(15,
  159. {{{14, 43}, {19, 44}}});
  160. ASSERT_TRUE(
  161. transformation.IsApplicable(context.get(), transformation_context));
  162. ApplyAndCheckFreshIds(transformation, context.get(),
  163. &transformation_context);
  164. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  165. context.get(), validator_options, kConsoleMessageConsumer));
  166. }
  167. after_transformation = R"(
  168. OpCapability Shader
  169. %1 = OpExtInstImport "GLSL.std.450"
  170. OpMemoryModel Logical GLSL450
  171. OpEntryPoint Fragment %4 "main"
  172. OpExecutionMode %4 OriginUpperLeft
  173. OpSource ESSL 310
  174. %2 = OpTypeVoid
  175. %3 = OpTypeFunction %2
  176. %6 = OpTypeFloat 32
  177. %7 = OpTypePointer Function %6
  178. %9 = OpConstant %6 3.5
  179. %11 = OpConstant %6 3.4000001
  180. %12 = OpTypeBool
  181. %17 = OpConstant %6 4
  182. %20 = OpConstant %6 45
  183. %27 = OpTypePointer Function %6
  184. %4 = OpFunction %2 None %3
  185. %5 = OpLabel
  186. %26 = OpVariable %27 Function
  187. %13 = OpFOrdEqual %12 %9 %11
  188. %40 = OpFMod %6 %9 %17
  189. %41 = OpFAdd %6 %11 %20
  190. OpSelectionMerge %15 None
  191. OpBranchConditional %13 %14 %19
  192. %14 = OpLabel
  193. %18 = OpPhi %6 %40 %5
  194. %43 = OpFMul %6 %18 %18 ; propagated from %15
  195. OpBranch %15
  196. %19 = OpLabel
  197. %22 = OpPhi %6 %41 %5
  198. %44 = OpFMul %6 %22 %22 ; propagated from %15
  199. OpBranch %15
  200. %15 = OpLabel
  201. %23 = OpPhi %6 %43 %14 %44 %19 ; propagated into %14 and %19
  202. %21 = OpPhi %6 %18 %14 %22 %19
  203. %24 = OpFDiv %6 %21 %23
  204. OpBranch %25
  205. %25 = OpLabel
  206. %28 = OpPhi %6 %20 %15
  207. OpStore %26 %28
  208. OpReturn
  209. OpFunctionEnd
  210. )";
  211. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  212. {
  213. TransformationPropagateInstructionUp transformation(15,
  214. {{{14, 45}, {19, 46}}});
  215. ASSERT_TRUE(
  216. transformation.IsApplicable(context.get(), transformation_context));
  217. ApplyAndCheckFreshIds(transformation, context.get(),
  218. &transformation_context);
  219. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  220. context.get(), validator_options, kConsoleMessageConsumer));
  221. }
  222. after_transformation = R"(
  223. OpCapability Shader
  224. %1 = OpExtInstImport "GLSL.std.450"
  225. OpMemoryModel Logical GLSL450
  226. OpEntryPoint Fragment %4 "main"
  227. OpExecutionMode %4 OriginUpperLeft
  228. OpSource ESSL 310
  229. %2 = OpTypeVoid
  230. %3 = OpTypeFunction %2
  231. %6 = OpTypeFloat 32
  232. %7 = OpTypePointer Function %6
  233. %9 = OpConstant %6 3.5
  234. %11 = OpConstant %6 3.4000001
  235. %12 = OpTypeBool
  236. %17 = OpConstant %6 4
  237. %20 = OpConstant %6 45
  238. %27 = OpTypePointer Function %6
  239. %4 = OpFunction %2 None %3
  240. %5 = OpLabel
  241. %26 = OpVariable %27 Function
  242. %13 = OpFOrdEqual %12 %9 %11
  243. %40 = OpFMod %6 %9 %17
  244. %41 = OpFAdd %6 %11 %20
  245. OpSelectionMerge %15 None
  246. OpBranchConditional %13 %14 %19
  247. %14 = OpLabel
  248. %18 = OpPhi %6 %40 %5
  249. %43 = OpFMul %6 %18 %18
  250. %45 = OpFDiv %6 %18 %43 ; propagated from %15
  251. OpBranch %15
  252. %19 = OpLabel
  253. %22 = OpPhi %6 %41 %5
  254. %44 = OpFMul %6 %22 %22
  255. %46 = OpFDiv %6 %22 %44 ; propagated from %15
  256. OpBranch %15
  257. %15 = OpLabel
  258. %24 = OpPhi %6 %45 %14 %46 %19 ; propagated into %14 and %19
  259. %23 = OpPhi %6 %43 %14 %44 %19
  260. %21 = OpPhi %6 %18 %14 %22 %19
  261. OpBranch %25
  262. %25 = OpLabel
  263. %28 = OpPhi %6 %20 %15
  264. OpStore %26 %28
  265. OpReturn
  266. OpFunctionEnd
  267. )";
  268. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  269. }
  270. TEST(TransformationPropagateInstructionUpTest, BlockDominatesPredecessor1) {
  271. std::string shader = R"(
  272. OpCapability Shader
  273. %1 = OpExtInstImport "GLSL.std.450"
  274. OpMemoryModel Logical GLSL450
  275. OpEntryPoint Fragment %4 "main"
  276. OpExecutionMode %4 OriginUpperLeft
  277. OpSource ESSL 310
  278. %2 = OpTypeVoid
  279. %3 = OpTypeFunction %2
  280. %6 = OpTypeFloat 32
  281. %7 = OpTypePointer Function %6
  282. %9 = OpConstant %6 3.5
  283. %11 = OpConstant %6 3.4000001
  284. %12 = OpTypeBool
  285. %17 = OpConstant %6 4
  286. %20 = OpConstant %6 45
  287. %4 = OpFunction %2 None %3
  288. %5 = OpLabel
  289. %13 = OpFOrdEqual %12 %9 %11
  290. OpSelectionMerge %15 None
  291. OpBranchConditional %13 %14 %19
  292. %14 = OpLabel
  293. %18 = OpFMod %6 %9 %17
  294. OpBranch %15
  295. %19 = OpLabel
  296. %22 = OpFAdd %6 %11 %20
  297. OpBranch %15
  298. %15 = OpLabel ; dominates %26
  299. %21 = OpPhi %6 %18 %14 %22 %19 %28 %26
  300. %23 = OpFMul %6 %21 %21
  301. %24 = OpFDiv %6 %21 %23
  302. OpLoopMerge %27 %26 None
  303. OpBranch %26
  304. %26 = OpLabel
  305. %28 = OpFAdd %6 %24 %23
  306. OpBranch %15
  307. %27 = OpLabel
  308. OpReturn
  309. OpFunctionEnd
  310. )";
  311. const auto env = SPV_ENV_UNIVERSAL_1_3;
  312. const auto consumer = nullptr;
  313. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  314. spvtools::ValidatorOptions validator_options;
  315. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  316. kConsoleMessageConsumer));
  317. TransformationContext transformation_context(
  318. MakeUnique<FactManager>(context.get()), validator_options);
  319. TransformationPropagateInstructionUp transformation(
  320. 15, {{{14, 40}, {19, 41}, {26, 42}}});
  321. ASSERT_TRUE(
  322. transformation.IsApplicable(context.get(), transformation_context));
  323. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  324. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  325. kConsoleMessageConsumer));
  326. std::string after_transformation = R"(
  327. OpCapability Shader
  328. %1 = OpExtInstImport "GLSL.std.450"
  329. OpMemoryModel Logical GLSL450
  330. OpEntryPoint Fragment %4 "main"
  331. OpExecutionMode %4 OriginUpperLeft
  332. OpSource ESSL 310
  333. %2 = OpTypeVoid
  334. %3 = OpTypeFunction %2
  335. %6 = OpTypeFloat 32
  336. %7 = OpTypePointer Function %6
  337. %9 = OpConstant %6 3.5
  338. %11 = OpConstant %6 3.4000001
  339. %12 = OpTypeBool
  340. %17 = OpConstant %6 4
  341. %20 = OpConstant %6 45
  342. %4 = OpFunction %2 None %3
  343. %5 = OpLabel
  344. %13 = OpFOrdEqual %12 %9 %11
  345. OpSelectionMerge %15 None
  346. OpBranchConditional %13 %14 %19
  347. %14 = OpLabel
  348. %18 = OpFMod %6 %9 %17
  349. %40 = OpFMul %6 %18 %18 ; propagated from %15
  350. OpBranch %15
  351. %19 = OpLabel
  352. %22 = OpFAdd %6 %11 %20
  353. %41 = OpFMul %6 %22 %22 ; propagated from %15
  354. OpBranch %15
  355. %15 = OpLabel
  356. %23 = OpPhi %6 %40 %14 %41 %19 %42 %26 ; propagated into %14, %19, %26
  357. %21 = OpPhi %6 %18 %14 %22 %19 %28 %26
  358. %24 = OpFDiv %6 %21 %23
  359. OpLoopMerge %27 %26 None
  360. OpBranch %26
  361. %26 = OpLabel
  362. %28 = OpFAdd %6 %24 %23
  363. %42 = OpFMul %6 %28 %28 ; propagated from %15
  364. OpBranch %15
  365. %27 = OpLabel
  366. OpReturn
  367. OpFunctionEnd
  368. )";
  369. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  370. }
  371. TEST(TransformationPropagateInstructionUpTest, BlockDominatesPredecessor2) {
  372. std::string shader = R"(
  373. OpCapability Shader
  374. %1 = OpExtInstImport "GLSL.std.450"
  375. OpMemoryModel Logical GLSL450
  376. OpEntryPoint Fragment %4 "main"
  377. OpExecutionMode %4 OriginUpperLeft
  378. OpSource ESSL 310
  379. %2 = OpTypeVoid
  380. %3 = OpTypeFunction %2
  381. %6 = OpTypeFloat 32
  382. %7 = OpTypePointer Function %6
  383. %9 = OpConstant %6 3.5
  384. %11 = OpConstant %6 3.4000001
  385. %12 = OpTypeBool
  386. %17 = OpConstant %6 4
  387. %20 = OpConstant %6 45
  388. %4 = OpFunction %2 None %3
  389. %5 = OpLabel
  390. %13 = OpFOrdEqual %12 %9 %11
  391. OpSelectionMerge %15 None
  392. OpBranchConditional %13 %14 %19
  393. %14 = OpLabel
  394. %18 = OpFMod %6 %9 %17
  395. OpBranch %15
  396. %19 = OpLabel
  397. %22 = OpFAdd %6 %11 %20
  398. OpBranch %15
  399. %15 = OpLabel ; doesn't dominate %26
  400. %21 = OpPhi %6 %18 %14 %22 %19 %20 %26
  401. %23 = OpFMul %6 %21 %21
  402. %24 = OpFDiv %6 %21 %23
  403. OpLoopMerge %27 %26 None
  404. OpBranch %27
  405. %26 = OpLabel
  406. OpBranch %15
  407. %27 = OpLabel
  408. OpReturn
  409. OpFunctionEnd
  410. )";
  411. const auto env = SPV_ENV_UNIVERSAL_1_3;
  412. const auto consumer = nullptr;
  413. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  414. spvtools::ValidatorOptions validator_options;
  415. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  416. kConsoleMessageConsumer));
  417. TransformationContext transformation_context(
  418. MakeUnique<FactManager>(context.get()), validator_options);
  419. TransformationPropagateInstructionUp transformation(
  420. 15, {{{14, 40}, {19, 41}, {26, 42}}});
  421. ASSERT_TRUE(
  422. transformation.IsApplicable(context.get(), transformation_context));
  423. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  424. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  425. kConsoleMessageConsumer));
  426. std::string after_transformation = R"(
  427. OpCapability Shader
  428. %1 = OpExtInstImport "GLSL.std.450"
  429. OpMemoryModel Logical GLSL450
  430. OpEntryPoint Fragment %4 "main"
  431. OpExecutionMode %4 OriginUpperLeft
  432. OpSource ESSL 310
  433. %2 = OpTypeVoid
  434. %3 = OpTypeFunction %2
  435. %6 = OpTypeFloat 32
  436. %7 = OpTypePointer Function %6
  437. %9 = OpConstant %6 3.5
  438. %11 = OpConstant %6 3.4000001
  439. %12 = OpTypeBool
  440. %17 = OpConstant %6 4
  441. %20 = OpConstant %6 45
  442. %4 = OpFunction %2 None %3
  443. %5 = OpLabel
  444. %13 = OpFOrdEqual %12 %9 %11
  445. OpSelectionMerge %15 None
  446. OpBranchConditional %13 %14 %19
  447. %14 = OpLabel
  448. %18 = OpFMod %6 %9 %17
  449. %40 = OpFMul %6 %18 %18 ; propagated from %15
  450. OpBranch %15
  451. %19 = OpLabel
  452. %22 = OpFAdd %6 %11 %20
  453. %41 = OpFMul %6 %22 %22 ; propagated from %15
  454. OpBranch %15
  455. %15 = OpLabel
  456. %23 = OpPhi %6 %40 %14 %41 %19 %42 %26 ; propagated into %14, %19, %26
  457. %21 = OpPhi %6 %18 %14 %22 %19 %20 %26
  458. %24 = OpFDiv %6 %21 %23
  459. OpLoopMerge %27 %26 None
  460. OpBranch %27
  461. %26 = OpLabel
  462. %42 = OpFMul %6 %20 %20 ; propagated from %15
  463. OpBranch %15
  464. %27 = OpLabel
  465. OpReturn
  466. OpFunctionEnd
  467. )";
  468. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  469. }
  470. TEST(TransformationPropagateInstructionUpTest, BlockDominatesPredecessor3) {
  471. std::string shader = R"(
  472. OpCapability Shader
  473. %1 = OpExtInstImport "GLSL.std.450"
  474. OpMemoryModel Logical GLSL450
  475. OpEntryPoint Fragment %4 "main"
  476. OpExecutionMode %4 OriginUpperLeft
  477. OpSource ESSL 310
  478. %2 = OpTypeVoid
  479. %3 = OpTypeFunction %2
  480. %6 = OpTypeFloat 32
  481. %7 = OpTypePointer Function %6
  482. %9 = OpConstant %6 3.5
  483. %11 = OpConstant %6 3.4000001
  484. %12 = OpTypeBool
  485. %17 = OpConstant %6 4
  486. %20 = OpConstant %6 45
  487. %4 = OpFunction %2 None %3
  488. %5 = OpLabel
  489. %13 = OpFOrdEqual %12 %9 %11
  490. OpSelectionMerge %15 None
  491. OpBranchConditional %13 %14 %19
  492. %14 = OpLabel
  493. %18 = OpFMod %6 %9 %17
  494. OpBranch %15
  495. %19 = OpLabel
  496. %22 = OpFAdd %6 %11 %20
  497. OpBranch %15
  498. %15 = OpLabel ; branches to itself
  499. %21 = OpPhi %6 %18 %14 %22 %19 %24 %15
  500. %23 = OpFMul %6 %21 %21
  501. %24 = OpFDiv %6 %21 %23
  502. OpLoopMerge %27 %15 None
  503. OpBranch %15
  504. %27 = OpLabel
  505. OpReturn
  506. OpFunctionEnd
  507. )";
  508. const auto env = SPV_ENV_UNIVERSAL_1_3;
  509. const auto consumer = nullptr;
  510. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  511. spvtools::ValidatorOptions validator_options;
  512. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  513. kConsoleMessageConsumer));
  514. TransformationContext transformation_context(
  515. MakeUnique<FactManager>(context.get()), validator_options);
  516. TransformationPropagateInstructionUp transformation(
  517. 15, {{{14, 40}, {19, 41}, {15, 42}}});
  518. ASSERT_TRUE(
  519. transformation.IsApplicable(context.get(), transformation_context));
  520. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  521. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  522. kConsoleMessageConsumer));
  523. std::string after_transformation = R"(
  524. OpCapability Shader
  525. %1 = OpExtInstImport "GLSL.std.450"
  526. OpMemoryModel Logical GLSL450
  527. OpEntryPoint Fragment %4 "main"
  528. OpExecutionMode %4 OriginUpperLeft
  529. OpSource ESSL 310
  530. %2 = OpTypeVoid
  531. %3 = OpTypeFunction %2
  532. %6 = OpTypeFloat 32
  533. %7 = OpTypePointer Function %6
  534. %9 = OpConstant %6 3.5
  535. %11 = OpConstant %6 3.4000001
  536. %12 = OpTypeBool
  537. %17 = OpConstant %6 4
  538. %20 = OpConstant %6 45
  539. %4 = OpFunction %2 None %3
  540. %5 = OpLabel
  541. %13 = OpFOrdEqual %12 %9 %11
  542. OpSelectionMerge %15 None
  543. OpBranchConditional %13 %14 %19
  544. %14 = OpLabel
  545. %18 = OpFMod %6 %9 %17
  546. %40 = OpFMul %6 %18 %18 ; propagated from %15
  547. OpBranch %15
  548. %19 = OpLabel
  549. %22 = OpFAdd %6 %11 %20
  550. %41 = OpFMul %6 %22 %22 ; propagated from %15
  551. OpBranch %15
  552. %15 = OpLabel
  553. %23 = OpPhi %6 %40 %14 %41 %19 %42 %15 ; propagated into %14, %19, %15
  554. %21 = OpPhi %6 %18 %14 %22 %19 %24 %15
  555. %24 = OpFDiv %6 %21 %23
  556. %42 = OpFMul %6 %24 %24 ; propagated from %15
  557. OpLoopMerge %27 %15 None
  558. OpBranch %15
  559. %27 = OpLabel
  560. OpReturn
  561. OpFunctionEnd
  562. )";
  563. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  564. }
  565. TEST(TransformationPropagateInstructionUpTest,
  566. HandlesVariablePointersCapability) {
  567. std::string shader = R"(
  568. OpCapability Shader
  569. %1 = OpExtInstImport "GLSL.std.450"
  570. OpMemoryModel Logical GLSL450
  571. OpEntryPoint Fragment %4 "main"
  572. OpExecutionMode %4 OriginUpperLeft
  573. OpSource ESSL 310
  574. %2 = OpTypeVoid
  575. %3 = OpTypeFunction %2
  576. %6 = OpTypeFloat 32
  577. %11 = OpConstant %6 23
  578. %7 = OpTypePointer Function %6
  579. %4 = OpFunction %2 None %3
  580. %5 = OpLabel
  581. %8 = OpVariable %7 Function
  582. OpBranch %9
  583. %9 = OpLabel
  584. %10 = OpCopyObject %7 %8
  585. OpStore %10 %11
  586. OpReturn
  587. OpFunctionEnd
  588. )";
  589. const auto env = SPV_ENV_UNIVERSAL_1_3;
  590. const auto consumer = nullptr;
  591. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  592. spvtools::ValidatorOptions validator_options;
  593. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  594. kConsoleMessageConsumer));
  595. TransformationContext transformation_context(
  596. MakeUnique<FactManager>(context.get()), validator_options);
  597. // Required capabilities haven't yet been specified.
  598. TransformationPropagateInstructionUp transformation(9, {{{5, 40}}});
  599. ASSERT_FALSE(
  600. transformation.IsApplicable(context.get(), transformation_context));
  601. context->AddCapability(spv::Capability::VariablePointers);
  602. ASSERT_TRUE(
  603. transformation.IsApplicable(context.get(), transformation_context));
  604. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  605. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  606. kConsoleMessageConsumer));
  607. std::string after_transformation = R"(
  608. OpCapability Shader
  609. OpCapability VariablePointers
  610. %1 = OpExtInstImport "GLSL.std.450"
  611. OpMemoryModel Logical GLSL450
  612. OpEntryPoint Fragment %4 "main"
  613. OpExecutionMode %4 OriginUpperLeft
  614. OpSource ESSL 310
  615. %2 = OpTypeVoid
  616. %3 = OpTypeFunction %2
  617. %6 = OpTypeFloat 32
  618. %11 = OpConstant %6 23
  619. %7 = OpTypePointer Function %6
  620. %4 = OpFunction %2 None %3
  621. %5 = OpLabel
  622. %8 = OpVariable %7 Function
  623. %40 = OpCopyObject %7 %8 ; propagated from %9
  624. OpBranch %9
  625. %9 = OpLabel
  626. %10 = OpPhi %7 %40 %5 ; propagated into %5
  627. OpStore %10 %11
  628. OpReturn
  629. OpFunctionEnd
  630. )";
  631. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  632. }
  633. TEST(TransformationPropagateInstructionUpTest,
  634. HandlesVariablePointersStorageBufferCapability) {
  635. std::string shader = R"(
  636. OpCapability Shader
  637. %1 = OpExtInstImport "GLSL.std.450"
  638. OpMemoryModel Logical GLSL450
  639. OpEntryPoint Fragment %4 "main"
  640. OpExecutionMode %4 OriginUpperLeft
  641. OpSource ESSL 310
  642. %2 = OpTypeVoid
  643. %3 = OpTypeFunction %2
  644. %6 = OpTypeFloat 32
  645. %11 = OpConstant %6 23
  646. %7 = OpTypePointer Function %6
  647. %4 = OpFunction %2 None %3
  648. %5 = OpLabel
  649. %8 = OpVariable %7 Function
  650. OpBranch %9
  651. %9 = OpLabel
  652. %10 = OpCopyObject %7 %8
  653. OpStore %10 %11
  654. OpReturn
  655. OpFunctionEnd
  656. )";
  657. const auto env = SPV_ENV_UNIVERSAL_1_3;
  658. const auto consumer = nullptr;
  659. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  660. spvtools::ValidatorOptions validator_options;
  661. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  662. kConsoleMessageConsumer));
  663. TransformationContext transformation_context(
  664. MakeUnique<FactManager>(context.get()), validator_options);
  665. // Required capabilities haven't yet been specified
  666. TransformationPropagateInstructionUp transformation(9, {{{5, 40}}});
  667. ASSERT_FALSE(
  668. transformation.IsApplicable(context.get(), transformation_context));
  669. context->AddCapability(spv::Capability::VariablePointersStorageBuffer);
  670. ASSERT_TRUE(
  671. transformation.IsApplicable(context.get(), transformation_context));
  672. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  673. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  674. kConsoleMessageConsumer));
  675. std::string after_transformation = R"(
  676. OpCapability Shader
  677. OpCapability VariablePointersStorageBuffer
  678. %1 = OpExtInstImport "GLSL.std.450"
  679. OpMemoryModel Logical GLSL450
  680. OpEntryPoint Fragment %4 "main"
  681. OpExecutionMode %4 OriginUpperLeft
  682. OpSource ESSL 310
  683. %2 = OpTypeVoid
  684. %3 = OpTypeFunction %2
  685. %6 = OpTypeFloat 32
  686. %11 = OpConstant %6 23
  687. %7 = OpTypePointer Function %6
  688. %4 = OpFunction %2 None %3
  689. %5 = OpLabel
  690. %8 = OpVariable %7 Function
  691. %40 = OpCopyObject %7 %8 ; propagated from %9
  692. OpBranch %9
  693. %9 = OpLabel
  694. %10 = OpPhi %7 %40 %5 ; propagated into %5
  695. OpStore %10 %11
  696. OpReturn
  697. OpFunctionEnd
  698. )";
  699. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  700. }
  701. TEST(TransformationPropagateInstructionUpTest, MultipleIdenticalPredecessors) {
  702. std::string shader = R"(
  703. OpCapability Shader
  704. %1 = OpExtInstImport "GLSL.std.450"
  705. OpMemoryModel Logical GLSL450
  706. OpEntryPoint Fragment %4 "main"
  707. OpExecutionMode %4 OriginUpperLeft
  708. OpSource ESSL 310
  709. %2 = OpTypeVoid
  710. %3 = OpTypeFunction %2
  711. %6 = OpTypeFloat 32
  712. %11 = OpConstant %6 23
  713. %12 = OpTypeBool
  714. %13 = OpConstantTrue %12
  715. %4 = OpFunction %2 None %3
  716. %5 = OpLabel
  717. OpSelectionMerge %9 None
  718. OpBranchConditional %13 %9 %9
  719. %9 = OpLabel
  720. %14 = OpPhi %6 %11 %5
  721. %10 = OpCopyObject %6 %14
  722. OpReturn
  723. OpFunctionEnd
  724. )";
  725. const auto env = SPV_ENV_UNIVERSAL_1_3;
  726. const auto consumer = nullptr;
  727. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  728. spvtools::ValidatorOptions validator_options;
  729. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  730. kConsoleMessageConsumer));
  731. TransformationContext transformation_context(
  732. MakeUnique<FactManager>(context.get()), validator_options);
  733. TransformationPropagateInstructionUp transformation(9, {{{5, 40}}});
  734. ASSERT_TRUE(
  735. transformation.IsApplicable(context.get(), transformation_context));
  736. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  737. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  738. kConsoleMessageConsumer));
  739. std::string after_transformation = R"(
  740. OpCapability Shader
  741. %1 = OpExtInstImport "GLSL.std.450"
  742. OpMemoryModel Logical GLSL450
  743. OpEntryPoint Fragment %4 "main"
  744. OpExecutionMode %4 OriginUpperLeft
  745. OpSource ESSL 310
  746. %2 = OpTypeVoid
  747. %3 = OpTypeFunction %2
  748. %6 = OpTypeFloat 32
  749. %11 = OpConstant %6 23
  750. %12 = OpTypeBool
  751. %13 = OpConstantTrue %12
  752. %4 = OpFunction %2 None %3
  753. %5 = OpLabel
  754. %40 = OpCopyObject %6 %11
  755. OpSelectionMerge %9 None
  756. OpBranchConditional %13 %9 %9
  757. %9 = OpLabel
  758. %10 = OpPhi %6 %40 %5
  759. %14 = OpPhi %6 %11 %5
  760. OpReturn
  761. OpFunctionEnd
  762. )";
  763. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  764. }
  765. TEST(TransformationPropagateInstructionUpTest,
  766. InapplicableDueToOpTypeSampledImage) {
  767. std::string shader = R"(
  768. OpCapability Shader
  769. %1 = OpExtInstImport "GLSL.std.450"
  770. OpMemoryModel Logical GLSL450
  771. OpEntryPoint Fragment %4 "main" %10
  772. OpExecutionMode %4 OriginUpperLeft
  773. OpSource ESSL 320
  774. OpDecorate %10 RelaxedPrecision
  775. OpDecorate %10 DescriptorSet 0
  776. OpDecorate %10 Binding 0
  777. %2 = OpTypeVoid
  778. %3 = OpTypeFunction %2
  779. %6 = OpTypeFloat 32
  780. %7 = OpTypeImage %6 2D 0 0 0 1 Unknown
  781. %8 = OpTypeSampledImage %7
  782. %9 = OpTypePointer UniformConstant %8
  783. %10 = OpVariable %9 UniformConstant
  784. %12 = OpTypeVector %6 2
  785. %13 = OpConstant %6 0
  786. %14 = OpConstantComposite %12 %13 %13
  787. %15 = OpTypeVector %6 4
  788. %30 = OpTypeBool
  789. %31 = OpConstantTrue %30
  790. %4 = OpFunction %2 None %3
  791. %5 = OpLabel
  792. %11 = OpLoad %8 %10
  793. OpSelectionMerge %20 None
  794. OpBranchConditional %31 %40 %41
  795. %40 = OpLabel
  796. OpBranch %20
  797. %41 = OpLabel
  798. OpBranch %20
  799. %20 = OpLabel
  800. %50 = OpCopyObject %8 %11
  801. %16 = OpImageSampleImplicitLod %15 %50 %14
  802. OpReturn
  803. OpFunctionEnd
  804. )";
  805. const auto env = SPV_ENV_UNIVERSAL_1_5;
  806. const auto consumer = nullptr;
  807. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  808. spvtools::ValidatorOptions validator_options;
  809. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  810. kConsoleMessageConsumer));
  811. TransformationContext transformation_context(
  812. MakeUnique<FactManager>(context.get()), validator_options);
  813. ASSERT_FALSE(
  814. TransformationPropagateInstructionUp(20, {{{40, 100}, {41, 101}}})
  815. .IsApplicable(context.get(), transformation_context));
  816. }
  817. } // namespace
  818. } // namespace fuzz
  819. } // namespace spvtools