data_synonym_transformation_test.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  1. // Copyright (c) 2019 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "source/fuzz/data_descriptor.h"
  15. #include "source/fuzz/id_use_descriptor.h"
  16. #include "source/fuzz/instruction_descriptor.h"
  17. #include "source/fuzz/transformation_composite_extract.h"
  18. #include "source/fuzz/transformation_replace_id_with_synonym.h"
  19. #include "source/fuzz/transformation_vector_shuffle.h"
  20. #include "test/fuzz/fuzz_test_util.h"
  21. namespace spvtools {
  22. namespace fuzz {
  23. namespace {
  24. // This file captures tests that check correctness of the collective use of a
  25. // number of transformations that relate to data synonyms.
  26. protobufs::Fact MakeSynonymFact(uint32_t first_id,
  27. std::vector<uint32_t>&& first_indices,
  28. uint32_t second_id,
  29. std::vector<uint32_t>&& second_indices) {
  30. protobufs::FactDataSynonym data_synonym_fact;
  31. *data_synonym_fact.mutable_data1() =
  32. MakeDataDescriptor(first_id, std::move(first_indices));
  33. *data_synonym_fact.mutable_data2() =
  34. MakeDataDescriptor(second_id, std::move(second_indices));
  35. protobufs::Fact result;
  36. *result.mutable_data_synonym_fact() = data_synonym_fact;
  37. return result;
  38. }
  39. TEST(DataSynonymTransformationTest, ArrayCompositeSynonyms) {
  40. std::string shader = R"(
  41. OpCapability Shader
  42. %1 = OpExtInstImport "GLSL.std.450"
  43. OpMemoryModel Logical GLSL450
  44. OpEntryPoint Fragment %4 "main"
  45. OpExecutionMode %4 OriginUpperLeft
  46. OpSource ESSL 310
  47. OpName %4 "main"
  48. OpName %11 "A"
  49. OpName %20 "B"
  50. OpName %31 "g"
  51. OpName %35 "h"
  52. OpDecorate %11 RelaxedPrecision
  53. OpDecorate %22 RelaxedPrecision
  54. OpDecorate %27 RelaxedPrecision
  55. OpDecorate %35 RelaxedPrecision
  56. OpDecorate %36 RelaxedPrecision
  57. OpDecorate %40 RelaxedPrecision
  58. OpDecorate %41 RelaxedPrecision
  59. %2 = OpTypeVoid
  60. %3 = OpTypeFunction %2
  61. %6 = OpTypeInt 32 1
  62. %7 = OpTypeInt 32 0
  63. %8 = OpConstant %7 3
  64. %9 = OpTypeArray %6 %8
  65. %10 = OpTypePointer Function %9
  66. %12 = OpConstant %6 0
  67. %13 = OpConstant %6 3
  68. %14 = OpTypePointer Function %6
  69. %16 = OpTypeFloat 32
  70. %17 = OpConstant %7 4
  71. %18 = OpTypeArray %16 %17
  72. %19 = OpTypePointer Function %18
  73. %24 = OpTypePointer Function %16
  74. %28 = OpConstant %16 42
  75. %30 = OpConstant %6 2
  76. %34 = OpConstant %6 1
  77. %38 = OpConstant %6 42
  78. %4 = OpFunction %2 None %3
  79. %5 = OpLabel
  80. %11 = OpVariable %10 Function
  81. %20 = OpVariable %19 Function
  82. %31 = OpVariable %24 Function
  83. %35 = OpVariable %14 Function
  84. %15 = OpAccessChain %14 %11 %12
  85. %21 = OpAccessChain %14 %11 %12
  86. %22 = OpLoad %6 %21
  87. %100 = OpCompositeConstruct %9 %12 %13 %22
  88. OpStore %15 %13
  89. %23 = OpConvertSToF %16 %22
  90. %25 = OpAccessChain %24 %20 %12
  91. OpStore %25 %23
  92. %26 = OpAccessChain %14 %11 %12
  93. %27 = OpLoad %6 %26
  94. %29 = OpAccessChain %24 %20 %27
  95. OpStore %29 %28
  96. %32 = OpLoad %16 %31
  97. %101 = OpCompositeConstruct %18 %28 %23 %32 %23
  98. %50 = OpCopyObject %16 %23
  99. %51 = OpCopyObject %16 %23
  100. %33 = OpAccessChain %24 %20 %30
  101. OpStore %33 %28
  102. OpStore %33 %32
  103. %36 = OpLoad %6 %35
  104. %37 = OpAccessChain %14 %11 %34
  105. OpStore %37 %36
  106. %39 = OpAccessChain %14 %11 %12
  107. %40 = OpLoad %6 %39
  108. %41 = OpIAdd %6 %38 %40
  109. %42 = OpAccessChain %14 %11 %30
  110. OpStore %42 %41
  111. OpReturn
  112. OpFunctionEnd
  113. )";
  114. const auto env = SPV_ENV_UNIVERSAL_1_3;
  115. const auto consumer = nullptr;
  116. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  117. ASSERT_TRUE(IsValid(env, context.get()));
  118. FactManager fact_manager;
  119. fact_manager.AddFact(MakeSynonymFact(12, {}, 100, {0}), context.get());
  120. fact_manager.AddFact(MakeSynonymFact(13, {}, 100, {1}), context.get());
  121. fact_manager.AddFact(MakeSynonymFact(22, {}, 100, {2}), context.get());
  122. fact_manager.AddFact(MakeSynonymFact(28, {}, 101, {0}), context.get());
  123. fact_manager.AddFact(MakeSynonymFact(23, {}, 101, {1}), context.get());
  124. fact_manager.AddFact(MakeSynonymFact(32, {}, 101, {2}), context.get());
  125. fact_manager.AddFact(MakeSynonymFact(23, {}, 101, {3}), context.get());
  126. // Replace %12 with %100[0] in '%25 = OpAccessChain %24 %20 %12'
  127. auto instruction_descriptor_1 =
  128. MakeInstructionDescriptor(25, SpvOpAccessChain, 0);
  129. auto good_extract_1 =
  130. TransformationCompositeExtract(instruction_descriptor_1, 102, 100, {0});
  131. // Bad: id already in use
  132. auto bad_extract_1 = TransformationCompositeExtract(
  133. MakeInstructionDescriptor(25, SpvOpAccessChain, 0), 25, 100, {0});
  134. ASSERT_TRUE(good_extract_1.IsApplicable(context.get(), fact_manager));
  135. ASSERT_FALSE(bad_extract_1.IsApplicable(context.get(), fact_manager));
  136. good_extract_1.Apply(context.get(), &fact_manager);
  137. auto replacement_1 = TransformationReplaceIdWithSynonym(
  138. MakeIdUseDescriptor(12, instruction_descriptor_1, 1), 102);
  139. ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
  140. replacement_1.Apply(context.get(), &fact_manager);
  141. ASSERT_TRUE(IsValid(env, context.get()));
  142. // Replace %13 with %100[1] in 'OpStore %15 %13'
  143. auto instruction_descriptor_2 = MakeInstructionDescriptor(100, SpvOpStore, 0);
  144. auto good_extract_2 =
  145. TransformationCompositeExtract(instruction_descriptor_2, 103, 100, {1});
  146. // No bad example provided here.
  147. ASSERT_TRUE(good_extract_2.IsApplicable(context.get(), fact_manager));
  148. good_extract_2.Apply(context.get(), &fact_manager);
  149. auto replacement_2 = TransformationReplaceIdWithSynonym(
  150. MakeIdUseDescriptor(13, instruction_descriptor_2, 1), 103);
  151. ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
  152. replacement_2.Apply(context.get(), &fact_manager);
  153. ASSERT_TRUE(IsValid(env, context.get()));
  154. // Replace %22 with %100[2] in '%23 = OpConvertSToF %16 %22'
  155. auto instruction_descriptor_3 =
  156. MakeInstructionDescriptor(23, SpvOpConvertSToF, 0);
  157. auto good_extract_3 =
  158. TransformationCompositeExtract(instruction_descriptor_3, 104, 100, {2});
  159. ASSERT_TRUE(good_extract_3.IsApplicable(context.get(), fact_manager));
  160. good_extract_3.Apply(context.get(), &fact_manager);
  161. auto replacement_3 = TransformationReplaceIdWithSynonym(
  162. MakeIdUseDescriptor(22, instruction_descriptor_3, 0), 104);
  163. // Bad: wrong input operand index
  164. auto bad_replacement_3 = TransformationReplaceIdWithSynonym(
  165. MakeIdUseDescriptor(22, instruction_descriptor_3, 1), 104);
  166. ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager));
  167. ASSERT_FALSE(bad_replacement_3.IsApplicable(context.get(), fact_manager));
  168. replacement_3.Apply(context.get(), &fact_manager);
  169. ASSERT_TRUE(IsValid(env, context.get()));
  170. // Replace %28 with %101[0] in 'OpStore %33 %28'
  171. auto instruction_descriptor_4 = MakeInstructionDescriptor(33, SpvOpStore, 0);
  172. auto good_extract_4 =
  173. TransformationCompositeExtract(instruction_descriptor_4, 105, 101, {0});
  174. // Bad: instruction descriptor does not identify an appropriate instruction
  175. auto bad_extract_4 = TransformationCompositeExtract(
  176. MakeInstructionDescriptor(33, SpvOpCopyObject, 0), 105, 101, {0});
  177. ASSERT_TRUE(good_extract_4.IsApplicable(context.get(), fact_manager));
  178. ASSERT_FALSE(bad_extract_4.IsApplicable(context.get(), fact_manager));
  179. good_extract_4.Apply(context.get(), &fact_manager);
  180. auto replacement_4 = TransformationReplaceIdWithSynonym(
  181. MakeIdUseDescriptor(28, instruction_descriptor_4, 1), 105);
  182. ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager));
  183. replacement_4.Apply(context.get(), &fact_manager);
  184. ASSERT_TRUE(IsValid(env, context.get()));
  185. // Replace %23 with %101[1] in '%50 = OpCopyObject %16 %23'
  186. auto instruction_descriptor_5 =
  187. MakeInstructionDescriptor(50, SpvOpCopyObject, 0);
  188. auto good_extract_5 =
  189. TransformationCompositeExtract(instruction_descriptor_5, 106, 101, {1});
  190. ASSERT_TRUE(good_extract_5.IsApplicable(context.get(), fact_manager));
  191. good_extract_5.Apply(context.get(), &fact_manager);
  192. auto replacement_5 = TransformationReplaceIdWithSynonym(
  193. MakeIdUseDescriptor(23, instruction_descriptor_5, 0), 106);
  194. // Bad: wrong synonym fact being used
  195. auto bad_replacement_5 = TransformationReplaceIdWithSynonym(
  196. MakeIdUseDescriptor(23, instruction_descriptor_5, 0), 105);
  197. ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager));
  198. ASSERT_FALSE(bad_replacement_5.IsApplicable(context.get(), fact_manager));
  199. replacement_5.Apply(context.get(), &fact_manager);
  200. ASSERT_TRUE(IsValid(env, context.get()));
  201. // Replace %32 with %101[2] in 'OpStore %33 %32'
  202. auto instruction_descriptor_6 = MakeInstructionDescriptor(33, SpvOpStore, 1);
  203. auto good_extract_6 =
  204. TransformationCompositeExtract(instruction_descriptor_6, 107, 101, {2});
  205. // Bad: id 1001 does not exist
  206. auto bad_extract_6 =
  207. TransformationCompositeExtract(instruction_descriptor_6, 107, 1001, {2});
  208. ASSERT_TRUE(good_extract_6.IsApplicable(context.get(), fact_manager));
  209. ASSERT_FALSE(bad_extract_6.IsApplicable(context.get(), fact_manager));
  210. good_extract_6.Apply(context.get(), &fact_manager);
  211. auto replacement_6 = TransformationReplaceIdWithSynonym(
  212. MakeIdUseDescriptor(32, instruction_descriptor_6, 1), 107);
  213. ASSERT_TRUE(replacement_6.IsApplicable(context.get(), fact_manager));
  214. replacement_6.Apply(context.get(), &fact_manager);
  215. ASSERT_TRUE(IsValid(env, context.get()));
  216. // Replace %23 with %101[3] in '%51 = OpCopyObject %16 %23'
  217. auto instruction_descriptor_7 =
  218. MakeInstructionDescriptor(51, SpvOpCopyObject, 0);
  219. auto good_extract_7 =
  220. TransformationCompositeExtract(instruction_descriptor_7, 108, 101, {3});
  221. ASSERT_TRUE(good_extract_7.IsApplicable(context.get(), fact_manager));
  222. good_extract_7.Apply(context.get(), &fact_manager);
  223. auto replacement_7 = TransformationReplaceIdWithSynonym(
  224. MakeIdUseDescriptor(23, instruction_descriptor_7, 0), 108);
  225. // Bad: use id 0 is invalid
  226. auto bad_replacement_7 = TransformationReplaceIdWithSynonym(
  227. MakeIdUseDescriptor(0, instruction_descriptor_7, 0), 108);
  228. ASSERT_TRUE(replacement_7.IsApplicable(context.get(), fact_manager));
  229. ASSERT_FALSE(bad_replacement_7.IsApplicable(context.get(), fact_manager));
  230. replacement_7.Apply(context.get(), &fact_manager);
  231. ASSERT_TRUE(IsValid(env, context.get()));
  232. const std::string after_transformation = R"(
  233. OpCapability Shader
  234. %1 = OpExtInstImport "GLSL.std.450"
  235. OpMemoryModel Logical GLSL450
  236. OpEntryPoint Fragment %4 "main"
  237. OpExecutionMode %4 OriginUpperLeft
  238. OpSource ESSL 310
  239. OpName %4 "main"
  240. OpName %11 "A"
  241. OpName %20 "B"
  242. OpName %31 "g"
  243. OpName %35 "h"
  244. OpDecorate %11 RelaxedPrecision
  245. OpDecorate %22 RelaxedPrecision
  246. OpDecorate %27 RelaxedPrecision
  247. OpDecorate %35 RelaxedPrecision
  248. OpDecorate %36 RelaxedPrecision
  249. OpDecorate %40 RelaxedPrecision
  250. OpDecorate %41 RelaxedPrecision
  251. %2 = OpTypeVoid
  252. %3 = OpTypeFunction %2
  253. %6 = OpTypeInt 32 1
  254. %7 = OpTypeInt 32 0
  255. %8 = OpConstant %7 3
  256. %9 = OpTypeArray %6 %8
  257. %10 = OpTypePointer Function %9
  258. %12 = OpConstant %6 0
  259. %13 = OpConstant %6 3
  260. %14 = OpTypePointer Function %6
  261. %16 = OpTypeFloat 32
  262. %17 = OpConstant %7 4
  263. %18 = OpTypeArray %16 %17
  264. %19 = OpTypePointer Function %18
  265. %24 = OpTypePointer Function %16
  266. %28 = OpConstant %16 42
  267. %30 = OpConstant %6 2
  268. %34 = OpConstant %6 1
  269. %38 = OpConstant %6 42
  270. %4 = OpFunction %2 None %3
  271. %5 = OpLabel
  272. %11 = OpVariable %10 Function
  273. %20 = OpVariable %19 Function
  274. %31 = OpVariable %24 Function
  275. %35 = OpVariable %14 Function
  276. %15 = OpAccessChain %14 %11 %12
  277. %21 = OpAccessChain %14 %11 %12
  278. %22 = OpLoad %6 %21
  279. %100 = OpCompositeConstruct %9 %12 %13 %22
  280. %103 = OpCompositeExtract %6 %100 1
  281. OpStore %15 %103
  282. %104 = OpCompositeExtract %6 %100 2
  283. %23 = OpConvertSToF %16 %104
  284. %102 = OpCompositeExtract %6 %100 0
  285. %25 = OpAccessChain %24 %20 %102
  286. OpStore %25 %23
  287. %26 = OpAccessChain %14 %11 %12
  288. %27 = OpLoad %6 %26
  289. %29 = OpAccessChain %24 %20 %27
  290. OpStore %29 %28
  291. %32 = OpLoad %16 %31
  292. %101 = OpCompositeConstruct %18 %28 %23 %32 %23
  293. %106 = OpCompositeExtract %16 %101 1
  294. %50 = OpCopyObject %16 %106
  295. %108 = OpCompositeExtract %16 %101 3
  296. %51 = OpCopyObject %16 %108
  297. %33 = OpAccessChain %24 %20 %30
  298. %105 = OpCompositeExtract %16 %101 0
  299. OpStore %33 %105
  300. %107 = OpCompositeExtract %16 %101 2
  301. OpStore %33 %107
  302. %36 = OpLoad %6 %35
  303. %37 = OpAccessChain %14 %11 %34
  304. OpStore %37 %36
  305. %39 = OpAccessChain %14 %11 %12
  306. %40 = OpLoad %6 %39
  307. %41 = OpIAdd %6 %38 %40
  308. %42 = OpAccessChain %14 %11 %30
  309. OpStore %42 %41
  310. OpReturn
  311. OpFunctionEnd
  312. )";
  313. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  314. }
  315. TEST(DataSynonymTransformationTest, MatrixCompositeSynonyms) {
  316. std::string shader = R"(
  317. OpCapability Shader
  318. %1 = OpExtInstImport "GLSL.std.450"
  319. OpMemoryModel Logical GLSL450
  320. OpEntryPoint Fragment %4 "main"
  321. OpExecutionMode %4 OriginUpperLeft
  322. OpSource ESSL 310
  323. OpName %4 "main"
  324. OpName %10 "m"
  325. %2 = OpTypeVoid
  326. %3 = OpTypeFunction %2
  327. %6 = OpTypeFloat 32
  328. %7 = OpTypeVector %6 4
  329. %50 = OpUndef %7
  330. %8 = OpTypeMatrix %7 3
  331. %9 = OpTypePointer Function %8
  332. %11 = OpTypeInt 32 1
  333. %12 = OpConstant %11 0
  334. %13 = OpConstant %6 1
  335. %14 = OpConstantComposite %7 %13 %13 %13 %13
  336. %15 = OpTypePointer Function %7
  337. %17 = OpConstant %11 1
  338. %18 = OpConstant %6 2
  339. %19 = OpConstantComposite %7 %18 %18 %18 %18
  340. %21 = OpConstant %11 2
  341. %4 = OpFunction %2 None %3
  342. %5 = OpLabel
  343. %10 = OpVariable %9 Function
  344. %16 = OpAccessChain %15 %10 %12
  345. OpStore %16 %14
  346. %20 = OpAccessChain %15 %10 %17
  347. OpStore %20 %19
  348. %22 = OpAccessChain %15 %10 %12
  349. %23 = OpLoad %7 %22
  350. %24 = OpAccessChain %15 %10 %17
  351. %25 = OpLoad %7 %24
  352. %100 = OpCompositeConstruct %8 %23 %25 %50
  353. %26 = OpFAdd %7 %23 %25
  354. %27 = OpAccessChain %15 %10 %21
  355. OpStore %27 %26
  356. OpReturn
  357. OpFunctionEnd
  358. )";
  359. const auto env = SPV_ENV_UNIVERSAL_1_3;
  360. const auto consumer = nullptr;
  361. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  362. ASSERT_TRUE(IsValid(env, context.get()));
  363. FactManager fact_manager;
  364. fact_manager.AddFact(MakeSynonymFact(23, {}, 100, {0}), context.get());
  365. fact_manager.AddFact(MakeSynonymFact(25, {}, 100, {1}), context.get());
  366. fact_manager.AddFact(MakeSynonymFact(50, {}, 100, {2}), context.get());
  367. // Replace %23 with %100[0] in '%26 = OpFAdd %7 %23 %25'
  368. auto instruction_descriptor_1 = MakeInstructionDescriptor(26, SpvOpFAdd, 0);
  369. auto extract_1 =
  370. TransformationCompositeExtract(instruction_descriptor_1, 101, 100, {0});
  371. ASSERT_TRUE(extract_1.IsApplicable(context.get(), fact_manager));
  372. extract_1.Apply(context.get(), &fact_manager);
  373. auto replacement_1 = TransformationReplaceIdWithSynonym(
  374. MakeIdUseDescriptor(23, instruction_descriptor_1, 0), 101);
  375. ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
  376. replacement_1.Apply(context.get(), &fact_manager);
  377. ASSERT_TRUE(IsValid(env, context.get()));
  378. // Replace %25 with %100[1] in '%26 = OpFAdd %7 %23 %25'
  379. auto instruction_descriptor_2 = MakeInstructionDescriptor(26, SpvOpFAdd, 0);
  380. auto extract_2 =
  381. TransformationCompositeExtract(instruction_descriptor_2, 102, 100, {1});
  382. ASSERT_TRUE(extract_2.IsApplicable(context.get(), fact_manager));
  383. extract_2.Apply(context.get(), &fact_manager);
  384. auto replacement_2 = TransformationReplaceIdWithSynonym(
  385. MakeIdUseDescriptor(25, instruction_descriptor_2, 1), 102);
  386. ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
  387. replacement_2.Apply(context.get(), &fact_manager);
  388. ASSERT_TRUE(IsValid(env, context.get()));
  389. const std::string after_transformation = R"(
  390. OpCapability Shader
  391. %1 = OpExtInstImport "GLSL.std.450"
  392. OpMemoryModel Logical GLSL450
  393. OpEntryPoint Fragment %4 "main"
  394. OpExecutionMode %4 OriginUpperLeft
  395. OpSource ESSL 310
  396. OpName %4 "main"
  397. OpName %10 "m"
  398. %2 = OpTypeVoid
  399. %3 = OpTypeFunction %2
  400. %6 = OpTypeFloat 32
  401. %7 = OpTypeVector %6 4
  402. %50 = OpUndef %7
  403. %8 = OpTypeMatrix %7 3
  404. %9 = OpTypePointer Function %8
  405. %11 = OpTypeInt 32 1
  406. %12 = OpConstant %11 0
  407. %13 = OpConstant %6 1
  408. %14 = OpConstantComposite %7 %13 %13 %13 %13
  409. %15 = OpTypePointer Function %7
  410. %17 = OpConstant %11 1
  411. %18 = OpConstant %6 2
  412. %19 = OpConstantComposite %7 %18 %18 %18 %18
  413. %21 = OpConstant %11 2
  414. %4 = OpFunction %2 None %3
  415. %5 = OpLabel
  416. %10 = OpVariable %9 Function
  417. %16 = OpAccessChain %15 %10 %12
  418. OpStore %16 %14
  419. %20 = OpAccessChain %15 %10 %17
  420. OpStore %20 %19
  421. %22 = OpAccessChain %15 %10 %12
  422. %23 = OpLoad %7 %22
  423. %24 = OpAccessChain %15 %10 %17
  424. %25 = OpLoad %7 %24
  425. %100 = OpCompositeConstruct %8 %23 %25 %50
  426. %101 = OpCompositeExtract %7 %100 0
  427. %102 = OpCompositeExtract %7 %100 1
  428. %26 = OpFAdd %7 %101 %102
  429. %27 = OpAccessChain %15 %10 %21
  430. OpStore %27 %26
  431. OpReturn
  432. OpFunctionEnd
  433. )";
  434. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  435. }
  436. TEST(DataSynonymTransformationTest, StructCompositeSynonyms) {
  437. std::string shader = R"(
  438. OpCapability Shader
  439. %1 = OpExtInstImport "GLSL.std.450"
  440. OpMemoryModel Logical GLSL450
  441. OpEntryPoint Fragment %4 "main"
  442. OpExecutionMode %4 OriginUpperLeft
  443. OpSource ESSL 310
  444. OpName %4 "main"
  445. OpName %9 "Inner"
  446. OpMemberName %9 0 "a"
  447. OpMemberName %9 1 "b"
  448. OpName %11 "i1"
  449. OpName %17 "i2"
  450. OpName %31 "Point"
  451. OpMemberName %31 0 "x"
  452. OpMemberName %31 1 "y"
  453. OpMemberName %31 2 "z"
  454. OpName %32 "Outer"
  455. OpMemberName %32 0 "c"
  456. OpMemberName %32 1 "d"
  457. OpName %34 "o1"
  458. %2 = OpTypeVoid
  459. %3 = OpTypeFunction %2
  460. %6 = OpTypeInt 32 1
  461. %7 = OpTypeFloat 32
  462. %8 = OpTypeVector %7 2
  463. %9 = OpTypeStruct %6 %8
  464. %10 = OpTypePointer Function %9
  465. %12 = OpConstant %6 1
  466. %13 = OpConstant %7 2
  467. %14 = OpConstant %7 3
  468. %15 = OpConstantComposite %8 %13 %14
  469. %16 = OpConstantComposite %9 %12 %15
  470. %18 = OpConstant %6 0
  471. %19 = OpTypePointer Function %6
  472. %24 = OpTypePointer Function %8
  473. %27 = OpConstant %7 4
  474. %31 = OpTypeStruct %7 %7 %7
  475. %32 = OpTypeStruct %9 %31
  476. %33 = OpTypePointer Function %32
  477. %36 = OpConstant %7 10
  478. %37 = OpTypeInt 32 0
  479. %38 = OpConstant %37 0
  480. %39 = OpTypePointer Function %7
  481. %42 = OpConstant %37 1
  482. %4 = OpFunction %2 None %3
  483. %5 = OpLabel
  484. %11 = OpVariable %10 Function
  485. %17 = OpVariable %10 Function
  486. %34 = OpVariable %33 Function
  487. %101 = OpCompositeConstruct %31 %27 %36 %27
  488. OpStore %11 %16
  489. %20 = OpAccessChain %19 %11 %18
  490. %21 = OpLoad %6 %20
  491. %22 = OpIAdd %6 %21 %12
  492. %102 = OpCompositeConstruct %9 %22 %15
  493. %23 = OpAccessChain %19 %17 %18
  494. OpStore %23 %22
  495. %25 = OpAccessChain %24 %17 %12
  496. %26 = OpLoad %8 %25
  497. %28 = OpCompositeConstruct %8 %27 %27
  498. %29 = OpFAdd %8 %26 %28
  499. %30 = OpAccessChain %24 %17 %12
  500. OpStore %30 %29
  501. %35 = OpLoad %9 %11
  502. %40 = OpAccessChain %39 %11 %12 %38
  503. %41 = OpLoad %7 %40
  504. %43 = OpAccessChain %39 %11 %12 %42
  505. %44 = OpLoad %7 %43
  506. %45 = OpCompositeConstruct %31 %36 %41 %44
  507. %100 = OpCompositeConstruct %32 %16 %45
  508. %46 = OpCompositeConstruct %32 %35 %45
  509. OpStore %34 %46
  510. OpReturn
  511. OpFunctionEnd
  512. )";
  513. const auto env = SPV_ENV_UNIVERSAL_1_3;
  514. const auto consumer = nullptr;
  515. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  516. ASSERT_TRUE(IsValid(env, context.get()));
  517. FactManager fact_manager;
  518. fact_manager.AddFact(MakeSynonymFact(16, {}, 100, {0}), context.get());
  519. fact_manager.AddFact(MakeSynonymFact(45, {}, 100, {1}), context.get());
  520. fact_manager.AddFact(MakeSynonymFact(27, {}, 101, {0}), context.get());
  521. fact_manager.AddFact(MakeSynonymFact(36, {}, 101, {1}), context.get());
  522. fact_manager.AddFact(MakeSynonymFact(27, {}, 101, {2}), context.get());
  523. fact_manager.AddFact(MakeSynonymFact(22, {}, 102, {0}), context.get());
  524. fact_manager.AddFact(MakeSynonymFact(15, {}, 102, {1}), context.get());
  525. // Replace %45 with %100[1] in '%46 = OpCompositeConstruct %32 %35 %45'
  526. auto instruction_descriptor_1 =
  527. MakeInstructionDescriptor(46, SpvOpCompositeConstruct, 0);
  528. auto extract_1 =
  529. TransformationCompositeExtract(instruction_descriptor_1, 201, 100, {1});
  530. ASSERT_TRUE(extract_1.IsApplicable(context.get(), fact_manager));
  531. extract_1.Apply(context.get(), &fact_manager);
  532. auto replacement_1 = TransformationReplaceIdWithSynonym(
  533. MakeIdUseDescriptor(45, instruction_descriptor_1, 1), 201);
  534. ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
  535. replacement_1.Apply(context.get(), &fact_manager);
  536. ASSERT_TRUE(IsValid(env, context.get()));
  537. // Replace second occurrence of %27 with %101[0] in '%28 =
  538. // OpCompositeConstruct %8 %27 %27'
  539. auto instruction_descriptor_2 =
  540. MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0);
  541. auto extract_2 =
  542. TransformationCompositeExtract(instruction_descriptor_2, 202, 101, {0});
  543. ASSERT_TRUE(extract_2.IsApplicable(context.get(), fact_manager));
  544. extract_2.Apply(context.get(), &fact_manager);
  545. auto replacement_2 = TransformationReplaceIdWithSynonym(
  546. MakeIdUseDescriptor(27, instruction_descriptor_2, 1), 202);
  547. ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
  548. replacement_2.Apply(context.get(), &fact_manager);
  549. ASSERT_TRUE(IsValid(env, context.get()));
  550. // Replace %36 with %101[1] in '%45 = OpCompositeConstruct %31 %36 %41 %44'
  551. auto instruction_descriptor_3 =
  552. MakeInstructionDescriptor(45, SpvOpCompositeConstruct, 0);
  553. auto extract_3 =
  554. TransformationCompositeExtract(instruction_descriptor_3, 203, 101, {1});
  555. ASSERT_TRUE(extract_3.IsApplicable(context.get(), fact_manager));
  556. extract_3.Apply(context.get(), &fact_manager);
  557. auto replacement_3 = TransformationReplaceIdWithSynonym(
  558. MakeIdUseDescriptor(36, instruction_descriptor_3, 0), 203);
  559. ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager));
  560. replacement_3.Apply(context.get(), &fact_manager);
  561. ASSERT_TRUE(IsValid(env, context.get()));
  562. // Replace first occurrence of %27 with %101[2] in '%28 = OpCompositeConstruct
  563. // %8 %27 %27'
  564. auto instruction_descriptor_4 =
  565. MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0);
  566. auto extract_4 =
  567. TransformationCompositeExtract(instruction_descriptor_4, 204, 101, {2});
  568. ASSERT_TRUE(extract_4.IsApplicable(context.get(), fact_manager));
  569. extract_4.Apply(context.get(), &fact_manager);
  570. auto replacement_4 = TransformationReplaceIdWithSynonym(
  571. MakeIdUseDescriptor(27, instruction_descriptor_4, 0), 204);
  572. ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager));
  573. replacement_4.Apply(context.get(), &fact_manager);
  574. ASSERT_TRUE(IsValid(env, context.get()));
  575. // Replace %22 with %102[0] in 'OpStore %23 %22'
  576. auto instruction_descriptor_5 = MakeInstructionDescriptor(23, SpvOpStore, 0);
  577. auto extract_5 =
  578. TransformationCompositeExtract(instruction_descriptor_5, 205, 102, {0});
  579. ASSERT_TRUE(extract_5.IsApplicable(context.get(), fact_manager));
  580. extract_5.Apply(context.get(), &fact_manager);
  581. auto replacement_5 = TransformationReplaceIdWithSynonym(
  582. MakeIdUseDescriptor(22, instruction_descriptor_5, 1), 205);
  583. ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager));
  584. replacement_5.Apply(context.get(), &fact_manager);
  585. ASSERT_TRUE(IsValid(env, context.get()));
  586. const std::string after_transformation = R"(
  587. OpCapability Shader
  588. %1 = OpExtInstImport "GLSL.std.450"
  589. OpMemoryModel Logical GLSL450
  590. OpEntryPoint Fragment %4 "main"
  591. OpExecutionMode %4 OriginUpperLeft
  592. OpSource ESSL 310
  593. OpName %4 "main"
  594. OpName %9 "Inner"
  595. OpMemberName %9 0 "a"
  596. OpMemberName %9 1 "b"
  597. OpName %11 "i1"
  598. OpName %17 "i2"
  599. OpName %31 "Point"
  600. OpMemberName %31 0 "x"
  601. OpMemberName %31 1 "y"
  602. OpMemberName %31 2 "z"
  603. OpName %32 "Outer"
  604. OpMemberName %32 0 "c"
  605. OpMemberName %32 1 "d"
  606. OpName %34 "o1"
  607. %2 = OpTypeVoid
  608. %3 = OpTypeFunction %2
  609. %6 = OpTypeInt 32 1
  610. %7 = OpTypeFloat 32
  611. %8 = OpTypeVector %7 2
  612. %9 = OpTypeStruct %6 %8
  613. %10 = OpTypePointer Function %9
  614. %12 = OpConstant %6 1
  615. %13 = OpConstant %7 2
  616. %14 = OpConstant %7 3
  617. %15 = OpConstantComposite %8 %13 %14
  618. %16 = OpConstantComposite %9 %12 %15
  619. %18 = OpConstant %6 0
  620. %19 = OpTypePointer Function %6
  621. %24 = OpTypePointer Function %8
  622. %27 = OpConstant %7 4
  623. %31 = OpTypeStruct %7 %7 %7
  624. %32 = OpTypeStruct %9 %31
  625. %33 = OpTypePointer Function %32
  626. %36 = OpConstant %7 10
  627. %37 = OpTypeInt 32 0
  628. %38 = OpConstant %37 0
  629. %39 = OpTypePointer Function %7
  630. %42 = OpConstant %37 1
  631. %4 = OpFunction %2 None %3
  632. %5 = OpLabel
  633. %11 = OpVariable %10 Function
  634. %17 = OpVariable %10 Function
  635. %34 = OpVariable %33 Function
  636. %101 = OpCompositeConstruct %31 %27 %36 %27
  637. OpStore %11 %16
  638. %20 = OpAccessChain %19 %11 %18
  639. %21 = OpLoad %6 %20
  640. %22 = OpIAdd %6 %21 %12
  641. %102 = OpCompositeConstruct %9 %22 %15
  642. %23 = OpAccessChain %19 %17 %18
  643. %205 = OpCompositeExtract %6 %102 0
  644. OpStore %23 %205
  645. %25 = OpAccessChain %24 %17 %12
  646. %26 = OpLoad %8 %25
  647. %202 = OpCompositeExtract %7 %101 0
  648. %204 = OpCompositeExtract %7 %101 2
  649. %28 = OpCompositeConstruct %8 %204 %202
  650. %29 = OpFAdd %8 %26 %28
  651. %30 = OpAccessChain %24 %17 %12
  652. OpStore %30 %29
  653. %35 = OpLoad %9 %11
  654. %40 = OpAccessChain %39 %11 %12 %38
  655. %41 = OpLoad %7 %40
  656. %43 = OpAccessChain %39 %11 %12 %42
  657. %44 = OpLoad %7 %43
  658. %203 = OpCompositeExtract %7 %101 1
  659. %45 = OpCompositeConstruct %31 %203 %41 %44
  660. %100 = OpCompositeConstruct %32 %16 %45
  661. %201 = OpCompositeExtract %31 %100 1
  662. %46 = OpCompositeConstruct %32 %35 %201
  663. OpStore %34 %46
  664. OpReturn
  665. OpFunctionEnd
  666. )";
  667. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  668. }
  669. TEST(DataSynonymTransformationTest, VectorCompositeSynonyms) {
  670. std::string shader = R"(
  671. OpCapability Shader
  672. %1 = OpExtInstImport "GLSL.std.450"
  673. OpMemoryModel Logical GLSL450
  674. OpEntryPoint Fragment %4 "main"
  675. OpExecutionMode %4 OriginUpperLeft
  676. OpSource ESSL 310
  677. OpName %4 "main"
  678. OpName %8 "f"
  679. OpName %12 "v2"
  680. OpName %18 "v3"
  681. OpName %23 "v4"
  682. OpName %32 "b"
  683. OpName %36 "bv2"
  684. OpName %41 "bv3"
  685. OpName %50 "bv4"
  686. %2 = OpTypeVoid
  687. %3 = OpTypeFunction %2
  688. %6 = OpTypeFloat 32
  689. %7 = OpTypePointer Function %6
  690. %9 = OpConstant %6 42
  691. %10 = OpTypeVector %6 2
  692. %11 = OpTypePointer Function %10
  693. %16 = OpTypeVector %6 3
  694. %17 = OpTypePointer Function %16
  695. %21 = OpTypeVector %6 4
  696. %22 = OpTypePointer Function %21
  697. %30 = OpTypeBool
  698. %31 = OpTypePointer Function %30
  699. %33 = OpConstantFalse %30
  700. %34 = OpTypeVector %30 2
  701. %35 = OpTypePointer Function %34
  702. %37 = OpConstantTrue %30
  703. %38 = OpConstantComposite %34 %37 %37
  704. %39 = OpTypeVector %30 3
  705. %40 = OpTypePointer Function %39
  706. %48 = OpTypeVector %30 4
  707. %49 = OpTypePointer Function %48
  708. %51 = OpTypeInt 32 0
  709. %52 = OpConstant %51 2
  710. %55 = OpConstant %6 0
  711. %57 = OpConstant %51 1
  712. %4 = OpFunction %2 None %3
  713. %5 = OpLabel
  714. %8 = OpVariable %7 Function
  715. %12 = OpVariable %11 Function
  716. %18 = OpVariable %17 Function
  717. %23 = OpVariable %22 Function
  718. %32 = OpVariable %31 Function
  719. %36 = OpVariable %35 Function
  720. %41 = OpVariable %40 Function
  721. %50 = OpVariable %49 Function
  722. OpStore %8 %9
  723. %13 = OpLoad %6 %8
  724. %14 = OpLoad %6 %8
  725. %15 = OpCompositeConstruct %10 %13 %14
  726. OpStore %12 %15
  727. %19 = OpLoad %10 %12
  728. %20 = OpVectorShuffle %16 %19 %19 0 0 1
  729. OpStore %18 %20
  730. %24 = OpLoad %16 %18
  731. %25 = OpLoad %6 %8
  732. %26 = OpCompositeExtract %6 %24 0
  733. %27 = OpCompositeExtract %6 %24 1
  734. %28 = OpCompositeExtract %6 %24 2
  735. %29 = OpCompositeConstruct %21 %26 %27 %28 %25
  736. OpStore %23 %29
  737. OpStore %32 %33
  738. OpStore %36 %38
  739. %42 = OpLoad %30 %32
  740. %43 = OpLoad %34 %36
  741. %44 = OpVectorShuffle %34 %43 %43 0 0
  742. %45 = OpCompositeExtract %30 %44 0
  743. %46 = OpCompositeExtract %30 %44 1
  744. %47 = OpCompositeConstruct %39 %42 %45 %46
  745. OpStore %41 %47
  746. %53 = OpAccessChain %7 %23 %52
  747. %54 = OpLoad %6 %53
  748. %100 = OpCompositeConstruct %21 %20 %54
  749. %101 = OpCompositeConstruct %21 %15 %19
  750. %102 = OpCompositeConstruct %16 %27 %15
  751. %103 = OpCompositeConstruct %48 %33 %47
  752. %104 = OpCompositeConstruct %34 %42 %45
  753. %105 = OpCompositeConstruct %39 %38 %46
  754. %86 = OpCopyObject %30 %33
  755. %56 = OpFOrdNotEqual %30 %54 %55
  756. %80 = OpCopyObject %16 %20
  757. %58 = OpAccessChain %7 %18 %57
  758. %59 = OpLoad %6 %58
  759. %60 = OpFOrdNotEqual %30 %59 %55
  760. %61 = OpLoad %34 %36
  761. %62 = OpLogicalAnd %30 %45 %46
  762. %63 = OpLogicalOr %30 %45 %46
  763. %64 = OpCompositeConstruct %48 %56 %60 %62 %63
  764. OpStore %12 %15
  765. %81 = OpVectorShuffle %16 %19 %19 0 0 1
  766. %82 = OpCompositeConstruct %21 %26 %27 %28 %25
  767. %83 = OpCopyObject %10 %15
  768. %84 = OpCopyObject %39 %47
  769. OpStore %50 %64
  770. %85 = OpCopyObject %30 %42
  771. OpStore %36 %38
  772. OpReturn
  773. OpFunctionEnd
  774. )";
  775. const auto env = SPV_ENV_UNIVERSAL_1_3;
  776. const auto consumer = nullptr;
  777. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  778. ASSERT_TRUE(IsValid(env, context.get()));
  779. FactManager fact_manager;
  780. fact_manager.AddFact(MakeSynonymFact(20, {0}, 100, {0}), context.get());
  781. fact_manager.AddFact(MakeSynonymFact(20, {1}, 100, {1}), context.get());
  782. fact_manager.AddFact(MakeSynonymFact(20, {2}, 100, {2}), context.get());
  783. fact_manager.AddFact(MakeSynonymFact(54, {}, 100, {3}), context.get());
  784. fact_manager.AddFact(MakeSynonymFact(15, {0}, 101, {0}), context.get());
  785. fact_manager.AddFact(MakeSynonymFact(15, {1}, 101, {1}), context.get());
  786. fact_manager.AddFact(MakeSynonymFact(19, {0}, 101, {2}), context.get());
  787. fact_manager.AddFact(MakeSynonymFact(19, {1}, 101, {3}), context.get());
  788. fact_manager.AddFact(MakeSynonymFact(27, {}, 102, {0}), context.get());
  789. fact_manager.AddFact(MakeSynonymFact(15, {0}, 102, {1}), context.get());
  790. fact_manager.AddFact(MakeSynonymFact(15, {1}, 102, {2}), context.get());
  791. fact_manager.AddFact(MakeSynonymFact(33, {}, 103, {0}), context.get());
  792. fact_manager.AddFact(MakeSynonymFact(47, {0}, 103, {1}), context.get());
  793. fact_manager.AddFact(MakeSynonymFact(47, {1}, 103, {2}), context.get());
  794. fact_manager.AddFact(MakeSynonymFact(47, {2}, 103, {3}), context.get());
  795. fact_manager.AddFact(MakeSynonymFact(42, {}, 104, {0}), context.get());
  796. fact_manager.AddFact(MakeSynonymFact(45, {}, 104, {1}), context.get());
  797. fact_manager.AddFact(MakeSynonymFact(38, {0}, 105, {0}), context.get());
  798. fact_manager.AddFact(MakeSynonymFact(38, {1}, 105, {1}), context.get());
  799. fact_manager.AddFact(MakeSynonymFact(46, {}, 105, {2}), context.get());
  800. // Replace %20 with %100[0:2] in '%80 = OpCopyObject %16 %20'
  801. auto instruction_descriptor_1 =
  802. MakeInstructionDescriptor(80, SpvOpCopyObject, 0);
  803. auto shuffle_1 = TransformationVectorShuffle(instruction_descriptor_1, 200,
  804. 100, 100, {0, 1, 2});
  805. ASSERT_TRUE(shuffle_1.IsApplicable(context.get(), fact_manager));
  806. shuffle_1.Apply(context.get(), &fact_manager);
  807. auto replacement_1 = TransformationReplaceIdWithSynonym(
  808. MakeIdUseDescriptor(20, instruction_descriptor_1, 0), 200);
  809. ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
  810. replacement_1.Apply(context.get(), &fact_manager);
  811. ASSERT_TRUE(IsValid(env, context.get()));
  812. // Replace %54 with %100[3] in '%56 = OpFOrdNotEqual %30 %54 %55'
  813. auto instruction_descriptor_2 =
  814. MakeInstructionDescriptor(56, SpvOpFOrdNotEqual, 0);
  815. auto extract_2 =
  816. TransformationCompositeExtract(instruction_descriptor_2, 201, 100, {3});
  817. ASSERT_TRUE(extract_2.IsApplicable(context.get(), fact_manager));
  818. extract_2.Apply(context.get(), &fact_manager);
  819. auto replacement_2 = TransformationReplaceIdWithSynonym(
  820. MakeIdUseDescriptor(54, instruction_descriptor_2, 0), 201);
  821. ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
  822. replacement_2.Apply(context.get(), &fact_manager);
  823. ASSERT_TRUE(IsValid(env, context.get()));
  824. // Replace %15 with %101[0:1] in 'OpStore %12 %15'
  825. auto instruction_descriptor_3 = MakeInstructionDescriptor(64, SpvOpStore, 0);
  826. auto shuffle_3 = TransformationVectorShuffle(instruction_descriptor_3, 202,
  827. 101, 101, {0, 1});
  828. ASSERT_TRUE(shuffle_3.IsApplicable(context.get(), fact_manager));
  829. shuffle_3.Apply(context.get(), &fact_manager);
  830. auto replacement_3 = TransformationReplaceIdWithSynonym(
  831. MakeIdUseDescriptor(15, instruction_descriptor_3, 1), 202);
  832. ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager));
  833. replacement_3.Apply(context.get(), &fact_manager);
  834. ASSERT_TRUE(IsValid(env, context.get()));
  835. // Replace %19 with %101[2:3] in '%81 = OpVectorShuffle %16 %19 %19 0 0 1'
  836. auto instruction_descriptor_4 =
  837. MakeInstructionDescriptor(81, SpvOpVectorShuffle, 0);
  838. auto shuffle_4 = TransformationVectorShuffle(instruction_descriptor_4, 203,
  839. 101, 101, {2, 3});
  840. ASSERT_TRUE(shuffle_4.IsApplicable(context.get(), fact_manager));
  841. shuffle_4.Apply(context.get(), &fact_manager);
  842. auto replacement_4 = TransformationReplaceIdWithSynonym(
  843. MakeIdUseDescriptor(19, instruction_descriptor_4, 0), 203);
  844. ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager));
  845. replacement_4.Apply(context.get(), &fact_manager);
  846. ASSERT_TRUE(IsValid(env, context.get()));
  847. // Replace %27 with %102[0] in '%82 = OpCompositeConstruct %21 %26 %27 %28
  848. // %25'
  849. auto instruction_descriptor_5 =
  850. MakeInstructionDescriptor(82, SpvOpCompositeConstruct, 0);
  851. auto extract_5 =
  852. TransformationCompositeExtract(instruction_descriptor_5, 204, 102, {0});
  853. ASSERT_TRUE(extract_5.IsApplicable(context.get(), fact_manager));
  854. extract_5.Apply(context.get(), &fact_manager);
  855. auto replacement_5 = TransformationReplaceIdWithSynonym(
  856. MakeIdUseDescriptor(27, instruction_descriptor_5, 1), 204);
  857. ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager));
  858. replacement_5.Apply(context.get(), &fact_manager);
  859. ASSERT_TRUE(IsValid(env, context.get()));
  860. // Replace %15 with %102[1:2] in '%83 = OpCopyObject %10 %15'
  861. auto instruction_descriptor_6 =
  862. MakeInstructionDescriptor(83, SpvOpCopyObject, 0);
  863. auto shuffle_6 = TransformationVectorShuffle(instruction_descriptor_6, 205,
  864. 102, 102, {1, 2});
  865. ASSERT_TRUE(shuffle_6.IsApplicable(context.get(), fact_manager));
  866. shuffle_6.Apply(context.get(), &fact_manager);
  867. auto replacement_6 = TransformationReplaceIdWithSynonym(
  868. MakeIdUseDescriptor(15, instruction_descriptor_6, 0), 205);
  869. ASSERT_TRUE(replacement_6.IsApplicable(context.get(), fact_manager));
  870. replacement_6.Apply(context.get(), &fact_manager);
  871. ASSERT_TRUE(IsValid(env, context.get()));
  872. // Replace %33 with %103[0] in '%86 = OpCopyObject %30 %33'
  873. auto instruction_descriptor_7 =
  874. MakeInstructionDescriptor(86, SpvOpCopyObject, 0);
  875. auto extract_7 =
  876. TransformationCompositeExtract(instruction_descriptor_7, 206, 103, {0});
  877. ASSERT_TRUE(extract_7.IsApplicable(context.get(), fact_manager));
  878. extract_7.Apply(context.get(), &fact_manager);
  879. auto replacement_7 = TransformationReplaceIdWithSynonym(
  880. MakeIdUseDescriptor(33, instruction_descriptor_7, 0), 206);
  881. ASSERT_TRUE(replacement_7.IsApplicable(context.get(), fact_manager));
  882. replacement_7.Apply(context.get(), &fact_manager);
  883. ASSERT_TRUE(IsValid(env, context.get()));
  884. // Replace %47 with %103[1:3] in '%84 = OpCopyObject %39 %47'
  885. auto instruction_descriptor_8 =
  886. MakeInstructionDescriptor(84, SpvOpCopyObject, 0);
  887. auto shuffle_8 = TransformationVectorShuffle(instruction_descriptor_8, 207,
  888. 103, 103, {1, 2, 3});
  889. ASSERT_TRUE(shuffle_8.IsApplicable(context.get(), fact_manager));
  890. shuffle_8.Apply(context.get(), &fact_manager);
  891. auto replacement_8 = TransformationReplaceIdWithSynonym(
  892. MakeIdUseDescriptor(47, instruction_descriptor_8, 0), 207);
  893. ASSERT_TRUE(replacement_8.IsApplicable(context.get(), fact_manager));
  894. replacement_8.Apply(context.get(), &fact_manager);
  895. ASSERT_TRUE(IsValid(env, context.get()));
  896. // Replace %42 with %104[0] in '%85 = OpCopyObject %30 %42'
  897. auto instruction_descriptor_9 =
  898. MakeInstructionDescriptor(85, SpvOpCopyObject, 0);
  899. auto extract_9 =
  900. TransformationCompositeExtract(instruction_descriptor_9, 208, 104, {0});
  901. ASSERT_TRUE(extract_9.IsApplicable(context.get(), fact_manager));
  902. extract_9.Apply(context.get(), &fact_manager);
  903. auto replacement_9 = TransformationReplaceIdWithSynonym(
  904. MakeIdUseDescriptor(42, instruction_descriptor_9, 0), 208);
  905. ASSERT_TRUE(replacement_9.IsApplicable(context.get(), fact_manager));
  906. replacement_9.Apply(context.get(), &fact_manager);
  907. ASSERT_TRUE(IsValid(env, context.get()));
  908. // Replace %45 with %104[1] in '%63 = OpLogicalOr %30 %45 %46'
  909. auto instruction_descriptor_10 =
  910. MakeInstructionDescriptor(63, SpvOpLogicalOr, 0);
  911. auto extract_10 =
  912. TransformationCompositeExtract(instruction_descriptor_10, 209, 104, {1});
  913. ASSERT_TRUE(extract_10.IsApplicable(context.get(), fact_manager));
  914. extract_10.Apply(context.get(), &fact_manager);
  915. auto replacement_10 = TransformationReplaceIdWithSynonym(
  916. MakeIdUseDescriptor(45, instruction_descriptor_10, 0), 209);
  917. ASSERT_TRUE(replacement_10.IsApplicable(context.get(), fact_manager));
  918. replacement_10.Apply(context.get(), &fact_manager);
  919. ASSERT_TRUE(IsValid(env, context.get()));
  920. // Replace %38 with %105[0:1] in 'OpStore %36 %38'
  921. auto instruction_descriptor_11 = MakeInstructionDescriptor(85, SpvOpStore, 0);
  922. auto shuffle_11 = TransformationVectorShuffle(instruction_descriptor_11, 210,
  923. 105, 105, {0, 1});
  924. ASSERT_TRUE(shuffle_11.IsApplicable(context.get(), fact_manager));
  925. shuffle_11.Apply(context.get(), &fact_manager);
  926. auto replacement_11 = TransformationReplaceIdWithSynonym(
  927. MakeIdUseDescriptor(38, instruction_descriptor_11, 1), 210);
  928. ASSERT_TRUE(replacement_11.IsApplicable(context.get(), fact_manager));
  929. replacement_11.Apply(context.get(), &fact_manager);
  930. ASSERT_TRUE(IsValid(env, context.get()));
  931. // Replace %46 with %105[2] in '%62 = OpLogicalAnd %30 %45 %46'
  932. auto instruction_descriptor_12 =
  933. MakeInstructionDescriptor(62, SpvOpLogicalAnd, 0);
  934. auto extract_12 =
  935. TransformationCompositeExtract(instruction_descriptor_12, 211, 105, {2});
  936. ASSERT_TRUE(extract_12.IsApplicable(context.get(), fact_manager));
  937. extract_12.Apply(context.get(), &fact_manager);
  938. auto replacement_12 = TransformationReplaceIdWithSynonym(
  939. MakeIdUseDescriptor(46, instruction_descriptor_12, 1), 211);
  940. ASSERT_TRUE(replacement_12.IsApplicable(context.get(), fact_manager));
  941. replacement_12.Apply(context.get(), &fact_manager);
  942. ASSERT_TRUE(IsValid(env, context.get()));
  943. const std::string after_transformation = R"(
  944. OpCapability Shader
  945. %1 = OpExtInstImport "GLSL.std.450"
  946. OpMemoryModel Logical GLSL450
  947. OpEntryPoint Fragment %4 "main"
  948. OpExecutionMode %4 OriginUpperLeft
  949. OpSource ESSL 310
  950. OpName %4 "main"
  951. OpName %8 "f"
  952. OpName %12 "v2"
  953. OpName %18 "v3"
  954. OpName %23 "v4"
  955. OpName %32 "b"
  956. OpName %36 "bv2"
  957. OpName %41 "bv3"
  958. OpName %50 "bv4"
  959. %2 = OpTypeVoid
  960. %3 = OpTypeFunction %2
  961. %6 = OpTypeFloat 32
  962. %7 = OpTypePointer Function %6
  963. %9 = OpConstant %6 42
  964. %10 = OpTypeVector %6 2
  965. %11 = OpTypePointer Function %10
  966. %16 = OpTypeVector %6 3
  967. %17 = OpTypePointer Function %16
  968. %21 = OpTypeVector %6 4
  969. %22 = OpTypePointer Function %21
  970. %30 = OpTypeBool
  971. %31 = OpTypePointer Function %30
  972. %33 = OpConstantFalse %30
  973. %34 = OpTypeVector %30 2
  974. %35 = OpTypePointer Function %34
  975. %37 = OpConstantTrue %30
  976. %38 = OpConstantComposite %34 %37 %37
  977. %39 = OpTypeVector %30 3
  978. %40 = OpTypePointer Function %39
  979. %48 = OpTypeVector %30 4
  980. %49 = OpTypePointer Function %48
  981. %51 = OpTypeInt 32 0
  982. %52 = OpConstant %51 2
  983. %55 = OpConstant %6 0
  984. %57 = OpConstant %51 1
  985. %4 = OpFunction %2 None %3
  986. %5 = OpLabel
  987. %8 = OpVariable %7 Function
  988. %12 = OpVariable %11 Function
  989. %18 = OpVariable %17 Function
  990. %23 = OpVariable %22 Function
  991. %32 = OpVariable %31 Function
  992. %36 = OpVariable %35 Function
  993. %41 = OpVariable %40 Function
  994. %50 = OpVariable %49 Function
  995. OpStore %8 %9
  996. %13 = OpLoad %6 %8
  997. %14 = OpLoad %6 %8
  998. %15 = OpCompositeConstruct %10 %13 %14
  999. OpStore %12 %15
  1000. %19 = OpLoad %10 %12
  1001. %20 = OpVectorShuffle %16 %19 %19 0 0 1
  1002. OpStore %18 %20
  1003. %24 = OpLoad %16 %18
  1004. %25 = OpLoad %6 %8
  1005. %26 = OpCompositeExtract %6 %24 0
  1006. %27 = OpCompositeExtract %6 %24 1
  1007. %28 = OpCompositeExtract %6 %24 2
  1008. %29 = OpCompositeConstruct %21 %26 %27 %28 %25
  1009. OpStore %23 %29
  1010. OpStore %32 %33
  1011. OpStore %36 %38
  1012. %42 = OpLoad %30 %32
  1013. %43 = OpLoad %34 %36
  1014. %44 = OpVectorShuffle %34 %43 %43 0 0
  1015. %45 = OpCompositeExtract %30 %44 0
  1016. %46 = OpCompositeExtract %30 %44 1
  1017. %47 = OpCompositeConstruct %39 %42 %45 %46
  1018. OpStore %41 %47
  1019. %53 = OpAccessChain %7 %23 %52
  1020. %54 = OpLoad %6 %53
  1021. %100 = OpCompositeConstruct %21 %20 %54
  1022. %101 = OpCompositeConstruct %21 %15 %19
  1023. %102 = OpCompositeConstruct %16 %27 %15
  1024. %103 = OpCompositeConstruct %48 %33 %47
  1025. %104 = OpCompositeConstruct %34 %42 %45
  1026. %105 = OpCompositeConstruct %39 %38 %46
  1027. %206 = OpCompositeExtract %30 %103 0
  1028. %86 = OpCopyObject %30 %206
  1029. %201 = OpCompositeExtract %6 %100 3
  1030. %56 = OpFOrdNotEqual %30 %201 %55
  1031. %200 = OpVectorShuffle %16 %100 %100 0 1 2
  1032. %80 = OpCopyObject %16 %200
  1033. %58 = OpAccessChain %7 %18 %57
  1034. %59 = OpLoad %6 %58
  1035. %60 = OpFOrdNotEqual %30 %59 %55
  1036. %61 = OpLoad %34 %36
  1037. %211 = OpCompositeExtract %30 %105 2
  1038. %62 = OpLogicalAnd %30 %45 %211
  1039. %209 = OpCompositeExtract %30 %104 1
  1040. %63 = OpLogicalOr %30 %209 %46
  1041. %64 = OpCompositeConstruct %48 %56 %60 %62 %63
  1042. %202 = OpVectorShuffle %10 %101 %101 0 1
  1043. OpStore %12 %202
  1044. %203 = OpVectorShuffle %10 %101 %101 2 3
  1045. %81 = OpVectorShuffle %16 %203 %19 0 0 1
  1046. %204 = OpCompositeExtract %6 %102 0
  1047. %82 = OpCompositeConstruct %21 %26 %204 %28 %25
  1048. %205 = OpVectorShuffle %10 %102 %102 1 2
  1049. %83 = OpCopyObject %10 %205
  1050. %207 = OpVectorShuffle %39 %103 %103 1 2 3
  1051. %84 = OpCopyObject %39 %207
  1052. OpStore %50 %64
  1053. %208 = OpCompositeExtract %30 %104 0
  1054. %85 = OpCopyObject %30 %208
  1055. %210 = OpVectorShuffle %34 %105 %105 0 1
  1056. OpStore %36 %210
  1057. OpReturn
  1058. OpFunctionEnd
  1059. )";
  1060. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  1061. }
  1062. } // namespace
  1063. } // namespace fuzz
  1064. } // namespace spvtools