transformation_vector_shuffle_test.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. // Copyright (c) 2019 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "source/fuzz/transformation_vector_shuffle.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(TransformationVectorShuffleTest, BasicTest) {
  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. %2 = OpTypeVoid
  31. %3 = OpTypeFunction %2
  32. %6 = OpTypeBool
  33. %7 = OpTypeVector %6 2
  34. %10 = OpConstantTrue %6
  35. %11 = OpConstantFalse %6
  36. %12 = OpConstantComposite %7 %10 %11
  37. %112 = OpUndef %7
  38. %13 = OpTypeVector %6 3
  39. %16 = OpConstantComposite %13 %10 %11 %10
  40. %17 = OpTypeVector %6 4
  41. %20 = OpConstantComposite %17 %10 %11 %10 %11
  42. %21 = OpTypeInt 32 1
  43. %22 = OpTypeVector %21 2
  44. %25 = OpConstant %21 1
  45. %26 = OpConstant %21 0
  46. %27 = OpConstantComposite %22 %25 %26
  47. %28 = OpTypeVector %21 3
  48. %31 = OpConstantComposite %28 %25 %26 %25
  49. %32 = OpTypeVector %21 4
  50. %33 = OpTypePointer Function %32
  51. %35 = OpConstantComposite %32 %25 %26 %25 %26
  52. %36 = OpTypeInt 32 0
  53. %37 = OpTypeVector %36 2
  54. %40 = OpConstant %36 1
  55. %41 = OpConstant %36 0
  56. %42 = OpConstantComposite %37 %40 %41
  57. %43 = OpTypeVector %36 3
  58. %46 = OpConstantComposite %43 %40 %41 %40
  59. %47 = OpTypeVector %36 4
  60. %50 = OpConstantComposite %47 %40 %41 %40 %41
  61. %51 = OpTypeFloat 32
  62. %55 = OpConstant %51 1
  63. %56 = OpConstant %51 0
  64. %58 = OpTypeVector %51 3
  65. %61 = OpConstantComposite %58 %55 %56 %55
  66. %62 = OpTypeVector %51 4
  67. %65 = OpConstantComposite %62 %55 %56 %55 %56
  68. %4 = OpFunction %2 None %3
  69. %5 = OpLabel
  70. OpSelectionMerge %100 None
  71. OpBranchConditional %10 %101 %102
  72. %101 = OpLabel
  73. %103 = OpCompositeConstruct %62 %55 %55 %55 %56
  74. OpBranch %100
  75. %102 = OpLabel
  76. OpBranch %100
  77. %100 = OpLabel
  78. OpReturn
  79. OpFunctionEnd
  80. )";
  81. const auto env = SPV_ENV_UNIVERSAL_1_4;
  82. const auto consumer = nullptr;
  83. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  84. spvtools::ValidatorOptions validator_options;
  85. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  86. kConsoleMessageConsumer));
  87. TransformationContext transformation_context(
  88. MakeUnique<FactManager>(context.get()), validator_options);
  89. transformation_context.GetFactManager()->AddFactDataSynonym(
  90. MakeDataDescriptor(10, {}), MakeDataDescriptor(12, {0}));
  91. transformation_context.GetFactManager()->AddFactDataSynonym(
  92. MakeDataDescriptor(11, {}), MakeDataDescriptor(12, {1}));
  93. transformation_context.GetFactManager()->AddFactDataSynonym(
  94. MakeDataDescriptor(10, {}), MakeDataDescriptor(16, {0}));
  95. transformation_context.GetFactManager()->AddFactDataSynonym(
  96. MakeDataDescriptor(11, {}), MakeDataDescriptor(16, {1}));
  97. transformation_context.GetFactManager()->AddFactDataSynonym(
  98. MakeDataDescriptor(10, {}), MakeDataDescriptor(16, {2}));
  99. transformation_context.GetFactManager()->AddFactDataSynonym(
  100. MakeDataDescriptor(10, {}), MakeDataDescriptor(20, {0}));
  101. transformation_context.GetFactManager()->AddFactDataSynonym(
  102. MakeDataDescriptor(11, {}), MakeDataDescriptor(20, {1}));
  103. transformation_context.GetFactManager()->AddFactDataSynonym(
  104. MakeDataDescriptor(10, {}), MakeDataDescriptor(20, {2}));
  105. transformation_context.GetFactManager()->AddFactDataSynonym(
  106. MakeDataDescriptor(11, {}), MakeDataDescriptor(20, {3}));
  107. transformation_context.GetFactManager()->AddFactDataSynonym(
  108. MakeDataDescriptor(25, {}), MakeDataDescriptor(27, {0}));
  109. transformation_context.GetFactManager()->AddFactDataSynonym(
  110. MakeDataDescriptor(26, {}), MakeDataDescriptor(27, {1}));
  111. transformation_context.GetFactManager()->AddFactDataSynonym(
  112. MakeDataDescriptor(25, {}), MakeDataDescriptor(31, {0}));
  113. transformation_context.GetFactManager()->AddFactDataSynonym(
  114. MakeDataDescriptor(26, {}), MakeDataDescriptor(31, {1}));
  115. transformation_context.GetFactManager()->AddFactDataSynonym(
  116. MakeDataDescriptor(25, {}), MakeDataDescriptor(31, {2}));
  117. transformation_context.GetFactManager()->AddFactDataSynonym(
  118. MakeDataDescriptor(25, {}), MakeDataDescriptor(35, {0}));
  119. transformation_context.GetFactManager()->AddFactDataSynonym(
  120. MakeDataDescriptor(26, {}), MakeDataDescriptor(35, {1}));
  121. transformation_context.GetFactManager()->AddFactDataSynonym(
  122. MakeDataDescriptor(25, {}), MakeDataDescriptor(35, {2}));
  123. transformation_context.GetFactManager()->AddFactDataSynonym(
  124. MakeDataDescriptor(26, {}), MakeDataDescriptor(35, {3}));
  125. transformation_context.GetFactManager()->AddFactDataSynonym(
  126. MakeDataDescriptor(40, {}), MakeDataDescriptor(42, {0}));
  127. transformation_context.GetFactManager()->AddFactDataSynonym(
  128. MakeDataDescriptor(41, {}), MakeDataDescriptor(42, {1}));
  129. transformation_context.GetFactManager()->AddFactDataSynonym(
  130. MakeDataDescriptor(40, {}), MakeDataDescriptor(46, {0}));
  131. transformation_context.GetFactManager()->AddFactDataSynonym(
  132. MakeDataDescriptor(41, {}), MakeDataDescriptor(46, {1}));
  133. transformation_context.GetFactManager()->AddFactDataSynonym(
  134. MakeDataDescriptor(40, {}), MakeDataDescriptor(46, {2}));
  135. transformation_context.GetFactManager()->AddFactDataSynonym(
  136. MakeDataDescriptor(40, {}), MakeDataDescriptor(50, {0}));
  137. transformation_context.GetFactManager()->AddFactDataSynonym(
  138. MakeDataDescriptor(41, {}), MakeDataDescriptor(50, {1}));
  139. transformation_context.GetFactManager()->AddFactDataSynonym(
  140. MakeDataDescriptor(40, {}), MakeDataDescriptor(50, {2}));
  141. transformation_context.GetFactManager()->AddFactDataSynonym(
  142. MakeDataDescriptor(41, {}), MakeDataDescriptor(50, {3}));
  143. transformation_context.GetFactManager()->AddFactDataSynonym(
  144. MakeDataDescriptor(55, {}), MakeDataDescriptor(61, {0}));
  145. transformation_context.GetFactManager()->AddFactDataSynonym(
  146. MakeDataDescriptor(56, {}), MakeDataDescriptor(61, {1}));
  147. transformation_context.GetFactManager()->AddFactDataSynonym(
  148. MakeDataDescriptor(55, {}), MakeDataDescriptor(61, {2}));
  149. transformation_context.GetFactManager()->AddFactDataSynonym(
  150. MakeDataDescriptor(55, {}), MakeDataDescriptor(65, {0}));
  151. transformation_context.GetFactManager()->AddFactDataSynonym(
  152. MakeDataDescriptor(56, {}), MakeDataDescriptor(65, {1}));
  153. transformation_context.GetFactManager()->AddFactDataSynonym(
  154. MakeDataDescriptor(55, {}), MakeDataDescriptor(65, {2}));
  155. transformation_context.GetFactManager()->AddFactDataSynonym(
  156. MakeDataDescriptor(56, {}), MakeDataDescriptor(65, {3}));
  157. // %103 does not dominate the return instruction.
  158. ASSERT_FALSE(TransformationVectorShuffle(
  159. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
  160. 103, 65, {3, 5, 7})
  161. .IsApplicable(context.get(), transformation_context));
  162. // Illegal to shuffle a bvec2 and a vec3
  163. ASSERT_FALSE(TransformationVectorShuffle(
  164. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
  165. 112, 61, {0, 2, 4})
  166. .IsApplicable(context.get(), transformation_context));
  167. // Illegal to shuffle an ivec2 and a uvec4
  168. ASSERT_FALSE(TransformationVectorShuffle(
  169. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
  170. 27, 50, {1, 3, 5})
  171. .IsApplicable(context.get(), transformation_context));
  172. // Vector 1 does not exist
  173. ASSERT_FALSE(TransformationVectorShuffle(
  174. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
  175. 300, 50, {1, 3, 5})
  176. .IsApplicable(context.get(), transformation_context));
  177. // Vector 2 does not exist
  178. ASSERT_FALSE(TransformationVectorShuffle(
  179. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
  180. 27, 300, {1, 3, 5})
  181. .IsApplicable(context.get(), transformation_context));
  182. // Index out of range
  183. ASSERT_FALSE(TransformationVectorShuffle(
  184. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
  185. 12, 112, {0, 20})
  186. .IsApplicable(context.get(), transformation_context));
  187. // Too many indices
  188. ASSERT_FALSE(TransformationVectorShuffle(
  189. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
  190. 12, 112, {0, 1, 0, 1, 0, 1, 0, 1})
  191. .IsApplicable(context.get(), transformation_context));
  192. // Too few indices
  193. ASSERT_FALSE(TransformationVectorShuffle(
  194. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
  195. 12, 112, {})
  196. .IsApplicable(context.get(), transformation_context));
  197. // Too few indices again
  198. ASSERT_FALSE(TransformationVectorShuffle(
  199. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
  200. 12, 112, {0})
  201. .IsApplicable(context.get(), transformation_context));
  202. // Indices define unknown type: we do not have vec2
  203. ASSERT_FALSE(TransformationVectorShuffle(
  204. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
  205. 65, 65, {0, 1})
  206. .IsApplicable(context.get(), transformation_context));
  207. // The instruction to insert before does not exist
  208. ASSERT_FALSE(
  209. TransformationVectorShuffle(
  210. MakeInstructionDescriptor(100, spv::Op::OpCompositeConstruct, 1), 201,
  211. 20, 12, {0xFFFFFFFF, 3, 5})
  212. .IsApplicable(context.get(), transformation_context));
  213. // The 'fresh' id is already in use
  214. ASSERT_FALSE(
  215. TransformationVectorShuffle(
  216. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 12, 12, 112, {})
  217. .IsApplicable(context.get(), transformation_context));
  218. protobufs::DataDescriptor temp_dd;
  219. TransformationVectorShuffle transformation1(
  220. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200, 12, 112,
  221. {1, 0});
  222. ASSERT_TRUE(
  223. transformation1.IsApplicable(context.get(), transformation_context));
  224. ApplyAndCheckFreshIds(transformation1, context.get(),
  225. &transformation_context);
  226. temp_dd = MakeDataDescriptor(200, {0});
  227. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  228. MakeDataDescriptor(11, {}), temp_dd));
  229. temp_dd = MakeDataDescriptor(200, {1});
  230. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  231. MakeDataDescriptor(10, {}), temp_dd));
  232. TransformationVectorShuffle transformation2(
  233. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 201, 20, 12,
  234. {0xFFFFFFFF, 3, 5});
  235. ASSERT_TRUE(
  236. transformation2.IsApplicable(context.get(), transformation_context));
  237. ApplyAndCheckFreshIds(transformation2, context.get(),
  238. &transformation_context);
  239. temp_dd = MakeDataDescriptor(201, {1});
  240. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  241. MakeDataDescriptor(11, {}), temp_dd));
  242. temp_dd = MakeDataDescriptor(201, {2});
  243. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  244. MakeDataDescriptor(11, {}), temp_dd));
  245. TransformationVectorShuffle transformation3(
  246. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 202, 27, 35,
  247. {5, 4, 1});
  248. ASSERT_TRUE(
  249. transformation3.IsApplicable(context.get(), transformation_context));
  250. ApplyAndCheckFreshIds(transformation3, context.get(),
  251. &transformation_context);
  252. temp_dd = MakeDataDescriptor(202, {0});
  253. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  254. MakeDataDescriptor(26, {}), temp_dd));
  255. temp_dd = MakeDataDescriptor(202, {1});
  256. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  257. MakeDataDescriptor(25, {}), temp_dd));
  258. temp_dd = MakeDataDescriptor(202, {2});
  259. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  260. MakeDataDescriptor(26, {}), temp_dd));
  261. TransformationVectorShuffle transformation4(
  262. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 203, 42, 46,
  263. {0, 1});
  264. ASSERT_TRUE(
  265. transformation4.IsApplicable(context.get(), transformation_context));
  266. ApplyAndCheckFreshIds(transformation4, context.get(),
  267. &transformation_context);
  268. temp_dd = MakeDataDescriptor(203, {0});
  269. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  270. MakeDataDescriptor(40, {}), temp_dd));
  271. temp_dd = MakeDataDescriptor(203, {1});
  272. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  273. MakeDataDescriptor(41, {}), temp_dd));
  274. TransformationVectorShuffle transformation5(
  275. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 204, 42, 46,
  276. {2, 3, 4});
  277. ASSERT_TRUE(
  278. transformation5.IsApplicable(context.get(), transformation_context));
  279. ApplyAndCheckFreshIds(transformation5, context.get(),
  280. &transformation_context);
  281. temp_dd = MakeDataDescriptor(204, {0});
  282. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  283. MakeDataDescriptor(40, {}), temp_dd));
  284. temp_dd = MakeDataDescriptor(204, {1});
  285. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  286. MakeDataDescriptor(41, {}), temp_dd));
  287. temp_dd = MakeDataDescriptor(204, {2});
  288. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  289. MakeDataDescriptor(40, {}), temp_dd));
  290. TransformationVectorShuffle transformation6(
  291. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 205, 42, 42,
  292. {0, 1, 2, 3});
  293. ASSERT_TRUE(
  294. transformation6.IsApplicable(context.get(), transformation_context));
  295. ApplyAndCheckFreshIds(transformation6, context.get(),
  296. &transformation_context);
  297. temp_dd = MakeDataDescriptor(205, {0});
  298. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  299. MakeDataDescriptor(40, {}), temp_dd));
  300. temp_dd = MakeDataDescriptor(205, {1});
  301. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  302. MakeDataDescriptor(41, {}), temp_dd));
  303. temp_dd = MakeDataDescriptor(205, {2});
  304. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  305. MakeDataDescriptor(40, {}), temp_dd));
  306. temp_dd = MakeDataDescriptor(205, {3});
  307. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  308. MakeDataDescriptor(41, {}), temp_dd));
  309. // swizzle vec4 from vec4 and vec4 using some undefs
  310. TransformationVectorShuffle transformation7(
  311. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 206, 65, 65,
  312. {0xFFFFFFFF, 3, 6, 0xFFFFFFFF});
  313. ASSERT_TRUE(
  314. transformation7.IsApplicable(context.get(), transformation_context));
  315. ApplyAndCheckFreshIds(transformation7, context.get(),
  316. &transformation_context);
  317. temp_dd = MakeDataDescriptor(206, {1});
  318. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  319. MakeDataDescriptor(56, {}), temp_dd));
  320. std::string after_transformation = R"(
  321. OpCapability Shader
  322. %1 = OpExtInstImport "GLSL.std.450"
  323. OpMemoryModel Logical GLSL450
  324. OpEntryPoint Fragment %4 "main"
  325. OpExecutionMode %4 OriginUpperLeft
  326. OpSource ESSL 310
  327. %2 = OpTypeVoid
  328. %3 = OpTypeFunction %2
  329. %6 = OpTypeBool
  330. %7 = OpTypeVector %6 2
  331. %10 = OpConstantTrue %6
  332. %11 = OpConstantFalse %6
  333. %12 = OpConstantComposite %7 %10 %11
  334. %112 = OpUndef %7
  335. %13 = OpTypeVector %6 3
  336. %16 = OpConstantComposite %13 %10 %11 %10
  337. %17 = OpTypeVector %6 4
  338. %20 = OpConstantComposite %17 %10 %11 %10 %11
  339. %21 = OpTypeInt 32 1
  340. %22 = OpTypeVector %21 2
  341. %25 = OpConstant %21 1
  342. %26 = OpConstant %21 0
  343. %27 = OpConstantComposite %22 %25 %26
  344. %28 = OpTypeVector %21 3
  345. %31 = OpConstantComposite %28 %25 %26 %25
  346. %32 = OpTypeVector %21 4
  347. %33 = OpTypePointer Function %32
  348. %35 = OpConstantComposite %32 %25 %26 %25 %26
  349. %36 = OpTypeInt 32 0
  350. %37 = OpTypeVector %36 2
  351. %40 = OpConstant %36 1
  352. %41 = OpConstant %36 0
  353. %42 = OpConstantComposite %37 %40 %41
  354. %43 = OpTypeVector %36 3
  355. %46 = OpConstantComposite %43 %40 %41 %40
  356. %47 = OpTypeVector %36 4
  357. %50 = OpConstantComposite %47 %40 %41 %40 %41
  358. %51 = OpTypeFloat 32
  359. %55 = OpConstant %51 1
  360. %56 = OpConstant %51 0
  361. %58 = OpTypeVector %51 3
  362. %61 = OpConstantComposite %58 %55 %56 %55
  363. %62 = OpTypeVector %51 4
  364. %65 = OpConstantComposite %62 %55 %56 %55 %56
  365. %4 = OpFunction %2 None %3
  366. %5 = OpLabel
  367. OpSelectionMerge %100 None
  368. OpBranchConditional %10 %101 %102
  369. %101 = OpLabel
  370. %103 = OpCompositeConstruct %62 %55 %55 %55 %56
  371. OpBranch %100
  372. %102 = OpLabel
  373. OpBranch %100
  374. %100 = OpLabel
  375. %200 = OpVectorShuffle %7 %12 %112 1 0
  376. %201 = OpVectorShuffle %13 %20 %12 0xFFFFFFFF 3 5
  377. %202 = OpVectorShuffle %28 %27 %35 5 4 1
  378. %203 = OpVectorShuffle %37 %42 %46 0 1
  379. %204 = OpVectorShuffle %43 %42 %46 2 3 4
  380. %205 = OpVectorShuffle %47 %42 %42 0 1 2 3
  381. %206 = OpVectorShuffle %62 %65 %65 0xFFFFFFFF 3 6 0xFFFFFFFF
  382. OpReturn
  383. OpFunctionEnd
  384. )";
  385. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  386. }
  387. TEST(TransformationVectorShuffleTest, IllegalInsertionPoints) {
  388. std::string shader = R"(
  389. OpCapability Shader
  390. %1 = OpExtInstImport "GLSL.std.450"
  391. OpMemoryModel Logical GLSL450
  392. OpEntryPoint Fragment %4 "main" %51 %27
  393. OpExecutionMode %4 OriginUpperLeft
  394. OpSource ESSL 310
  395. OpName %4 "main"
  396. OpName %25 "buf"
  397. OpMemberName %25 0 "value"
  398. OpName %27 ""
  399. OpName %51 "color"
  400. OpMemberDecorate %25 0 Offset 0
  401. OpDecorate %25 Block
  402. OpDecorate %27 DescriptorSet 0
  403. OpDecorate %27 Binding 0
  404. OpDecorate %51 Location 0
  405. %2 = OpTypeVoid
  406. %3 = OpTypeFunction %2
  407. %6 = OpTypeFloat 32
  408. %7 = OpTypeVector %6 4
  409. %150 = OpTypeVector %6 2
  410. %10 = OpConstant %6 0.300000012
  411. %11 = OpConstant %6 0.400000006
  412. %12 = OpConstant %6 0.5
  413. %13 = OpConstant %6 1
  414. %14 = OpConstantComposite %7 %10 %11 %12 %13
  415. %15 = OpTypeInt 32 1
  416. %18 = OpConstant %15 0
  417. %25 = OpTypeStruct %6
  418. %26 = OpTypePointer Uniform %25
  419. %27 = OpVariable %26 Uniform
  420. %28 = OpTypePointer Uniform %6
  421. %32 = OpTypeBool
  422. %103 = OpConstantTrue %32
  423. %34 = OpConstant %6 0.100000001
  424. %48 = OpConstant %15 1
  425. %50 = OpTypePointer Output %7
  426. %51 = OpVariable %50 Output
  427. %100 = OpTypePointer Function %6
  428. %4 = OpFunction %2 None %3
  429. %5 = OpLabel
  430. %101 = OpVariable %100 Function
  431. %102 = OpVariable %100 Function
  432. OpBranch %19
  433. %19 = OpLabel
  434. %60 = OpPhi %7 %14 %5 %58 %20
  435. %59 = OpPhi %15 %18 %5 %49 %20
  436. %29 = OpAccessChain %28 %27 %18
  437. %30 = OpLoad %6 %29
  438. %31 = OpConvertFToS %15 %30
  439. %33 = OpSLessThan %32 %59 %31
  440. OpLoopMerge %21 %20 None
  441. OpBranchConditional %33 %20 %21
  442. %20 = OpLabel
  443. %39 = OpCompositeExtract %6 %60 0
  444. %40 = OpFAdd %6 %39 %34
  445. %55 = OpCompositeInsert %7 %40 %60 0
  446. %44 = OpCompositeExtract %6 %60 1
  447. %45 = OpFSub %6 %44 %34
  448. %58 = OpCompositeInsert %7 %45 %55 1
  449. %49 = OpIAdd %15 %59 %48
  450. OpBranch %19
  451. %21 = OpLabel
  452. OpStore %51 %60
  453. OpSelectionMerge %105 None
  454. OpBranchConditional %103 %104 %105
  455. %104 = OpLabel
  456. OpBranch %105
  457. %105 = OpLabel
  458. OpReturn
  459. OpFunctionEnd
  460. )";
  461. const auto env = SPV_ENV_UNIVERSAL_1_4;
  462. const auto consumer = nullptr;
  463. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  464. spvtools::ValidatorOptions validator_options;
  465. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  466. kConsoleMessageConsumer));
  467. TransformationContext transformation_context(
  468. MakeUnique<FactManager>(context.get()), validator_options);
  469. // Cannot insert before the OpVariables of a function.
  470. ASSERT_FALSE(TransformationVectorShuffle(
  471. MakeInstructionDescriptor(101, spv::Op::OpVariable, 0), 200,
  472. 14, 14, {0, 1})
  473. .IsApplicable(context.get(), transformation_context));
  474. ASSERT_FALSE(TransformationVectorShuffle(
  475. MakeInstructionDescriptor(101, spv::Op::OpVariable, 1), 200,
  476. 14, 14, {1, 2})
  477. .IsApplicable(context.get(), transformation_context));
  478. ASSERT_FALSE(TransformationVectorShuffle(
  479. MakeInstructionDescriptor(102, spv::Op::OpVariable, 0), 200,
  480. 14, 14, {1, 2})
  481. .IsApplicable(context.get(), transformation_context));
  482. // OK to insert right after the OpVariables.
  483. ASSERT_FALSE(TransformationVectorShuffle(
  484. MakeInstructionDescriptor(102, spv::Op::OpBranch, 1), 200,
  485. 14, 14, {1, 1})
  486. .IsApplicable(context.get(), transformation_context));
  487. // Cannot insert before the OpPhis of a block.
  488. ASSERT_FALSE(
  489. TransformationVectorShuffle(
  490. MakeInstructionDescriptor(60, spv::Op::OpPhi, 0), 200, 14, 14, {2, 0})
  491. .IsApplicable(context.get(), transformation_context));
  492. ASSERT_FALSE(
  493. TransformationVectorShuffle(
  494. MakeInstructionDescriptor(59, spv::Op::OpPhi, 0), 200, 14, 14, {3, 0})
  495. .IsApplicable(context.get(), transformation_context));
  496. // OK to insert after the OpPhis.
  497. ASSERT_TRUE(TransformationVectorShuffle(
  498. MakeInstructionDescriptor(59, spv::Op::OpAccessChain, 0), 200,
  499. 14, 14, {3, 4})
  500. .IsApplicable(context.get(), transformation_context));
  501. // Cannot insert before OpLoopMerge
  502. ASSERT_FALSE(
  503. TransformationVectorShuffle(
  504. MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0), 200,
  505. 14, 14, {3})
  506. .IsApplicable(context.get(), transformation_context));
  507. // Cannot insert before OpSelectionMerge
  508. ASSERT_FALSE(
  509. TransformationVectorShuffle(
  510. MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0), 200,
  511. 14, 14, {2})
  512. .IsApplicable(context.get(), transformation_context));
  513. }
  514. TEST(TransformationVectorShuffleTest, HandlesIrrelevantIds1) {
  515. std::string shader = R"(
  516. OpCapability Shader
  517. %1 = OpExtInstImport "GLSL.std.450"
  518. OpMemoryModel Logical GLSL450
  519. OpEntryPoint Fragment %4 "main"
  520. OpExecutionMode %4 OriginUpperLeft
  521. OpSource ESSL 310
  522. %2 = OpTypeVoid
  523. %3 = OpTypeFunction %2
  524. %6 = OpTypeBool
  525. %7 = OpTypeVector %6 2
  526. %10 = OpConstantTrue %6
  527. %11 = OpConstantFalse %6
  528. %12 = OpConstantComposite %7 %10 %11
  529. %112 = OpConstantComposite %7 %11 %10
  530. %13 = OpTypeVector %6 3
  531. %16 = OpConstantComposite %13 %10 %11 %10
  532. %17 = OpTypeVector %6 4
  533. %20 = OpConstantComposite %17 %10 %11 %10 %11
  534. %21 = OpTypeInt 32 1
  535. %22 = OpTypeVector %21 2
  536. %25 = OpConstant %21 1
  537. %26 = OpConstant %21 0
  538. %27 = OpConstantComposite %22 %25 %26
  539. %28 = OpTypeVector %21 3
  540. %31 = OpConstantComposite %28 %25 %26 %25
  541. %32 = OpTypeVector %21 4
  542. %33 = OpTypePointer Function %32
  543. %35 = OpConstantComposite %32 %25 %26 %25 %26
  544. %36 = OpTypeInt 32 0
  545. %37 = OpTypeVector %36 2
  546. %40 = OpConstant %36 1
  547. %41 = OpConstant %36 0
  548. %42 = OpConstantComposite %37 %40 %41
  549. %43 = OpTypeVector %36 3
  550. %46 = OpConstantComposite %43 %40 %41 %40
  551. %47 = OpTypeVector %36 4
  552. %50 = OpConstantComposite %47 %40 %41 %40 %41
  553. %51 = OpTypeFloat 32
  554. %55 = OpConstant %51 1
  555. %56 = OpConstant %51 0
  556. %58 = OpTypeVector %51 3
  557. %61 = OpConstantComposite %58 %55 %56 %55
  558. %62 = OpTypeVector %51 4
  559. %65 = OpConstantComposite %62 %55 %56 %55 %56
  560. %4 = OpFunction %2 None %3
  561. %5 = OpLabel
  562. OpSelectionMerge %100 None
  563. OpBranchConditional %10 %101 %102
  564. %101 = OpLabel
  565. %103 = OpCompositeConstruct %62 %55 %55 %55 %56
  566. OpBranch %100
  567. %102 = OpLabel
  568. OpBranch %100
  569. %100 = OpLabel
  570. OpReturn
  571. OpFunctionEnd
  572. )";
  573. const auto env = SPV_ENV_UNIVERSAL_1_4;
  574. const auto consumer = nullptr;
  575. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  576. spvtools::ValidatorOptions validator_options;
  577. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  578. kConsoleMessageConsumer));
  579. TransformationContext transformation_context(
  580. MakeUnique<FactManager>(context.get()), validator_options);
  581. TransformationVectorShuffle transformation(
  582. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200, 12, 112,
  583. {2, 0});
  584. ASSERT_TRUE(
  585. transformation.IsApplicable(context.get(), transformation_context));
  586. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  587. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  588. kConsoleMessageConsumer));
  589. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  590. MakeDataDescriptor(12, {0}), MakeDataDescriptor(200, {1})));
  591. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  592. MakeDataDescriptor(112, {0}), MakeDataDescriptor(200, {0})));
  593. }
  594. TEST(TransformationVectorShuffleTest, HandlesIrrelevantIds2) {
  595. std::string shader = R"(
  596. OpCapability Shader
  597. %1 = OpExtInstImport "GLSL.std.450"
  598. OpMemoryModel Logical GLSL450
  599. OpEntryPoint Fragment %4 "main"
  600. OpExecutionMode %4 OriginUpperLeft
  601. OpSource ESSL 310
  602. %2 = OpTypeVoid
  603. %3 = OpTypeFunction %2
  604. %6 = OpTypeBool
  605. %7 = OpTypeVector %6 2
  606. %10 = OpConstantTrue %6
  607. %11 = OpConstantFalse %6
  608. %12 = OpConstantComposite %7 %10 %11
  609. %112 = OpConstantComposite %7 %11 %10
  610. %13 = OpTypeVector %6 3
  611. %16 = OpConstantComposite %13 %10 %11 %10
  612. %17 = OpTypeVector %6 4
  613. %20 = OpConstantComposite %17 %10 %11 %10 %11
  614. %21 = OpTypeInt 32 1
  615. %22 = OpTypeVector %21 2
  616. %25 = OpConstant %21 1
  617. %26 = OpConstant %21 0
  618. %27 = OpConstantComposite %22 %25 %26
  619. %28 = OpTypeVector %21 3
  620. %31 = OpConstantComposite %28 %25 %26 %25
  621. %32 = OpTypeVector %21 4
  622. %33 = OpTypePointer Function %32
  623. %35 = OpConstantComposite %32 %25 %26 %25 %26
  624. %36 = OpTypeInt 32 0
  625. %37 = OpTypeVector %36 2
  626. %40 = OpConstant %36 1
  627. %41 = OpConstant %36 0
  628. %42 = OpConstantComposite %37 %40 %41
  629. %43 = OpTypeVector %36 3
  630. %46 = OpConstantComposite %43 %40 %41 %40
  631. %47 = OpTypeVector %36 4
  632. %50 = OpConstantComposite %47 %40 %41 %40 %41
  633. %51 = OpTypeFloat 32
  634. %55 = OpConstant %51 1
  635. %56 = OpConstant %51 0
  636. %58 = OpTypeVector %51 3
  637. %61 = OpConstantComposite %58 %55 %56 %55
  638. %62 = OpTypeVector %51 4
  639. %65 = OpConstantComposite %62 %55 %56 %55 %56
  640. %4 = OpFunction %2 None %3
  641. %5 = OpLabel
  642. OpSelectionMerge %100 None
  643. OpBranchConditional %10 %101 %102
  644. %101 = OpLabel
  645. %103 = OpCompositeConstruct %62 %55 %55 %55 %56
  646. OpBranch %100
  647. %102 = OpLabel
  648. OpBranch %100
  649. %100 = OpLabel
  650. OpReturn
  651. OpFunctionEnd
  652. )";
  653. const auto env = SPV_ENV_UNIVERSAL_1_4;
  654. const auto consumer = nullptr;
  655. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  656. spvtools::ValidatorOptions validator_options;
  657. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  658. kConsoleMessageConsumer));
  659. TransformationContext transformation_context(
  660. MakeUnique<FactManager>(context.get()), validator_options);
  661. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(112);
  662. TransformationVectorShuffle transformation(
  663. MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200, 12, 112,
  664. {2, 0});
  665. ASSERT_TRUE(
  666. transformation.IsApplicable(context.get(), transformation_context));
  667. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  668. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  669. kConsoleMessageConsumer));
  670. // Because %12 is not irrelevant, we get a synonym between it and %200[1].
  671. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  672. MakeDataDescriptor(12, {0}), MakeDataDescriptor(200, {1})));
  673. // Because %112 is irrelevant, we do not get a synonym between it and %200[0].
  674. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  675. MakeDataDescriptor(112, {0}), MakeDataDescriptor(200, {0})));
  676. }
  677. TEST(TransformationVectorShuffleTest, HandlesIrrelevantIds3) {
  678. std::string shader = R"(
  679. OpCapability Shader
  680. %1 = OpExtInstImport "GLSL.std.450"
  681. OpMemoryModel Logical GLSL450
  682. OpEntryPoint Fragment %4 "main"
  683. OpExecutionMode %4 OriginUpperLeft
  684. OpSource ESSL 320
  685. %2 = OpTypeVoid
  686. %3 = OpTypeFunction %2
  687. %6 = OpTypeInt 32 1
  688. %7 = OpTypeVector %6 2
  689. %8 = OpTypePointer Function %7
  690. %10 = OpConstant %6 0
  691. %11 = OpConstant %6 1
  692. %12 = OpConstantComposite %7 %10 %11
  693. %40 = OpConstantComposite %7 %10 %11
  694. %13 = OpTypeBool
  695. %14 = OpConstantFalse %13
  696. %4 = OpFunction %2 None %3
  697. %5 = OpLabel
  698. %9 = OpVariable %8 Function
  699. OpStore %9 %12
  700. OpSelectionMerge %16 None
  701. OpBranchConditional %14 %15 %16
  702. %15 = OpLabel
  703. OpBranch %16
  704. %16 = OpLabel
  705. OpReturn
  706. OpFunctionEnd
  707. )";
  708. const auto env = SPV_ENV_UNIVERSAL_1_4;
  709. const auto consumer = nullptr;
  710. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  711. spvtools::ValidatorOptions validator_options;
  712. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  713. kConsoleMessageConsumer));
  714. TransformationContext transformation_context(
  715. MakeUnique<FactManager>(context.get()), validator_options);
  716. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(40);
  717. transformation_context.GetFactManager()->AddFactBlockIsDead(15);
  718. TransformationVectorShuffle transformation1(
  719. MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 200, 12, 12, {0, 3});
  720. ASSERT_TRUE(
  721. transformation1.IsApplicable(context.get(), transformation_context));
  722. ApplyAndCheckFreshIds(transformation1, context.get(),
  723. &transformation_context);
  724. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  725. MakeDataDescriptor(200, {0}), MakeDataDescriptor(12, {0})));
  726. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  727. MakeDataDescriptor(200, {1}), MakeDataDescriptor(12, {1})));
  728. TransformationVectorShuffle transformation2(
  729. MakeInstructionDescriptor(16, spv::Op::OpReturn, 0), 201, 12, 40, {0, 1});
  730. ASSERT_TRUE(
  731. transformation2.IsApplicable(context.get(), transformation_context));
  732. ApplyAndCheckFreshIds(transformation2, context.get(),
  733. &transformation_context);
  734. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  735. MakeDataDescriptor(201, {0}), MakeDataDescriptor(12, {0})));
  736. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  737. MakeDataDescriptor(201, {1}), MakeDataDescriptor(12, {1})));
  738. TransformationVectorShuffle transformation3(
  739. MakeInstructionDescriptor(16, spv::Op::OpReturn, 0), 202, 40, 12, {2, 3});
  740. ASSERT_TRUE(
  741. transformation3.IsApplicable(context.get(), transformation_context));
  742. ApplyAndCheckFreshIds(transformation3, context.get(),
  743. &transformation_context);
  744. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  745. MakeDataDescriptor(202, {0}), MakeDataDescriptor(12, {0})));
  746. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  747. MakeDataDescriptor(202, {1}), MakeDataDescriptor(12, {1})));
  748. TransformationVectorShuffle transformation4(
  749. MakeInstructionDescriptor(16, spv::Op::OpReturn, 0), 203, 40, 12, {0, 3});
  750. ASSERT_TRUE(
  751. transformation4.IsApplicable(context.get(), transformation_context));
  752. ApplyAndCheckFreshIds(transformation4, context.get(),
  753. &transformation_context);
  754. // Because %40 is irrelevant we do not get a synonym between it and %203[0].
  755. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  756. MakeDataDescriptor(203, {0}), MakeDataDescriptor(40, {0})));
  757. // Because %12 is *not* irrelevant we do get a synonym between it and %203[1].
  758. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  759. MakeDataDescriptor(203, {1}), MakeDataDescriptor(12, {1})));
  760. }
  761. } // namespace
  762. } // namespace fuzz
  763. } // namespace spvtools