transformation_add_synonym_test.cpp 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498
  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_add_synonym.h"
  15. #include "gtest/gtest.h"
  16. #include "source/fuzz/fuzzer_util.h"
  17. #include "source/fuzz/instruction_descriptor.h"
  18. #include "test/fuzz/fuzz_test_util.h"
  19. namespace spvtools {
  20. namespace fuzz {
  21. namespace {
  22. TEST(TransformationAddSynonymTest, NotApplicable) {
  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. OpDecorate %22 RelaxedPrecision
  32. %2 = OpTypeVoid
  33. %3 = OpTypeFunction %2
  34. %6 = OpTypeInt 32 1
  35. %7 = OpTypePointer Function %6
  36. %9 = OpConstant %6 3
  37. %10 = OpTypeFloat 32
  38. %11 = OpTypePointer Function %10
  39. %13 = OpConstant %10 4.5
  40. %14 = OpTypeVector %10 2
  41. %15 = OpTypePointer Function %14
  42. %17 = OpConstant %10 3
  43. %18 = OpConstant %10 4
  44. %19 = OpConstantComposite %14 %17 %18
  45. %20 = OpTypeVector %6 2
  46. %21 = OpTypePointer Function %20
  47. %23 = OpConstant %6 4
  48. %24 = OpConstantComposite %20 %9 %23
  49. %26 = OpConstantNull %6
  50. %4 = OpFunction %2 None %3
  51. %5 = OpLabel
  52. %8 = OpVariable %7 Function
  53. %12 = OpVariable %11 Function
  54. %16 = OpVariable %15 Function
  55. %22 = OpVariable %21 Function
  56. OpStore %8 %9
  57. OpStore %12 %13
  58. OpStore %16 %19
  59. OpStore %22 %24
  60. %25 = OpUndef %6
  61. %27 = OpLoad %6 %8
  62. OpReturn
  63. OpFunctionEnd
  64. )";
  65. const auto env = SPV_ENV_UNIVERSAL_1_3;
  66. const auto consumer = nullptr;
  67. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  68. spvtools::ValidatorOptions validator_options;
  69. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  70. kConsoleMessageConsumer));
  71. TransformationContext transformation_context(
  72. MakeUnique<FactManager>(context.get()), validator_options);
  73. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(24);
  74. auto insert_before = MakeInstructionDescriptor(22, spv::Op::OpReturn, 0);
  75. #ifndef NDEBUG
  76. ASSERT_DEATH(
  77. TransformationAddSynonym(
  78. 9, static_cast<protobufs::TransformationAddSynonym::SynonymType>(-1),
  79. 40, insert_before)
  80. .IsApplicable(context.get(), transformation_context),
  81. "Synonym type is invalid");
  82. #endif
  83. // These tests should succeed regardless of the synonym type.
  84. for (int i = 0;
  85. i < protobufs::TransformationAddSynonym::SynonymType_descriptor()
  86. ->value_count();
  87. ++i) {
  88. const auto* synonym_value =
  89. protobufs::TransformationAddSynonym::SynonymType_descriptor()->value(i);
  90. ASSERT_TRUE(protobufs::TransformationAddSynonym::SynonymType_IsValid(
  91. synonym_value->number()));
  92. auto synonym_type =
  93. static_cast<protobufs::TransformationAddSynonym::SynonymType>(
  94. synonym_value->number());
  95. // |synonym_fresh_id| is not fresh.
  96. ASSERT_FALSE(TransformationAddSynonym(9, synonym_type, 9, insert_before)
  97. .IsApplicable(context.get(), transformation_context));
  98. // |result_id| is invalid.
  99. ASSERT_FALSE(TransformationAddSynonym(40, synonym_type, 40, insert_before)
  100. .IsApplicable(context.get(), transformation_context));
  101. // Instruction with |result_id| has no type id.
  102. ASSERT_FALSE(TransformationAddSynonym(5, synonym_type, 40, insert_before)
  103. .IsApplicable(context.get(), transformation_context));
  104. // Instruction with |result_id| is an OpUndef.
  105. ASSERT_FALSE(TransformationAddSynonym(25, synonym_type, 40, insert_before)
  106. .IsApplicable(context.get(), transformation_context));
  107. // Instruction with |result_id| is an OpConstantNull.
  108. ASSERT_FALSE(TransformationAddSynonym(26, synonym_type, 40, insert_before)
  109. .IsApplicable(context.get(), transformation_context));
  110. // |result_id| is irrelevant.
  111. ASSERT_FALSE(TransformationAddSynonym(24, synonym_type, 40, insert_before)
  112. .IsApplicable(context.get(), transformation_context));
  113. // |insert_before| is invalid.
  114. ASSERT_FALSE(TransformationAddSynonym(
  115. 9, synonym_type, 40,
  116. MakeInstructionDescriptor(25, spv::Op::OpStore, 0))
  117. .IsApplicable(context.get(), transformation_context));
  118. // Can't insert before |insert_before|.
  119. ASSERT_FALSE(TransformationAddSynonym(
  120. 9, synonym_type, 40,
  121. MakeInstructionDescriptor(5, spv::Op::OpLabel, 0))
  122. .IsApplicable(context.get(), transformation_context));
  123. ASSERT_FALSE(TransformationAddSynonym(
  124. 9, synonym_type, 40,
  125. MakeInstructionDescriptor(22, spv::Op::OpVariable, 0))
  126. .IsApplicable(context.get(), transformation_context));
  127. ASSERT_FALSE(TransformationAddSynonym(
  128. 9, synonym_type, 40,
  129. MakeInstructionDescriptor(25, spv::Op::OpFunctionEnd, 0))
  130. .IsApplicable(context.get(), transformation_context));
  131. // Domination rules are not satisfied.
  132. ASSERT_FALSE(TransformationAddSynonym(
  133. 27, synonym_type, 40,
  134. MakeInstructionDescriptor(27, spv::Op::OpLoad, 0))
  135. .IsApplicable(context.get(), transformation_context));
  136. ASSERT_FALSE(TransformationAddSynonym(
  137. 27, synonym_type, 40,
  138. MakeInstructionDescriptor(22, spv::Op::OpStore, 1))
  139. .IsApplicable(context.get(), transformation_context));
  140. }
  141. }
  142. TEST(TransformationAddSynonymTest, AddZeroSubZeroMulOne) {
  143. std::string shader = R"(
  144. OpCapability Shader
  145. %1 = OpExtInstImport "GLSL.std.450"
  146. OpMemoryModel Logical GLSL450
  147. OpEntryPoint Fragment %4 "main"
  148. OpExecutionMode %4 OriginUpperLeft
  149. OpSource ESSL 310
  150. %2 = OpTypeVoid
  151. %3 = OpTypeFunction %2
  152. %6 = OpTypeInt 32 1
  153. %7 = OpConstant %6 0
  154. %8 = OpConstant %6 1
  155. %9 = OpConstant %6 34
  156. %10 = OpTypeInt 32 0
  157. %13 = OpConstant %10 34
  158. %14 = OpTypeFloat 32
  159. %15 = OpConstant %14 0
  160. %16 = OpConstant %14 1
  161. %17 = OpConstant %14 34
  162. %18 = OpTypeVector %14 2
  163. %19 = OpConstantComposite %18 %15 %15
  164. %20 = OpConstantComposite %18 %16 %16
  165. %21 = OpConstant %14 3
  166. %22 = OpConstant %14 4
  167. %23 = OpConstantComposite %18 %21 %22
  168. %24 = OpTypeVector %6 2
  169. %25 = OpConstantComposite %24 %7 %7
  170. %26 = OpConstantComposite %24 %8 %8
  171. %27 = OpConstant %6 3
  172. %28 = OpConstant %6 4
  173. %29 = OpConstantComposite %24 %27 %28
  174. %30 = OpTypeVector %10 2
  175. %33 = OpConstant %10 3
  176. %34 = OpConstant %10 4
  177. %35 = OpConstantComposite %30 %33 %34
  178. %36 = OpTypeBool
  179. %37 = OpTypeVector %36 2
  180. %38 = OpConstantTrue %36
  181. %39 = OpConstantComposite %37 %38 %38
  182. %40 = OpConstant %6 37
  183. %4 = OpFunction %2 None %3
  184. %5 = OpLabel
  185. OpReturn
  186. OpFunctionEnd
  187. )";
  188. const auto env = SPV_ENV_UNIVERSAL_1_3;
  189. const auto consumer = nullptr;
  190. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  191. spvtools::ValidatorOptions validator_options;
  192. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  193. kConsoleMessageConsumer));
  194. TransformationContext transformation_context(
  195. MakeUnique<FactManager>(context.get()), validator_options);
  196. auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
  197. uint32_t fresh_id = 50;
  198. for (auto synonym_type : {protobufs::TransformationAddSynonym::ADD_ZERO,
  199. protobufs::TransformationAddSynonym::SUB_ZERO,
  200. protobufs::TransformationAddSynonym::MUL_ONE}) {
  201. ASSERT_TRUE(
  202. TransformationAddSynonym::IsAdditionalConstantRequired(synonym_type));
  203. // Can't create a synonym of a scalar or a vector of a wrong (in this case -
  204. // boolean) type.
  205. ASSERT_FALSE(
  206. TransformationAddSynonym(38, synonym_type, fresh_id, insert_before)
  207. .IsApplicable(context.get(), transformation_context));
  208. ASSERT_FALSE(
  209. TransformationAddSynonym(39, synonym_type, fresh_id, insert_before)
  210. .IsApplicable(context.get(), transformation_context));
  211. // Required constant is not present in the module.
  212. ASSERT_FALSE(
  213. TransformationAddSynonym(13, synonym_type, fresh_id, insert_before)
  214. .IsApplicable(context.get(), transformation_context));
  215. ASSERT_FALSE(
  216. TransformationAddSynonym(35, synonym_type, fresh_id, insert_before)
  217. .IsApplicable(context.get(), transformation_context));
  218. for (auto result_id : {9, 17, 23, 29}) {
  219. TransformationAddSynonym transformation(result_id, synonym_type, fresh_id,
  220. insert_before);
  221. ASSERT_TRUE(
  222. transformation.IsApplicable(context.get(), transformation_context));
  223. ApplyAndCheckFreshIds(transformation, context.get(),
  224. &transformation_context);
  225. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  226. MakeDataDescriptor(result_id, {}), MakeDataDescriptor(fresh_id, {})));
  227. ++fresh_id;
  228. }
  229. }
  230. {
  231. TransformationAddSynonym transformation(
  232. 40, protobufs::TransformationAddSynonym::BITWISE_OR, fresh_id,
  233. insert_before);
  234. ASSERT_TRUE(
  235. transformation.IsApplicable(context.get(), transformation_context));
  236. ApplyAndCheckFreshIds(transformation, context.get(),
  237. &transformation_context);
  238. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  239. MakeDataDescriptor(40, {}), MakeDataDescriptor(fresh_id, {})));
  240. ++fresh_id;
  241. }
  242. {
  243. TransformationAddSynonym transformation(
  244. 40, protobufs::TransformationAddSynonym::BITWISE_XOR, fresh_id,
  245. insert_before);
  246. ASSERT_TRUE(
  247. transformation.IsApplicable(context.get(), transformation_context));
  248. ApplyAndCheckFreshIds(transformation, context.get(),
  249. &transformation_context);
  250. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  251. MakeDataDescriptor(40, {}), MakeDataDescriptor(fresh_id, {})));
  252. }
  253. std::string expected_shader = R"(
  254. OpCapability Shader
  255. %1 = OpExtInstImport "GLSL.std.450"
  256. OpMemoryModel Logical GLSL450
  257. OpEntryPoint Fragment %4 "main"
  258. OpExecutionMode %4 OriginUpperLeft
  259. OpSource ESSL 310
  260. %2 = OpTypeVoid
  261. %3 = OpTypeFunction %2
  262. %6 = OpTypeInt 32 1
  263. %7 = OpConstant %6 0
  264. %8 = OpConstant %6 1
  265. %9 = OpConstant %6 34
  266. %10 = OpTypeInt 32 0
  267. %13 = OpConstant %10 34
  268. %14 = OpTypeFloat 32
  269. %15 = OpConstant %14 0
  270. %16 = OpConstant %14 1
  271. %17 = OpConstant %14 34
  272. %18 = OpTypeVector %14 2
  273. %19 = OpConstantComposite %18 %15 %15
  274. %20 = OpConstantComposite %18 %16 %16
  275. %21 = OpConstant %14 3
  276. %22 = OpConstant %14 4
  277. %23 = OpConstantComposite %18 %21 %22
  278. %24 = OpTypeVector %6 2
  279. %25 = OpConstantComposite %24 %7 %7
  280. %26 = OpConstantComposite %24 %8 %8
  281. %27 = OpConstant %6 3
  282. %28 = OpConstant %6 4
  283. %29 = OpConstantComposite %24 %27 %28
  284. %30 = OpTypeVector %10 2
  285. %33 = OpConstant %10 3
  286. %34 = OpConstant %10 4
  287. %35 = OpConstantComposite %30 %33 %34
  288. %36 = OpTypeBool
  289. %37 = OpTypeVector %36 2
  290. %38 = OpConstantTrue %36
  291. %39 = OpConstantComposite %37 %38 %38
  292. %40 = OpConstant %6 37
  293. %4 = OpFunction %2 None %3
  294. %5 = OpLabel
  295. %50 = OpIAdd %6 %9 %7
  296. %51 = OpFAdd %14 %17 %15
  297. %52 = OpFAdd %18 %23 %19
  298. %53 = OpIAdd %24 %29 %25
  299. %54 = OpISub %6 %9 %7
  300. %55 = OpFSub %14 %17 %15
  301. %56 = OpFSub %18 %23 %19
  302. %57 = OpISub %24 %29 %25
  303. %58 = OpIMul %6 %9 %8
  304. %59 = OpFMul %14 %17 %16
  305. %60 = OpFMul %18 %23 %20
  306. %61 = OpIMul %24 %29 %26
  307. %62 = OpBitwiseOr %6 %40 %7
  308. %63 = OpBitwiseXor %6 %40 %7
  309. OpReturn
  310. OpFunctionEnd
  311. )";
  312. ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
  313. }
  314. TEST(TransformationAddSynonymTest, LogicalAndLogicalOr) {
  315. std::string shader = R"(
  316. OpCapability Shader
  317. %1 = OpExtInstImport "GLSL.std.450"
  318. OpMemoryModel Logical GLSL450
  319. OpEntryPoint Fragment %4 "main"
  320. OpExecutionMode %4 OriginUpperLeft
  321. OpSource ESSL 310
  322. %2 = OpTypeVoid
  323. %3 = OpTypeFunction %2
  324. %6 = OpTypeBool
  325. %7 = OpConstantFalse %6
  326. %9 = OpConstantTrue %6
  327. %10 = OpTypeVector %6 2
  328. %11 = OpConstantComposite %10 %7 %9
  329. %12 = OpConstantComposite %10 %7 %7
  330. %13 = OpConstantComposite %10 %9 %9
  331. %14 = OpTypeFloat 32
  332. %17 = OpConstant %14 35
  333. %18 = OpTypeVector %14 2
  334. %21 = OpConstant %14 3
  335. %22 = OpConstant %14 4
  336. %23 = OpConstantComposite %18 %21 %22
  337. %4 = OpFunction %2 None %3
  338. %5 = OpLabel
  339. OpReturn
  340. OpFunctionEnd
  341. )";
  342. const auto env = SPV_ENV_UNIVERSAL_1_3;
  343. const auto consumer = nullptr;
  344. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  345. spvtools::ValidatorOptions validator_options;
  346. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  347. kConsoleMessageConsumer));
  348. TransformationContext transformation_context(
  349. MakeUnique<FactManager>(context.get()), validator_options);
  350. auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
  351. uint32_t fresh_id = 50;
  352. for (auto synonym_type : {protobufs::TransformationAddSynonym::LOGICAL_AND,
  353. protobufs::TransformationAddSynonym::LOGICAL_OR}) {
  354. ASSERT_TRUE(
  355. TransformationAddSynonym::IsAdditionalConstantRequired(synonym_type));
  356. // Can't create a synonym of a scalar or a vector of a wrong (in this case -
  357. // float) type.
  358. ASSERT_FALSE(
  359. TransformationAddSynonym(17, synonym_type, fresh_id, insert_before)
  360. .IsApplicable(context.get(), transformation_context));
  361. ASSERT_FALSE(
  362. TransformationAddSynonym(23, synonym_type, fresh_id, insert_before)
  363. .IsApplicable(context.get(), transformation_context));
  364. for (auto result_id : {9, 11}) {
  365. TransformationAddSynonym transformation(result_id, synonym_type, fresh_id,
  366. insert_before);
  367. ASSERT_TRUE(
  368. transformation.IsApplicable(context.get(), transformation_context));
  369. ApplyAndCheckFreshIds(transformation, context.get(),
  370. &transformation_context);
  371. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  372. MakeDataDescriptor(result_id, {}), MakeDataDescriptor(fresh_id, {})));
  373. ++fresh_id;
  374. }
  375. }
  376. std::string expected_shader = R"(
  377. OpCapability Shader
  378. %1 = OpExtInstImport "GLSL.std.450"
  379. OpMemoryModel Logical GLSL450
  380. OpEntryPoint Fragment %4 "main"
  381. OpExecutionMode %4 OriginUpperLeft
  382. OpSource ESSL 310
  383. %2 = OpTypeVoid
  384. %3 = OpTypeFunction %2
  385. %6 = OpTypeBool
  386. %7 = OpConstantFalse %6
  387. %9 = OpConstantTrue %6
  388. %10 = OpTypeVector %6 2
  389. %11 = OpConstantComposite %10 %7 %9
  390. %12 = OpConstantComposite %10 %7 %7
  391. %13 = OpConstantComposite %10 %9 %9
  392. %14 = OpTypeFloat 32
  393. %17 = OpConstant %14 35
  394. %18 = OpTypeVector %14 2
  395. %21 = OpConstant %14 3
  396. %22 = OpConstant %14 4
  397. %23 = OpConstantComposite %18 %21 %22
  398. %4 = OpFunction %2 None %3
  399. %5 = OpLabel
  400. %50 = OpLogicalAnd %6 %9 %9
  401. %51 = OpLogicalAnd %10 %11 %13
  402. %52 = OpLogicalOr %6 %9 %7
  403. %53 = OpLogicalOr %10 %11 %12
  404. OpReturn
  405. OpFunctionEnd
  406. )";
  407. ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
  408. }
  409. TEST(TransformationAddSynonymTest, LogicalAndConstantIsNotPresent) {
  410. std::string shader = R"(
  411. OpCapability Shader
  412. %1 = OpExtInstImport "GLSL.std.450"
  413. OpMemoryModel Logical GLSL450
  414. OpEntryPoint Fragment %4 "main"
  415. OpExecutionMode %4 OriginUpperLeft
  416. OpSource ESSL 310
  417. %2 = OpTypeVoid
  418. %3 = OpTypeFunction %2
  419. %6 = OpTypeBool
  420. %7 = OpConstantFalse %6
  421. %10 = OpTypeVector %6 2
  422. %12 = OpConstantComposite %10 %7 %7
  423. %4 = OpFunction %2 None %3
  424. %5 = OpLabel
  425. OpReturn
  426. OpFunctionEnd
  427. )";
  428. const auto env = SPV_ENV_UNIVERSAL_1_3;
  429. const auto consumer = nullptr;
  430. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  431. spvtools::ValidatorOptions validator_options;
  432. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  433. kConsoleMessageConsumer));
  434. TransformationContext transformation_context(
  435. MakeUnique<FactManager>(context.get()), validator_options);
  436. auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
  437. const auto synonym_type = protobufs::TransformationAddSynonym::LOGICAL_AND;
  438. // Required constant is not present in the module.
  439. ASSERT_FALSE(TransformationAddSynonym(7, synonym_type, 50, insert_before)
  440. .IsApplicable(context.get(), transformation_context));
  441. ASSERT_FALSE(TransformationAddSynonym(12, synonym_type, 50, insert_before)
  442. .IsApplicable(context.get(), transformation_context));
  443. }
  444. TEST(TransformationAddSynonymTest, LogicalOrConstantIsNotPresent) {
  445. std::string shader = R"(
  446. OpCapability Shader
  447. %1 = OpExtInstImport "GLSL.std.450"
  448. OpMemoryModel Logical GLSL450
  449. OpEntryPoint Fragment %4 "main"
  450. OpExecutionMode %4 OriginUpperLeft
  451. OpSource ESSL 310
  452. %2 = OpTypeVoid
  453. %3 = OpTypeFunction %2
  454. %6 = OpTypeBool
  455. %7 = OpConstantTrue %6
  456. %10 = OpTypeVector %6 2
  457. %12 = OpConstantComposite %10 %7 %7
  458. %4 = OpFunction %2 None %3
  459. %5 = OpLabel
  460. OpReturn
  461. OpFunctionEnd
  462. )";
  463. const auto env = SPV_ENV_UNIVERSAL_1_3;
  464. const auto consumer = nullptr;
  465. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  466. spvtools::ValidatorOptions validator_options;
  467. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  468. kConsoleMessageConsumer));
  469. TransformationContext transformation_context(
  470. MakeUnique<FactManager>(context.get()), validator_options);
  471. auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
  472. const auto synonym_type = protobufs::TransformationAddSynonym::LOGICAL_OR;
  473. // Required constant is not present in the module.
  474. ASSERT_FALSE(TransformationAddSynonym(7, synonym_type, 50, insert_before)
  475. .IsApplicable(context.get(), transformation_context));
  476. ASSERT_FALSE(TransformationAddSynonym(12, synonym_type, 50, insert_before)
  477. .IsApplicable(context.get(), transformation_context));
  478. }
  479. TEST(TransformationAddSynonymTest, CopyObject) {
  480. std::string shader = R"(
  481. OpCapability Shader
  482. %1 = OpExtInstImport "GLSL.std.450"
  483. OpMemoryModel Logical GLSL450
  484. OpEntryPoint Fragment %4 "main"
  485. OpExecutionMode %4 OriginUpperLeft
  486. OpSource ESSL 310
  487. OpDecorate %8 RelaxedPrecision
  488. %2 = OpTypeVoid
  489. %3 = OpTypeFunction %2
  490. %6 = OpTypeInt 32 1
  491. %7 = OpTypePointer Function %6
  492. %9 = OpConstant %6 4
  493. %10 = OpTypeFloat 32
  494. %11 = OpTypePointer Function %10
  495. %13 = OpConstant %10 4
  496. %14 = OpTypeVector %10 2
  497. %15 = OpTypePointer Function %14
  498. %17 = OpConstant %10 3.4000001
  499. %18 = OpConstantComposite %14 %17 %17
  500. %19 = OpTypeBool
  501. %20 = OpTypeStruct %19
  502. %21 = OpTypePointer Function %20
  503. %23 = OpConstantTrue %19
  504. %24 = OpConstantComposite %20 %23
  505. %4 = OpFunction %2 None %3
  506. %5 = OpLabel
  507. %8 = OpVariable %7 Function
  508. %12 = OpVariable %11 Function
  509. %16 = OpVariable %15 Function
  510. %22 = OpVariable %21 Function
  511. OpStore %8 %9
  512. OpStore %12 %13
  513. OpStore %16 %18
  514. OpStore %22 %24
  515. OpReturn
  516. OpFunctionEnd
  517. )";
  518. const auto env = SPV_ENV_UNIVERSAL_1_3;
  519. const auto consumer = nullptr;
  520. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  521. spvtools::ValidatorOptions validator_options;
  522. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  523. kConsoleMessageConsumer));
  524. TransformationContext transformation_context(
  525. MakeUnique<FactManager>(context.get()), validator_options);
  526. auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
  527. const auto synonym_type = protobufs::TransformationAddSynonym::COPY_OBJECT;
  528. ASSERT_FALSE(
  529. TransformationAddSynonym::IsAdditionalConstantRequired(synonym_type));
  530. uint32_t fresh_id = 50;
  531. for (auto result_id : {9, 13, 17, 18, 23, 24, 22}) {
  532. TransformationAddSynonym transformation(result_id, synonym_type, fresh_id,
  533. insert_before);
  534. ASSERT_TRUE(
  535. transformation.IsApplicable(context.get(), transformation_context));
  536. ApplyAndCheckFreshIds(transformation, context.get(),
  537. &transformation_context);
  538. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  539. MakeDataDescriptor(result_id, {}), MakeDataDescriptor(fresh_id, {})));
  540. ++fresh_id;
  541. }
  542. std::string expected_shader = R"(
  543. OpCapability Shader
  544. %1 = OpExtInstImport "GLSL.std.450"
  545. OpMemoryModel Logical GLSL450
  546. OpEntryPoint Fragment %4 "main"
  547. OpExecutionMode %4 OriginUpperLeft
  548. OpSource ESSL 310
  549. OpDecorate %8 RelaxedPrecision
  550. %2 = OpTypeVoid
  551. %3 = OpTypeFunction %2
  552. %6 = OpTypeInt 32 1
  553. %7 = OpTypePointer Function %6
  554. %9 = OpConstant %6 4
  555. %10 = OpTypeFloat 32
  556. %11 = OpTypePointer Function %10
  557. %13 = OpConstant %10 4
  558. %14 = OpTypeVector %10 2
  559. %15 = OpTypePointer Function %14
  560. %17 = OpConstant %10 3.4000001
  561. %18 = OpConstantComposite %14 %17 %17
  562. %19 = OpTypeBool
  563. %20 = OpTypeStruct %19
  564. %21 = OpTypePointer Function %20
  565. %23 = OpConstantTrue %19
  566. %24 = OpConstantComposite %20 %23
  567. %4 = OpFunction %2 None %3
  568. %5 = OpLabel
  569. %8 = OpVariable %7 Function
  570. %12 = OpVariable %11 Function
  571. %16 = OpVariable %15 Function
  572. %22 = OpVariable %21 Function
  573. OpStore %8 %9
  574. OpStore %12 %13
  575. OpStore %16 %18
  576. OpStore %22 %24
  577. %50 = OpCopyObject %6 %9
  578. %51 = OpCopyObject %10 %13
  579. %52 = OpCopyObject %10 %17
  580. %53 = OpCopyObject %14 %18
  581. %54 = OpCopyObject %19 %23
  582. %55 = OpCopyObject %20 %24
  583. %56 = OpCopyObject %21 %22
  584. OpReturn
  585. OpFunctionEnd
  586. )";
  587. ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
  588. }
  589. TEST(TransformationAddSynonymTest, CopyBooleanConstants) {
  590. std::string shader = R"(
  591. OpCapability Shader
  592. %1 = OpExtInstImport "GLSL.std.450"
  593. OpMemoryModel Logical GLSL450
  594. OpEntryPoint Fragment %4 "main"
  595. OpExecutionMode %4 OriginUpperLeft
  596. OpSource ESSL 310
  597. OpName %4 "main"
  598. %2 = OpTypeVoid
  599. %6 = OpTypeBool
  600. %7 = OpConstantTrue %6
  601. %8 = OpConstantFalse %6
  602. %3 = OpTypeFunction %2
  603. %4 = OpFunction %2 None %3
  604. %5 = OpLabel
  605. OpReturn
  606. OpFunctionEnd
  607. )";
  608. const auto env = SPV_ENV_UNIVERSAL_1_3;
  609. const auto consumer = nullptr;
  610. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  611. spvtools::ValidatorOptions validator_options;
  612. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  613. kConsoleMessageConsumer));
  614. TransformationContext transformation_context(
  615. MakeUnique<FactManager>(context.get()), validator_options);
  616. ASSERT_EQ(0, transformation_context.GetFactManager()
  617. ->GetIdsForWhichSynonymsAreKnown()
  618. .size());
  619. {
  620. TransformationAddSynonym copy_true(
  621. 7, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
  622. MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
  623. ASSERT_TRUE(copy_true.IsApplicable(context.get(), transformation_context));
  624. ApplyAndCheckFreshIds(copy_true, context.get(), &transformation_context);
  625. std::vector<uint32_t> ids_for_which_synonyms_are_known =
  626. transformation_context.GetFactManager()
  627. ->GetIdsForWhichSynonymsAreKnown();
  628. ASSERT_EQ(2, ids_for_which_synonyms_are_known.size());
  629. ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
  630. ids_for_which_synonyms_are_known.end(),
  631. 7) != ids_for_which_synonyms_are_known.end());
  632. ASSERT_EQ(
  633. 2, transformation_context.GetFactManager()->GetSynonymsForId(7).size());
  634. protobufs::DataDescriptor descriptor_100 = MakeDataDescriptor(100, {});
  635. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  636. MakeDataDescriptor(7, {}), descriptor_100));
  637. }
  638. {
  639. TransformationAddSynonym copy_false(
  640. 8, protobufs::TransformationAddSynonym::COPY_OBJECT, 101,
  641. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0));
  642. ASSERT_TRUE(copy_false.IsApplicable(context.get(), transformation_context));
  643. ApplyAndCheckFreshIds(copy_false, context.get(), &transformation_context);
  644. std::vector<uint32_t> ids_for_which_synonyms_are_known =
  645. transformation_context.GetFactManager()
  646. ->GetIdsForWhichSynonymsAreKnown();
  647. ASSERT_EQ(4, ids_for_which_synonyms_are_known.size());
  648. ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
  649. ids_for_which_synonyms_are_known.end(),
  650. 8) != ids_for_which_synonyms_are_known.end());
  651. ASSERT_EQ(
  652. 2, transformation_context.GetFactManager()->GetSynonymsForId(8).size());
  653. protobufs::DataDescriptor descriptor_101 = MakeDataDescriptor(101, {});
  654. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  655. MakeDataDescriptor(8, {}), descriptor_101));
  656. }
  657. {
  658. TransformationAddSynonym copy_false_again(
  659. 101, protobufs::TransformationAddSynonym::COPY_OBJECT, 102,
  660. MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
  661. ASSERT_TRUE(
  662. copy_false_again.IsApplicable(context.get(), transformation_context));
  663. ApplyAndCheckFreshIds(copy_false_again, context.get(),
  664. &transformation_context);
  665. std::vector<uint32_t> ids_for_which_synonyms_are_known =
  666. transformation_context.GetFactManager()
  667. ->GetIdsForWhichSynonymsAreKnown();
  668. ASSERT_EQ(5, ids_for_which_synonyms_are_known.size());
  669. ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
  670. ids_for_which_synonyms_are_known.end(),
  671. 101) != ids_for_which_synonyms_are_known.end());
  672. ASSERT_EQ(
  673. 3,
  674. transformation_context.GetFactManager()->GetSynonymsForId(101).size());
  675. protobufs::DataDescriptor descriptor_102 = MakeDataDescriptor(102, {});
  676. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  677. MakeDataDescriptor(101, {}), descriptor_102));
  678. }
  679. {
  680. TransformationAddSynonym copy_true_again(
  681. 7, protobufs::TransformationAddSynonym::COPY_OBJECT, 103,
  682. MakeInstructionDescriptor(102, spv::Op::OpReturn, 0));
  683. ASSERT_TRUE(
  684. copy_true_again.IsApplicable(context.get(), transformation_context));
  685. ApplyAndCheckFreshIds(copy_true_again, context.get(),
  686. &transformation_context);
  687. std::vector<uint32_t> ids_for_which_synonyms_are_known =
  688. transformation_context.GetFactManager()
  689. ->GetIdsForWhichSynonymsAreKnown();
  690. ASSERT_EQ(6, ids_for_which_synonyms_are_known.size());
  691. ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
  692. ids_for_which_synonyms_are_known.end(),
  693. 7) != ids_for_which_synonyms_are_known.end());
  694. ASSERT_EQ(
  695. 3, transformation_context.GetFactManager()->GetSynonymsForId(7).size());
  696. protobufs::DataDescriptor descriptor_103 = MakeDataDescriptor(103, {});
  697. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  698. MakeDataDescriptor(7, {}), descriptor_103));
  699. }
  700. std::string after_transformation = R"(
  701. OpCapability Shader
  702. %1 = OpExtInstImport "GLSL.std.450"
  703. OpMemoryModel Logical GLSL450
  704. OpEntryPoint Fragment %4 "main"
  705. OpExecutionMode %4 OriginUpperLeft
  706. OpSource ESSL 310
  707. OpName %4 "main"
  708. %2 = OpTypeVoid
  709. %6 = OpTypeBool
  710. %7 = OpConstantTrue %6
  711. %8 = OpConstantFalse %6
  712. %3 = OpTypeFunction %2
  713. %4 = OpFunction %2 None %3
  714. %5 = OpLabel
  715. %100 = OpCopyObject %6 %7
  716. %101 = OpCopyObject %6 %8
  717. %102 = OpCopyObject %6 %101
  718. %103 = OpCopyObject %6 %7
  719. OpReturn
  720. OpFunctionEnd
  721. )";
  722. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  723. }
  724. TEST(TransformationAddSynonymTest, CheckIllegalCases) {
  725. // The following SPIR-V comes from this GLSL, pushed through spirv-opt
  726. // and then doctored a bit.
  727. //
  728. // #version 310 es
  729. //
  730. // precision highp float;
  731. //
  732. // struct S {
  733. // int a;
  734. // float b;
  735. // };
  736. //
  737. // layout(set = 0, binding = 2) uniform block {
  738. // S s;
  739. // lowp float f;
  740. // int ii;
  741. // } ubuf;
  742. //
  743. // layout(location = 0) out vec4 color;
  744. //
  745. // void main() {
  746. // float c = 0.0;
  747. // lowp float d = 0.0;
  748. // S localS = ubuf.s;
  749. // for (int i = 0; i < ubuf.s.a; i++) {
  750. // switch (ubuf.ii) {
  751. // case 0:
  752. // c += 0.1;
  753. // d += 0.2;
  754. // case 1:
  755. // c += 0.1;
  756. // if (c > d) {
  757. // d += 0.2;
  758. // } else {
  759. // d += c;
  760. // }
  761. // break;
  762. // default:
  763. // i += 1;
  764. // localS.b += d;
  765. // }
  766. // }
  767. // color = vec4(c, d, localS.b, 1.0);
  768. // }
  769. std::string shader = R"(
  770. OpCapability Shader
  771. %1 = OpExtInstImport "GLSL.std.450"
  772. OpMemoryModel Logical GLSL450
  773. OpEntryPoint Fragment %4 "main" %80
  774. OpExecutionMode %4 OriginUpperLeft
  775. OpSource ESSL 310
  776. OpName %4 "main"
  777. OpName %12 "S"
  778. OpMemberName %12 0 "a"
  779. OpMemberName %12 1 "b"
  780. OpName %15 "S"
  781. OpMemberName %15 0 "a"
  782. OpMemberName %15 1 "b"
  783. OpName %16 "block"
  784. OpMemberName %16 0 "s"
  785. OpMemberName %16 1 "f"
  786. OpMemberName %16 2 "ii"
  787. OpName %18 "ubuf"
  788. OpName %80 "color"
  789. OpMemberDecorate %12 0 RelaxedPrecision
  790. OpMemberDecorate %15 0 RelaxedPrecision
  791. OpMemberDecorate %15 0 Offset 0
  792. OpMemberDecorate %15 1 Offset 4
  793. OpMemberDecorate %16 0 Offset 0
  794. OpMemberDecorate %16 1 RelaxedPrecision
  795. OpMemberDecorate %16 1 Offset 16
  796. OpMemberDecorate %16 2 RelaxedPrecision
  797. OpMemberDecorate %16 2 Offset 20
  798. OpDecorate %16 Block
  799. OpDecorate %18 DescriptorSet 0
  800. OpDecorate %18 Binding 2
  801. OpDecorate %38 RelaxedPrecision
  802. OpDecorate %43 RelaxedPrecision
  803. OpDecorate %53 RelaxedPrecision
  804. OpDecorate %62 RelaxedPrecision
  805. OpDecorate %69 RelaxedPrecision
  806. OpDecorate %77 RelaxedPrecision
  807. OpDecorate %80 Location 0
  808. OpDecorate %101 RelaxedPrecision
  809. OpDecorate %102 RelaxedPrecision
  810. OpDecorate %96 RelaxedPrecision
  811. OpDecorate %108 RelaxedPrecision
  812. OpDecorate %107 RelaxedPrecision
  813. OpDecorate %98 RelaxedPrecision
  814. %2 = OpTypeVoid
  815. %3 = OpTypeFunction %2
  816. %6 = OpTypeFloat 32
  817. %9 = OpConstant %6 0
  818. %11 = OpTypeInt 32 1
  819. %12 = OpTypeStruct %11 %6
  820. %15 = OpTypeStruct %11 %6
  821. %16 = OpTypeStruct %15 %6 %11
  822. %17 = OpTypePointer Uniform %16
  823. %18 = OpVariable %17 Uniform
  824. %19 = OpConstant %11 0
  825. %20 = OpTypePointer Uniform %15
  826. %27 = OpConstant %11 1
  827. %36 = OpTypePointer Uniform %11
  828. %39 = OpTypeBool
  829. %41 = OpConstant %11 2
  830. %48 = OpConstant %6 0.100000001
  831. %51 = OpConstant %6 0.200000003
  832. %78 = OpTypeVector %6 4
  833. %79 = OpTypePointer Output %78
  834. %80 = OpVariable %79 Output
  835. %85 = OpConstant %6 1
  836. %95 = OpUndef %12
  837. %112 = OpTypePointer Uniform %6
  838. %113 = OpTypeInt 32 0
  839. %114 = OpConstant %113 1
  840. %179 = OpTypePointer Function %39
  841. %4 = OpFunction %2 None %3
  842. %5 = OpLabel
  843. %180 = OpVariable %179 Function
  844. %181 = OpVariable %179 Function
  845. %182 = OpVariable %179 Function
  846. %21 = OpAccessChain %20 %18 %19
  847. %115 = OpAccessChain %112 %21 %114
  848. %116 = OpLoad %6 %115
  849. %90 = OpCompositeInsert %12 %116 %95 1
  850. OpBranch %30
  851. %30 = OpLabel
  852. %99 = OpPhi %12 %90 %5 %109 %47
  853. %98 = OpPhi %6 %9 %5 %107 %47
  854. %97 = OpPhi %6 %9 %5 %105 %47
  855. %96 = OpPhi %11 %19 %5 %77 %47
  856. %37 = OpAccessChain %36 %18 %19 %19
  857. %38 = OpLoad %11 %37
  858. %40 = OpSLessThan %39 %96 %38
  859. OpLoopMerge %32 %47 None
  860. OpBranchConditional %40 %31 %32
  861. %31 = OpLabel
  862. %42 = OpAccessChain %36 %18 %41
  863. %43 = OpLoad %11 %42
  864. OpSelectionMerge %45 None
  865. OpSwitch %43 %46 0 %44 1 %45
  866. %46 = OpLabel
  867. %69 = OpIAdd %11 %96 %27
  868. %72 = OpCompositeExtract %6 %99 1
  869. %73 = OpFAdd %6 %72 %98
  870. %93 = OpCompositeInsert %12 %73 %99 1
  871. OpBranch %47
  872. %44 = OpLabel
  873. %50 = OpFAdd %6 %97 %48
  874. %53 = OpFAdd %6 %98 %51
  875. OpBranch %45
  876. %45 = OpLabel
  877. %101 = OpPhi %6 %98 %31 %53 %44
  878. %100 = OpPhi %6 %97 %31 %50 %44
  879. %55 = OpFAdd %6 %100 %48
  880. %58 = OpFOrdGreaterThan %39 %55 %101
  881. OpSelectionMerge %60 None
  882. OpBranchConditional %58 %59 %63
  883. %59 = OpLabel
  884. %62 = OpFAdd %6 %101 %51
  885. OpBranch %60
  886. %63 = OpLabel
  887. %66 = OpFAdd %6 %101 %55
  888. OpBranch %60
  889. %60 = OpLabel
  890. %108 = OpPhi %6 %62 %59 %66 %63
  891. OpBranch %47
  892. %47 = OpLabel
  893. %109 = OpPhi %12 %93 %46 %99 %60
  894. %107 = OpPhi %6 %98 %46 %108 %60
  895. %105 = OpPhi %6 %97 %46 %55 %60
  896. %102 = OpPhi %11 %69 %46 %96 %60
  897. %77 = OpIAdd %11 %102 %27
  898. OpBranch %30
  899. %32 = OpLabel
  900. %84 = OpCompositeExtract %6 %99 1
  901. %86 = OpCompositeConstruct %78 %97 %98 %84 %85
  902. OpStore %80 %86
  903. OpReturn
  904. OpFunctionEnd
  905. )";
  906. const auto env = SPV_ENV_UNIVERSAL_1_3;
  907. const auto consumer = nullptr;
  908. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  909. spvtools::ValidatorOptions validator_options;
  910. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  911. kConsoleMessageConsumer));
  912. TransformationContext transformation_context(
  913. MakeUnique<FactManager>(context.get()), validator_options);
  914. // Inapplicable because %18 is decorated.
  915. ASSERT_FALSE(TransformationAddSynonym(
  916. 18, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  917. MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0))
  918. .IsApplicable(context.get(), transformation_context));
  919. // Inapplicable because %77 is decorated.
  920. ASSERT_FALSE(TransformationAddSynonym(
  921. 77, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  922. MakeInstructionDescriptor(77, spv::Op::OpBranch, 0))
  923. .IsApplicable(context.get(), transformation_context));
  924. // Inapplicable because %80 is decorated.
  925. ASSERT_FALSE(TransformationAddSynonym(
  926. 80, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  927. MakeInstructionDescriptor(77, spv::Op::OpIAdd, 0))
  928. .IsApplicable(context.get(), transformation_context));
  929. // Inapplicable because %84 is not available at the requested point
  930. ASSERT_FALSE(
  931. TransformationAddSynonym(
  932. 84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  933. MakeInstructionDescriptor(32, spv::Op::OpCompositeExtract, 0))
  934. .IsApplicable(context.get(), transformation_context));
  935. // Fine because %84 is available at the requested point
  936. ASSERT_TRUE(
  937. TransformationAddSynonym(
  938. 84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  939. MakeInstructionDescriptor(32, spv::Op::OpCompositeConstruct, 0))
  940. .IsApplicable(context.get(), transformation_context));
  941. // Inapplicable because id %9 is already in use
  942. ASSERT_FALSE(
  943. TransformationAddSynonym(
  944. 84, protobufs::TransformationAddSynonym::COPY_OBJECT, 9,
  945. MakeInstructionDescriptor(32, spv::Op::OpCompositeConstruct, 0))
  946. .IsApplicable(context.get(), transformation_context));
  947. // Inapplicable because the requested point does not exist
  948. ASSERT_FALSE(TransformationAddSynonym(
  949. 84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  950. MakeInstructionDescriptor(86, spv::Op::OpReturn, 2))
  951. .IsApplicable(context.get(), transformation_context));
  952. // Inapplicable because %9 is not in a function
  953. ASSERT_FALSE(TransformationAddSynonym(
  954. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  955. MakeInstructionDescriptor(9, spv::Op::OpTypeInt, 0))
  956. .IsApplicable(context.get(), transformation_context));
  957. // Inapplicable because the insert point is right before, or inside, a chunk
  958. // of OpPhis
  959. ASSERT_FALSE(TransformationAddSynonym(
  960. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  961. MakeInstructionDescriptor(30, spv::Op::OpPhi, 0))
  962. .IsApplicable(context.get(), transformation_context));
  963. ASSERT_FALSE(TransformationAddSynonym(
  964. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  965. MakeInstructionDescriptor(99, spv::Op::OpPhi, 1))
  966. .IsApplicable(context.get(), transformation_context));
  967. // OK, because the insert point is just after a chunk of OpPhis.
  968. ASSERT_TRUE(TransformationAddSynonym(
  969. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  970. MakeInstructionDescriptor(96, spv::Op::OpAccessChain, 0))
  971. .IsApplicable(context.get(), transformation_context));
  972. // Inapplicable because the insert point is right after an OpSelectionMerge
  973. ASSERT_FALSE(
  974. TransformationAddSynonym(
  975. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  976. MakeInstructionDescriptor(58, spv::Op::OpBranchConditional, 0))
  977. .IsApplicable(context.get(), transformation_context));
  978. // OK, because the insert point is right before the OpSelectionMerge
  979. ASSERT_TRUE(TransformationAddSynonym(
  980. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  981. MakeInstructionDescriptor(58, spv::Op::OpSelectionMerge, 0))
  982. .IsApplicable(context.get(), transformation_context));
  983. // Inapplicable because the insert point is right after an OpSelectionMerge
  984. ASSERT_FALSE(TransformationAddSynonym(
  985. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  986. MakeInstructionDescriptor(43, spv::Op::OpSwitch, 0))
  987. .IsApplicable(context.get(), transformation_context));
  988. // OK, because the insert point is right before the OpSelectionMerge
  989. ASSERT_TRUE(TransformationAddSynonym(
  990. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  991. MakeInstructionDescriptor(43, spv::Op::OpSelectionMerge, 0))
  992. .IsApplicable(context.get(), transformation_context));
  993. // Inapplicable because the insert point is right after an OpLoopMerge
  994. ASSERT_FALSE(
  995. TransformationAddSynonym(
  996. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  997. MakeInstructionDescriptor(40, spv::Op::OpBranchConditional, 0))
  998. .IsApplicable(context.get(), transformation_context));
  999. // OK, because the insert point is right before the OpLoopMerge
  1000. ASSERT_TRUE(TransformationAddSynonym(
  1001. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  1002. MakeInstructionDescriptor(40, spv::Op::OpLoopMerge, 0))
  1003. .IsApplicable(context.get(), transformation_context));
  1004. // Inapplicable because id %300 does not exist
  1005. ASSERT_FALSE(TransformationAddSynonym(
  1006. 300, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  1007. MakeInstructionDescriptor(40, spv::Op::OpLoopMerge, 0))
  1008. .IsApplicable(context.get(), transformation_context));
  1009. // Inapplicable because the following instruction is OpVariable
  1010. ASSERT_FALSE(TransformationAddSynonym(
  1011. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  1012. MakeInstructionDescriptor(180, spv::Op::OpVariable, 0))
  1013. .IsApplicable(context.get(), transformation_context));
  1014. ASSERT_FALSE(TransformationAddSynonym(
  1015. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  1016. MakeInstructionDescriptor(181, spv::Op::OpVariable, 0))
  1017. .IsApplicable(context.get(), transformation_context));
  1018. ASSERT_FALSE(TransformationAddSynonym(
  1019. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  1020. MakeInstructionDescriptor(182, spv::Op::OpVariable, 0))
  1021. .IsApplicable(context.get(), transformation_context));
  1022. // OK, because this is just past the group of OpVariable instructions.
  1023. ASSERT_TRUE(TransformationAddSynonym(
  1024. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
  1025. MakeInstructionDescriptor(182, spv::Op::OpAccessChain, 0))
  1026. .IsApplicable(context.get(), transformation_context));
  1027. }
  1028. TEST(TransformationAddSynonymTest, MiscellaneousCopies) {
  1029. // The following SPIR-V comes from this GLSL:
  1030. //
  1031. // #version 310 es
  1032. //
  1033. // precision highp float;
  1034. //
  1035. // float g;
  1036. //
  1037. // vec4 h;
  1038. //
  1039. // void main() {
  1040. // int a;
  1041. // int b;
  1042. // b = int(g);
  1043. // h.x = float(a);
  1044. // }
  1045. std::string shader = R"(
  1046. OpCapability Shader
  1047. %1 = OpExtInstImport "GLSL.std.450"
  1048. OpMemoryModel Logical GLSL450
  1049. OpEntryPoint Fragment %4 "main"
  1050. OpExecutionMode %4 OriginUpperLeft
  1051. OpSource ESSL 310
  1052. OpName %4 "main"
  1053. OpName %8 "b"
  1054. OpName %11 "g"
  1055. OpName %16 "h"
  1056. OpName %17 "a"
  1057. %2 = OpTypeVoid
  1058. %3 = OpTypeFunction %2
  1059. %6 = OpTypeInt 32 1
  1060. %7 = OpTypePointer Function %6
  1061. %9 = OpTypeFloat 32
  1062. %10 = OpTypePointer Private %9
  1063. %11 = OpVariable %10 Private
  1064. %14 = OpTypeVector %9 4
  1065. %15 = OpTypePointer Private %14
  1066. %16 = OpVariable %15 Private
  1067. %20 = OpTypeInt 32 0
  1068. %21 = OpConstant %20 0
  1069. %4 = OpFunction %2 None %3
  1070. %5 = OpLabel
  1071. %8 = OpVariable %7 Function
  1072. %17 = OpVariable %7 Function
  1073. %12 = OpLoad %9 %11
  1074. %13 = OpConvertFToS %6 %12
  1075. OpStore %8 %13
  1076. %18 = OpLoad %6 %17
  1077. %19 = OpConvertSToF %9 %18
  1078. %22 = OpAccessChain %10 %16 %21
  1079. OpStore %22 %19
  1080. OpReturn
  1081. OpFunctionEnd
  1082. )";
  1083. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1084. const auto consumer = nullptr;
  1085. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1086. spvtools::ValidatorOptions validator_options;
  1087. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1088. kConsoleMessageConsumer));
  1089. TransformationContext transformation_context(
  1090. MakeUnique<FactManager>(context.get()), validator_options);
  1091. std::vector<TransformationAddSynonym> transformations = {
  1092. TransformationAddSynonym(
  1093. 19, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
  1094. MakeInstructionDescriptor(22, spv::Op::OpStore, 0)),
  1095. TransformationAddSynonym(
  1096. 22, protobufs::TransformationAddSynonym::COPY_OBJECT, 101,
  1097. MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
  1098. TransformationAddSynonym(
  1099. 12, protobufs::TransformationAddSynonym::COPY_OBJECT, 102,
  1100. MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
  1101. TransformationAddSynonym(
  1102. 11, protobufs::TransformationAddSynonym::COPY_OBJECT, 103,
  1103. MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
  1104. TransformationAddSynonym(
  1105. 16, protobufs::TransformationAddSynonym::COPY_OBJECT, 104,
  1106. MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
  1107. TransformationAddSynonym(
  1108. 8, protobufs::TransformationAddSynonym::COPY_OBJECT, 105,
  1109. MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
  1110. TransformationAddSynonym(
  1111. 17, protobufs::TransformationAddSynonym::COPY_OBJECT, 106,
  1112. MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0))};
  1113. for (auto& transformation : transformations) {
  1114. ASSERT_TRUE(
  1115. transformation.IsApplicable(context.get(), transformation_context));
  1116. ApplyAndCheckFreshIds(transformation, context.get(),
  1117. &transformation_context);
  1118. }
  1119. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1120. kConsoleMessageConsumer));
  1121. std::string after_transformation = R"(
  1122. OpCapability Shader
  1123. %1 = OpExtInstImport "GLSL.std.450"
  1124. OpMemoryModel Logical GLSL450
  1125. OpEntryPoint Fragment %4 "main"
  1126. OpExecutionMode %4 OriginUpperLeft
  1127. OpSource ESSL 310
  1128. OpName %4 "main"
  1129. OpName %8 "b"
  1130. OpName %11 "g"
  1131. OpName %16 "h"
  1132. OpName %17 "a"
  1133. %2 = OpTypeVoid
  1134. %3 = OpTypeFunction %2
  1135. %6 = OpTypeInt 32 1
  1136. %7 = OpTypePointer Function %6
  1137. %9 = OpTypeFloat 32
  1138. %10 = OpTypePointer Private %9
  1139. %11 = OpVariable %10 Private
  1140. %14 = OpTypeVector %9 4
  1141. %15 = OpTypePointer Private %14
  1142. %16 = OpVariable %15 Private
  1143. %20 = OpTypeInt 32 0
  1144. %21 = OpConstant %20 0
  1145. %4 = OpFunction %2 None %3
  1146. %5 = OpLabel
  1147. %8 = OpVariable %7 Function
  1148. %17 = OpVariable %7 Function
  1149. %12 = OpLoad %9 %11
  1150. %13 = OpConvertFToS %6 %12
  1151. OpStore %8 %13
  1152. %18 = OpLoad %6 %17
  1153. %19 = OpConvertSToF %9 %18
  1154. %22 = OpAccessChain %10 %16 %21
  1155. %106 = OpCopyObject %7 %17
  1156. %105 = OpCopyObject %7 %8
  1157. %104 = OpCopyObject %15 %16
  1158. %103 = OpCopyObject %10 %11
  1159. %102 = OpCopyObject %9 %12
  1160. %101 = OpCopyObject %10 %22
  1161. %100 = OpCopyObject %9 %19
  1162. OpStore %22 %19
  1163. OpReturn
  1164. OpFunctionEnd
  1165. )";
  1166. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  1167. }
  1168. TEST(TransformationAddSynonymTest, DoNotCopyNullPointers) {
  1169. std::string shader = R"(
  1170. OpCapability Shader
  1171. OpCapability VariablePointers
  1172. %1 = OpExtInstImport "GLSL.std.450"
  1173. OpMemoryModel Logical GLSL450
  1174. OpEntryPoint Fragment %4 "main"
  1175. OpExecutionMode %4 OriginUpperLeft
  1176. OpSource ESSL 310
  1177. %2 = OpTypeVoid
  1178. %3 = OpTypeFunction %2
  1179. %6 = OpTypeInt 32 1
  1180. %7 = OpTypePointer Function %6
  1181. %8 = OpConstantNull %7
  1182. %4 = OpFunction %2 None %3
  1183. %5 = OpLabel
  1184. OpReturn
  1185. OpFunctionEnd
  1186. )";
  1187. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1188. const auto consumer = nullptr;
  1189. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1190. spvtools::ValidatorOptions validator_options;
  1191. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1192. kConsoleMessageConsumer));
  1193. TransformationContext transformation_context(
  1194. MakeUnique<FactManager>(context.get()), validator_options);
  1195. // Illegal to copy null.
  1196. ASSERT_FALSE(TransformationAddSynonym(
  1197. 8, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
  1198. MakeInstructionDescriptor(5, spv::Op::OpReturn, 0))
  1199. .IsApplicable(context.get(), transformation_context));
  1200. }
  1201. TEST(TransformationAddSynonymTest, PropagateIrrelevantPointeeFact) {
  1202. // Checks that if a pointer is known to have an irrelevant value, the same
  1203. // holds after the pointer is copied.
  1204. std::string shader = R"(
  1205. OpCapability Shader
  1206. %1 = OpExtInstImport "GLSL.std.450"
  1207. OpMemoryModel Logical GLSL450
  1208. OpEntryPoint Fragment %4 "main"
  1209. OpExecutionMode %4 OriginUpperLeft
  1210. OpSource ESSL 310
  1211. %2 = OpTypeVoid
  1212. %3 = OpTypeFunction %2
  1213. %6 = OpTypeInt 32 1
  1214. %7 = OpTypePointer Function %6
  1215. %4 = OpFunction %2 None %3
  1216. %5 = OpLabel
  1217. %8 = OpVariable %7 Function
  1218. %9 = OpVariable %7 Function
  1219. OpReturn
  1220. OpFunctionEnd
  1221. )";
  1222. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1223. const auto consumer = nullptr;
  1224. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1225. spvtools::ValidatorOptions validator_options;
  1226. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1227. kConsoleMessageConsumer));
  1228. TransformationContext transformation_context(
  1229. MakeUnique<FactManager>(context.get()), validator_options);
  1230. transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(8);
  1231. TransformationAddSynonym transformation1(
  1232. 8, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
  1233. MakeInstructionDescriptor(9, spv::Op::OpReturn, 0));
  1234. TransformationAddSynonym transformation2(
  1235. 9, protobufs::TransformationAddSynonym::COPY_OBJECT, 101,
  1236. MakeInstructionDescriptor(9, spv::Op::OpReturn, 0));
  1237. TransformationAddSynonym transformation3(
  1238. 100, protobufs::TransformationAddSynonym::COPY_OBJECT, 102,
  1239. MakeInstructionDescriptor(9, spv::Op::OpReturn, 0));
  1240. ASSERT_TRUE(
  1241. transformation1.IsApplicable(context.get(), transformation_context));
  1242. ApplyAndCheckFreshIds(transformation1, context.get(),
  1243. &transformation_context);
  1244. ASSERT_TRUE(
  1245. transformation2.IsApplicable(context.get(), transformation_context));
  1246. ApplyAndCheckFreshIds(transformation2, context.get(),
  1247. &transformation_context);
  1248. ASSERT_TRUE(
  1249. transformation3.IsApplicable(context.get(), transformation_context));
  1250. ApplyAndCheckFreshIds(transformation3, context.get(),
  1251. &transformation_context);
  1252. ASSERT_TRUE(
  1253. transformation_context.GetFactManager()->PointeeValueIsIrrelevant(8));
  1254. ASSERT_TRUE(
  1255. transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
  1256. ASSERT_TRUE(
  1257. transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
  1258. ASSERT_FALSE(
  1259. transformation_context.GetFactManager()->PointeeValueIsIrrelevant(9));
  1260. ASSERT_FALSE(
  1261. transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
  1262. }
  1263. TEST(TransformationAddSynonymTest, DoNotCopyOpSampledImage) {
  1264. // This checks that we do not try to copy the result id of an OpSampledImage
  1265. // instruction.
  1266. std::string shader = R"(
  1267. OpCapability Shader
  1268. OpCapability SampledBuffer
  1269. OpCapability ImageBuffer
  1270. %1 = OpExtInstImport "GLSL.std.450"
  1271. OpMemoryModel Logical GLSL450
  1272. OpEntryPoint Fragment %2 "main" %40 %41
  1273. OpExecutionMode %2 OriginUpperLeft
  1274. OpSource GLSL 450
  1275. OpDecorate %40 DescriptorSet 0
  1276. OpDecorate %40 Binding 69
  1277. OpDecorate %41 DescriptorSet 0
  1278. OpDecorate %41 Binding 1
  1279. %54 = OpTypeFloat 32
  1280. %76 = OpTypeVector %54 4
  1281. %55 = OpConstant %54 0
  1282. %56 = OpTypeVector %54 3
  1283. %94 = OpTypeVector %54 2
  1284. %112 = OpConstantComposite %94 %55 %55
  1285. %57 = OpConstantComposite %56 %55 %55 %55
  1286. %15 = OpTypeImage %54 2D 2 0 0 1 Unknown
  1287. %114 = OpTypePointer UniformConstant %15
  1288. %38 = OpTypeSampler
  1289. %125 = OpTypePointer UniformConstant %38
  1290. %132 = OpTypeVoid
  1291. %133 = OpTypeFunction %132
  1292. %45 = OpTypeSampledImage %15
  1293. %40 = OpVariable %114 UniformConstant
  1294. %41 = OpVariable %125 UniformConstant
  1295. %2 = OpFunction %132 None %133
  1296. %164 = OpLabel
  1297. %184 = OpLoad %15 %40
  1298. %213 = OpLoad %38 %41
  1299. %216 = OpSampledImage %45 %184 %213
  1300. %217 = OpImageSampleImplicitLod %76 %216 %112 Bias %55
  1301. OpReturn
  1302. OpFunctionEnd
  1303. )";
  1304. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1305. const auto consumer = nullptr;
  1306. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1307. spvtools::ValidatorOptions validator_options;
  1308. TransformationContext transformation_context(
  1309. MakeUnique<FactManager>(context.get()), validator_options);
  1310. ASSERT_FALSE(
  1311. TransformationAddSynonym(
  1312. 216, protobufs::TransformationAddSynonym::COPY_OBJECT, 500,
  1313. MakeInstructionDescriptor(217, spv::Op::OpImageSampleImplicitLod, 0))
  1314. .IsApplicable(context.get(), transformation_context));
  1315. }
  1316. TEST(TransformationAddSynonymTest, DoNotCopyVoidRunctionResult) {
  1317. // This checks that we do not try to copy the result of a void function.
  1318. std::string shader = R"(
  1319. OpCapability Shader
  1320. %1 = OpExtInstImport "GLSL.std.450"
  1321. OpMemoryModel Logical GLSL450
  1322. OpEntryPoint Fragment %4 "main"
  1323. OpExecutionMode %4 OriginUpperLeft
  1324. OpSource ESSL 320
  1325. OpName %4 "main"
  1326. OpName %6 "foo("
  1327. %2 = OpTypeVoid
  1328. %3 = OpTypeFunction %2
  1329. %4 = OpFunction %2 None %3
  1330. %5 = OpLabel
  1331. %8 = OpFunctionCall %2 %6
  1332. OpReturn
  1333. OpFunctionEnd
  1334. %6 = OpFunction %2 None %3
  1335. %7 = OpLabel
  1336. OpReturn
  1337. OpFunctionEnd
  1338. )";
  1339. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1340. const auto consumer = nullptr;
  1341. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1342. spvtools::ValidatorOptions validator_options;
  1343. TransformationContext transformation_context(
  1344. MakeUnique<FactManager>(context.get()), validator_options);
  1345. ASSERT_FALSE(TransformationAddSynonym(
  1346. 8, protobufs::TransformationAddSynonym::COPY_OBJECT, 500,
  1347. MakeInstructionDescriptor(8, spv::Op::OpReturn, 0))
  1348. .IsApplicable(context.get(), transformation_context));
  1349. }
  1350. TEST(TransformationAddSynonymTest, HandlesDeadBlocks) {
  1351. std::string shader = R"(
  1352. OpCapability Shader
  1353. %1 = OpExtInstImport "GLSL.std.450"
  1354. OpMemoryModel Logical GLSL450
  1355. OpEntryPoint Fragment %4 "main"
  1356. OpExecutionMode %4 OriginUpperLeft
  1357. OpSource ESSL 320
  1358. %2 = OpTypeVoid
  1359. %3 = OpTypeFunction %2
  1360. %6 = OpTypeBool
  1361. %7 = OpConstantTrue %6
  1362. %11 = OpTypePointer Function %6
  1363. %4 = OpFunction %2 None %3
  1364. %5 = OpLabel
  1365. %12 = OpVariable %11 Function
  1366. OpSelectionMerge %10 None
  1367. OpBranchConditional %7 %8 %9
  1368. %8 = OpLabel
  1369. OpBranch %10
  1370. %9 = OpLabel
  1371. OpBranch %10
  1372. %10 = OpLabel
  1373. OpReturn
  1374. OpFunctionEnd
  1375. )";
  1376. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1377. const auto consumer = nullptr;
  1378. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1379. spvtools::ValidatorOptions validator_options;
  1380. TransformationContext transformation_context(
  1381. MakeUnique<FactManager>(context.get()), validator_options);
  1382. transformation_context.GetFactManager()->AddFactBlockIsDead(9);
  1383. auto insert_before = MakeInstructionDescriptor(9, spv::Op::OpBranch, 0);
  1384. ASSERT_FALSE(TransformationAddSynonym(
  1385. 7, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
  1386. insert_before)
  1387. .IsApplicable(context.get(), transformation_context));
  1388. ASSERT_FALSE(TransformationAddSynonym(
  1389. 12, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
  1390. insert_before)
  1391. .IsApplicable(context.get(), transformation_context));
  1392. }
  1393. } // namespace
  1394. } // namespace fuzz
  1395. } // namespace spvtools