transformation_composite_extract_test.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  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_composite_extract.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(TransformationCompositeExtractTest, 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. OpName %4 "main"
  31. OpName %8 "a"
  32. OpName %10 "b"
  33. OpName %17 "FunnyPoint"
  34. OpMemberName %17 0 "x"
  35. OpMemberName %17 1 "y"
  36. OpMemberName %17 2 "z"
  37. OpName %19 "p"
  38. %2 = OpTypeVoid
  39. %3 = OpTypeFunction %2
  40. %6 = OpTypeInt 32 1
  41. %7 = OpTypePointer Function %6
  42. %12 = OpTypeBool
  43. %16 = OpTypeFloat 32
  44. %17 = OpTypeStruct %16 %16 %6
  45. %81 = OpTypeStruct %17 %16
  46. %18 = OpTypePointer Function %17
  47. %20 = OpConstant %6 0
  48. %23 = OpTypePointer Function %16
  49. %26 = OpConstant %6 1
  50. %30 = OpConstant %6 2
  51. %80 = OpUndef %16
  52. %4 = OpFunction %2 None %3
  53. %5 = OpLabel
  54. %8 = OpVariable %7 Function
  55. %10 = OpVariable %7 Function
  56. %19 = OpVariable %18 Function
  57. %9 = OpLoad %6 %8
  58. %11 = OpLoad %6 %10
  59. %100 = OpCompositeConstruct %17 %80 %80 %26
  60. %104 = OpCompositeConstruct %81 %100 %80
  61. %13 = OpIEqual %12 %9 %11
  62. OpSelectionMerge %15 None
  63. OpBranchConditional %13 %14 %25
  64. %14 = OpLabel
  65. %21 = OpLoad %6 %8
  66. %22 = OpConvertSToF %16 %21
  67. %101 = OpCompositeConstruct %17 %22 %80 %30
  68. %24 = OpAccessChain %23 %19 %20
  69. OpStore %24 %22
  70. OpBranch %15
  71. %25 = OpLabel
  72. %27 = OpLoad %6 %10
  73. %28 = OpConvertSToF %16 %27
  74. %102 = OpCompositeConstruct %17 %80 %28 %27
  75. %29 = OpAccessChain %23 %19 %26
  76. OpStore %29 %28
  77. OpBranch %15
  78. %15 = OpLabel
  79. %31 = OpAccessChain %23 %19 %20
  80. %32 = OpLoad %16 %31
  81. %33 = OpAccessChain %23 %19 %26
  82. %34 = OpLoad %16 %33
  83. %103 = OpCompositeConstruct %17 %34 %32 %9
  84. %35 = OpFAdd %16 %32 %34
  85. %36 = OpConvertFToS %6 %35
  86. %37 = OpAccessChain %7 %19 %30
  87. OpStore %37 %36
  88. OpReturn
  89. OpFunctionEnd
  90. )";
  91. const auto env = SPV_ENV_UNIVERSAL_1_4;
  92. const auto consumer = nullptr;
  93. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  94. spvtools::ValidatorOptions validator_options;
  95. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  96. kConsoleMessageConsumer));
  97. TransformationContext transformation_context(
  98. MakeUnique<FactManager>(context.get()), validator_options);
  99. // Instruction does not exist.
  100. ASSERT_FALSE(
  101. TransformationCompositeExtract(
  102. MakeInstructionDescriptor(36, spv::Op::OpIAdd, 0), 200, 101, {0})
  103. .IsApplicable(context.get(), transformation_context));
  104. // Id for composite is not a composite.
  105. ASSERT_FALSE(
  106. TransformationCompositeExtract(
  107. MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0), 200, 32, {})
  108. .IsApplicable(context.get(), transformation_context));
  109. // Composite does not dominate instruction being inserted before.
  110. ASSERT_FALSE(TransformationCompositeExtract(
  111. MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0),
  112. 200, 101, {0})
  113. .IsApplicable(context.get(), transformation_context));
  114. // Too many indices for extraction from struct composite.
  115. ASSERT_FALSE(TransformationCompositeExtract(
  116. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0),
  117. 200, 101, {0, 0})
  118. .IsApplicable(context.get(), transformation_context));
  119. // Too many indices for extraction from struct composite.
  120. ASSERT_FALSE(TransformationCompositeExtract(
  121. MakeInstructionDescriptor(13, spv::Op::OpIEqual, 0), 200,
  122. 104, {0, 0, 0})
  123. .IsApplicable(context.get(), transformation_context));
  124. // Out of bounds index for extraction from struct composite.
  125. ASSERT_FALSE(
  126. TransformationCompositeExtract(
  127. MakeInstructionDescriptor(13, spv::Op::OpIEqual, 0), 200, 104, {0, 3})
  128. .IsApplicable(context.get(), transformation_context));
  129. // Result id already used.
  130. ASSERT_FALSE(
  131. TransformationCompositeExtract(
  132. MakeInstructionDescriptor(35, spv::Op::OpFAdd, 0), 80, 103, {0})
  133. .IsApplicable(context.get(), transformation_context));
  134. TransformationCompositeExtract transformation_1(
  135. MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
  136. ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(201));
  137. ASSERT_EQ(nullptr, context->get_instr_block(201));
  138. uint32_t num_uses_of_100_before = context->get_def_use_mgr()->NumUses(100);
  139. ASSERT_TRUE(
  140. transformation_1.IsApplicable(context.get(), transformation_context));
  141. ApplyAndCheckFreshIds(transformation_1, context.get(),
  142. &transformation_context);
  143. ASSERT_EQ(spv::Op::OpCompositeExtract,
  144. context->get_def_use_mgr()->GetDef(201)->opcode());
  145. ASSERT_EQ(15, context->get_instr_block(201)->id());
  146. ASSERT_EQ(num_uses_of_100_before + 1,
  147. context->get_def_use_mgr()->NumUses(100));
  148. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  149. kConsoleMessageConsumer));
  150. TransformationCompositeExtract transformation_2(
  151. MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0), 202, 104,
  152. {0, 2});
  153. ASSERT_TRUE(
  154. transformation_2.IsApplicable(context.get(), transformation_context));
  155. ApplyAndCheckFreshIds(transformation_2, context.get(),
  156. &transformation_context);
  157. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  158. kConsoleMessageConsumer));
  159. TransformationCompositeExtract transformation_3(
  160. MakeInstructionDescriptor(29, spv::Op::OpAccessChain, 0), 203, 104, {0});
  161. ASSERT_TRUE(
  162. transformation_3.IsApplicable(context.get(), transformation_context));
  163. ApplyAndCheckFreshIds(transformation_3, context.get(),
  164. &transformation_context);
  165. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  166. kConsoleMessageConsumer));
  167. TransformationCompositeExtract transformation_4(
  168. MakeInstructionDescriptor(24, spv::Op::OpStore, 0), 204, 101, {0});
  169. ASSERT_TRUE(
  170. transformation_4.IsApplicable(context.get(), transformation_context));
  171. ApplyAndCheckFreshIds(transformation_4, context.get(),
  172. &transformation_context);
  173. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  174. kConsoleMessageConsumer));
  175. TransformationCompositeExtract transformation_5(
  176. MakeInstructionDescriptor(29, spv::Op::OpBranch, 0), 205, 102, {2});
  177. ASSERT_TRUE(
  178. transformation_5.IsApplicable(context.get(), transformation_context));
  179. ApplyAndCheckFreshIds(transformation_5, context.get(),
  180. &transformation_context);
  181. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  182. kConsoleMessageConsumer));
  183. TransformationCompositeExtract transformation_6(
  184. MakeInstructionDescriptor(37, spv::Op::OpReturn, 0), 206, 103, {1});
  185. ASSERT_TRUE(
  186. transformation_6.IsApplicable(context.get(), transformation_context));
  187. ApplyAndCheckFreshIds(transformation_6, context.get(),
  188. &transformation_context);
  189. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  190. kConsoleMessageConsumer));
  191. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  192. MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
  193. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  194. MakeDataDescriptor(202, {}), MakeDataDescriptor(104, {0, 2})));
  195. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  196. MakeDataDescriptor(203, {}), MakeDataDescriptor(104, {0})));
  197. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  198. MakeDataDescriptor(204, {}), MakeDataDescriptor(101, {0})));
  199. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  200. MakeDataDescriptor(205, {}), MakeDataDescriptor(102, {2})));
  201. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  202. MakeDataDescriptor(206, {}), MakeDataDescriptor(103, {1})));
  203. std::string after_transformation = R"(
  204. OpCapability Shader
  205. %1 = OpExtInstImport "GLSL.std.450"
  206. OpMemoryModel Logical GLSL450
  207. OpEntryPoint Fragment %4 "main"
  208. OpExecutionMode %4 OriginUpperLeft
  209. OpSource ESSL 310
  210. OpName %4 "main"
  211. OpName %8 "a"
  212. OpName %10 "b"
  213. OpName %17 "FunnyPoint"
  214. OpMemberName %17 0 "x"
  215. OpMemberName %17 1 "y"
  216. OpMemberName %17 2 "z"
  217. OpName %19 "p"
  218. %2 = OpTypeVoid
  219. %3 = OpTypeFunction %2
  220. %6 = OpTypeInt 32 1
  221. %7 = OpTypePointer Function %6
  222. %12 = OpTypeBool
  223. %16 = OpTypeFloat 32
  224. %17 = OpTypeStruct %16 %16 %6
  225. %81 = OpTypeStruct %17 %16
  226. %18 = OpTypePointer Function %17
  227. %20 = OpConstant %6 0
  228. %23 = OpTypePointer Function %16
  229. %26 = OpConstant %6 1
  230. %30 = OpConstant %6 2
  231. %80 = OpUndef %16
  232. %4 = OpFunction %2 None %3
  233. %5 = OpLabel
  234. %8 = OpVariable %7 Function
  235. %10 = OpVariable %7 Function
  236. %19 = OpVariable %18 Function
  237. %9 = OpLoad %6 %8
  238. %11 = OpLoad %6 %10
  239. %100 = OpCompositeConstruct %17 %80 %80 %26
  240. %104 = OpCompositeConstruct %81 %100 %80
  241. %13 = OpIEqual %12 %9 %11
  242. OpSelectionMerge %15 None
  243. OpBranchConditional %13 %14 %25
  244. %14 = OpLabel
  245. %21 = OpLoad %6 %8
  246. %22 = OpConvertSToF %16 %21
  247. %101 = OpCompositeConstruct %17 %22 %80 %30
  248. %24 = OpAccessChain %23 %19 %20
  249. %204 = OpCompositeExtract %16 %101 0
  250. OpStore %24 %22
  251. OpBranch %15
  252. %25 = OpLabel
  253. %27 = OpLoad %6 %10
  254. %28 = OpConvertSToF %16 %27
  255. %102 = OpCompositeConstruct %17 %80 %28 %27
  256. %203 = OpCompositeExtract %17 %104 0
  257. %29 = OpAccessChain %23 %19 %26
  258. OpStore %29 %28
  259. %205 = OpCompositeExtract %6 %102 2
  260. OpBranch %15
  261. %15 = OpLabel
  262. %31 = OpAccessChain %23 %19 %20
  263. %32 = OpLoad %16 %31
  264. %33 = OpAccessChain %23 %19 %26
  265. %34 = OpLoad %16 %33
  266. %103 = OpCompositeConstruct %17 %34 %32 %9
  267. %35 = OpFAdd %16 %32 %34
  268. %201 = OpCompositeExtract %6 %100 2
  269. %36 = OpConvertFToS %6 %35
  270. %202 = OpCompositeExtract %6 %104 0 2
  271. %37 = OpAccessChain %7 %19 %30
  272. OpStore %37 %36
  273. %206 = OpCompositeExtract %16 %103 1
  274. OpReturn
  275. OpFunctionEnd
  276. )";
  277. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  278. }
  279. TEST(TransformationCompositeExtractTest, IllegalInsertionPoints) {
  280. std::string shader = R"(
  281. OpCapability Shader
  282. %1 = OpExtInstImport "GLSL.std.450"
  283. OpMemoryModel Logical GLSL450
  284. OpEntryPoint Fragment %4 "main" %51 %27
  285. OpExecutionMode %4 OriginUpperLeft
  286. OpSource ESSL 310
  287. OpName %4 "main"
  288. OpName %25 "buf"
  289. OpMemberName %25 0 "value"
  290. OpName %27 ""
  291. OpName %51 "color"
  292. OpMemberDecorate %25 0 Offset 0
  293. OpDecorate %25 Block
  294. OpDecorate %27 DescriptorSet 0
  295. OpDecorate %27 Binding 0
  296. OpDecorate %51 Location 0
  297. %2 = OpTypeVoid
  298. %3 = OpTypeFunction %2
  299. %6 = OpTypeFloat 32
  300. %7 = OpTypeVector %6 4
  301. %10 = OpConstant %6 0.300000012
  302. %11 = OpConstant %6 0.400000006
  303. %12 = OpConstant %6 0.5
  304. %13 = OpConstant %6 1
  305. %14 = OpConstantComposite %7 %10 %11 %12 %13
  306. %15 = OpTypeInt 32 1
  307. %18 = OpConstant %15 0
  308. %25 = OpTypeStruct %6
  309. %26 = OpTypePointer Uniform %25
  310. %27 = OpVariable %26 Uniform
  311. %28 = OpTypePointer Uniform %6
  312. %32 = OpTypeBool
  313. %103 = OpConstantTrue %32
  314. %34 = OpConstant %6 0.100000001
  315. %48 = OpConstant %15 1
  316. %50 = OpTypePointer Output %7
  317. %51 = OpVariable %50 Output
  318. %100 = OpTypePointer Function %6
  319. %4 = OpFunction %2 None %3
  320. %5 = OpLabel
  321. %101 = OpVariable %100 Function
  322. %102 = OpVariable %100 Function
  323. OpBranch %19
  324. %19 = OpLabel
  325. %60 = OpPhi %7 %14 %5 %58 %20
  326. %59 = OpPhi %15 %18 %5 %49 %20
  327. %29 = OpAccessChain %28 %27 %18
  328. %30 = OpLoad %6 %29
  329. %31 = OpConvertFToS %15 %30
  330. %33 = OpSLessThan %32 %59 %31
  331. OpLoopMerge %21 %20 None
  332. OpBranchConditional %33 %20 %21
  333. %20 = OpLabel
  334. %39 = OpCompositeExtract %6 %60 0
  335. %40 = OpFAdd %6 %39 %34
  336. %55 = OpCompositeInsert %7 %40 %60 0
  337. %44 = OpCompositeExtract %6 %60 1
  338. %45 = OpFSub %6 %44 %34
  339. %58 = OpCompositeInsert %7 %45 %55 1
  340. %49 = OpIAdd %15 %59 %48
  341. OpBranch %19
  342. %21 = OpLabel
  343. OpStore %51 %60
  344. OpSelectionMerge %105 None
  345. OpBranchConditional %103 %104 %105
  346. %104 = OpLabel
  347. OpBranch %105
  348. %105 = OpLabel
  349. OpReturn
  350. OpFunctionEnd
  351. )";
  352. const auto env = SPV_ENV_UNIVERSAL_1_4;
  353. const auto consumer = nullptr;
  354. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  355. spvtools::ValidatorOptions validator_options;
  356. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  357. kConsoleMessageConsumer));
  358. TransformationContext transformation_context(
  359. MakeUnique<FactManager>(context.get()), validator_options);
  360. // Cannot insert before the OpVariables of a function.
  361. ASSERT_FALSE(
  362. TransformationCompositeExtract(
  363. MakeInstructionDescriptor(101, spv::Op::OpVariable, 0), 200, 14, {0})
  364. .IsApplicable(context.get(), transformation_context));
  365. ASSERT_FALSE(
  366. TransformationCompositeExtract(
  367. MakeInstructionDescriptor(101, spv::Op::OpVariable, 1), 200, 14, {1})
  368. .IsApplicable(context.get(), transformation_context));
  369. ASSERT_FALSE(
  370. TransformationCompositeExtract(
  371. MakeInstructionDescriptor(102, spv::Op::OpVariable, 0), 200, 14, {1})
  372. .IsApplicable(context.get(), transformation_context));
  373. // OK to insert right after the OpVariables.
  374. ASSERT_FALSE(
  375. TransformationCompositeExtract(
  376. MakeInstructionDescriptor(102, spv::Op::OpBranch, 1), 200, 14, {1})
  377. .IsApplicable(context.get(), transformation_context));
  378. // Cannot insert before the OpPhis of a block.
  379. ASSERT_FALSE(
  380. TransformationCompositeExtract(
  381. MakeInstructionDescriptor(60, spv::Op::OpPhi, 0), 200, 14, {2})
  382. .IsApplicable(context.get(), transformation_context));
  383. ASSERT_FALSE(
  384. TransformationCompositeExtract(
  385. MakeInstructionDescriptor(59, spv::Op::OpPhi, 0), 200, 14, {3})
  386. .IsApplicable(context.get(), transformation_context));
  387. // OK to insert after the OpPhis.
  388. ASSERT_TRUE(TransformationCompositeExtract(
  389. MakeInstructionDescriptor(59, spv::Op::OpAccessChain, 0), 200,
  390. 14, {3})
  391. .IsApplicable(context.get(), transformation_context));
  392. // Cannot insert before OpLoopMerge
  393. ASSERT_FALSE(
  394. TransformationCompositeExtract(
  395. MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0), 200,
  396. 14, {3})
  397. .IsApplicable(context.get(), transformation_context));
  398. // Cannot insert before OpSelectionMerge
  399. ASSERT_FALSE(
  400. TransformationCompositeExtract(
  401. MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0), 200,
  402. 14, {2})
  403. .IsApplicable(context.get(), transformation_context));
  404. }
  405. TEST(TransformationCompositeExtractTest, AddSynonymsForRelevantIds) {
  406. std::string shader = R"(
  407. OpCapability Shader
  408. %1 = OpExtInstImport "GLSL.std.450"
  409. OpMemoryModel Logical GLSL450
  410. OpEntryPoint Fragment %4 "main"
  411. OpExecutionMode %4 OriginUpperLeft
  412. OpSource ESSL 310
  413. OpName %4 "main"
  414. OpName %8 "a"
  415. OpName %10 "b"
  416. OpName %17 "FunnyPoint"
  417. OpMemberName %17 0 "x"
  418. OpMemberName %17 1 "y"
  419. OpMemberName %17 2 "z"
  420. OpName %19 "p"
  421. %2 = OpTypeVoid
  422. %3 = OpTypeFunction %2
  423. %6 = OpTypeInt 32 1
  424. %7 = OpTypePointer Function %6
  425. %12 = OpTypeBool
  426. %16 = OpTypeFloat 32
  427. %17 = OpTypeStruct %16 %16 %6
  428. %81 = OpTypeStruct %17 %16
  429. %18 = OpTypePointer Function %17
  430. %20 = OpConstant %6 0
  431. %23 = OpTypePointer Function %16
  432. %26 = OpConstant %6 1
  433. %30 = OpConstant %6 2
  434. %80 = OpUndef %16
  435. %4 = OpFunction %2 None %3
  436. %5 = OpLabel
  437. %8 = OpVariable %7 Function
  438. %10 = OpVariable %7 Function
  439. %19 = OpVariable %18 Function
  440. %9 = OpLoad %6 %8
  441. %11 = OpLoad %6 %10
  442. %100 = OpCompositeConstruct %17 %80 %80 %26
  443. %104 = OpCompositeConstruct %81 %100 %80
  444. %13 = OpIEqual %12 %9 %11
  445. OpSelectionMerge %15 None
  446. OpBranchConditional %13 %14 %25
  447. %14 = OpLabel
  448. %21 = OpLoad %6 %8
  449. %22 = OpConvertSToF %16 %21
  450. %101 = OpCompositeConstruct %17 %22 %80 %30
  451. %24 = OpAccessChain %23 %19 %20
  452. OpStore %24 %22
  453. OpBranch %15
  454. %25 = OpLabel
  455. %27 = OpLoad %6 %10
  456. %28 = OpConvertSToF %16 %27
  457. %102 = OpCompositeConstruct %17 %80 %28 %27
  458. %29 = OpAccessChain %23 %19 %26
  459. OpStore %29 %28
  460. OpBranch %15
  461. %15 = OpLabel
  462. %31 = OpAccessChain %23 %19 %20
  463. %32 = OpLoad %16 %31
  464. %33 = OpAccessChain %23 %19 %26
  465. %34 = OpLoad %16 %33
  466. %103 = OpCompositeConstruct %17 %34 %32 %9
  467. %35 = OpFAdd %16 %32 %34
  468. %36 = OpConvertFToS %6 %35
  469. %37 = OpAccessChain %7 %19 %30
  470. OpStore %37 %36
  471. OpReturn
  472. OpFunctionEnd
  473. )";
  474. const auto env = SPV_ENV_UNIVERSAL_1_4;
  475. const auto consumer = nullptr;
  476. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  477. spvtools::ValidatorOptions validator_options;
  478. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  479. kConsoleMessageConsumer));
  480. TransformationContext transformation_context(
  481. MakeUnique<FactManager>(context.get()), validator_options);
  482. TransformationCompositeExtract transformation(
  483. MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
  484. ASSERT_TRUE(
  485. transformation.IsApplicable(context.get(), transformation_context));
  486. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  487. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  488. MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
  489. }
  490. TEST(TransformationCompositeExtractTest, DontAddSynonymsForIrrelevantIds) {
  491. std::string shader = R"(
  492. OpCapability Shader
  493. %1 = OpExtInstImport "GLSL.std.450"
  494. OpMemoryModel Logical GLSL450
  495. OpEntryPoint Fragment %4 "main"
  496. OpExecutionMode %4 OriginUpperLeft
  497. OpSource ESSL 310
  498. OpName %4 "main"
  499. OpName %8 "a"
  500. OpName %10 "b"
  501. OpName %17 "FunnyPoint"
  502. OpMemberName %17 0 "x"
  503. OpMemberName %17 1 "y"
  504. OpMemberName %17 2 "z"
  505. OpName %19 "p"
  506. %2 = OpTypeVoid
  507. %3 = OpTypeFunction %2
  508. %6 = OpTypeInt 32 1
  509. %7 = OpTypePointer Function %6
  510. %12 = OpTypeBool
  511. %16 = OpTypeFloat 32
  512. %17 = OpTypeStruct %16 %16 %6
  513. %81 = OpTypeStruct %17 %16
  514. %18 = OpTypePointer Function %17
  515. %20 = OpConstant %6 0
  516. %23 = OpTypePointer Function %16
  517. %26 = OpConstant %6 1
  518. %30 = OpConstant %6 2
  519. %80 = OpUndef %16
  520. %4 = OpFunction %2 None %3
  521. %5 = OpLabel
  522. %8 = OpVariable %7 Function
  523. %10 = OpVariable %7 Function
  524. %19 = OpVariable %18 Function
  525. %9 = OpLoad %6 %8
  526. %11 = OpLoad %6 %10
  527. %100 = OpCompositeConstruct %17 %80 %80 %26
  528. %104 = OpCompositeConstruct %81 %100 %80
  529. %13 = OpIEqual %12 %9 %11
  530. OpSelectionMerge %15 None
  531. OpBranchConditional %13 %14 %25
  532. %14 = OpLabel
  533. %21 = OpLoad %6 %8
  534. %22 = OpConvertSToF %16 %21
  535. %101 = OpCompositeConstruct %17 %22 %80 %30
  536. %24 = OpAccessChain %23 %19 %20
  537. OpStore %24 %22
  538. OpBranch %15
  539. %25 = OpLabel
  540. %27 = OpLoad %6 %10
  541. %28 = OpConvertSToF %16 %27
  542. %102 = OpCompositeConstruct %17 %80 %28 %27
  543. %29 = OpAccessChain %23 %19 %26
  544. OpStore %29 %28
  545. OpBranch %15
  546. %15 = OpLabel
  547. %31 = OpAccessChain %23 %19 %20
  548. %32 = OpLoad %16 %31
  549. %33 = OpAccessChain %23 %19 %26
  550. %34 = OpLoad %16 %33
  551. %103 = OpCompositeConstruct %17 %34 %32 %9
  552. %35 = OpFAdd %16 %32 %34
  553. %36 = OpConvertFToS %6 %35
  554. %37 = OpAccessChain %7 %19 %30
  555. OpStore %37 %36
  556. OpReturn
  557. OpFunctionEnd
  558. )";
  559. const auto env = SPV_ENV_UNIVERSAL_1_4;
  560. const auto consumer = nullptr;
  561. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  562. spvtools::ValidatorOptions validator_options;
  563. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  564. kConsoleMessageConsumer));
  565. TransformationContext transformation_context(
  566. MakeUnique<FactManager>(context.get()), validator_options);
  567. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(100);
  568. TransformationCompositeExtract transformation(
  569. MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
  570. ASSERT_TRUE(
  571. transformation.IsApplicable(context.get(), transformation_context));
  572. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  573. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  574. MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
  575. }
  576. TEST(TransformationCompositeExtractTest, DontAddSynonymInDeadBlock) {
  577. std::string shader = R"(
  578. OpCapability Shader
  579. %1 = OpExtInstImport "GLSL.std.450"
  580. OpMemoryModel Logical GLSL450
  581. OpEntryPoint Fragment %4 "main"
  582. OpExecutionMode %4 OriginUpperLeft
  583. OpSource ESSL 320
  584. %2 = OpTypeVoid
  585. %3 = OpTypeFunction %2
  586. %6 = OpTypeInt 32 1
  587. %7 = OpTypeVector %6 2
  588. %8 = OpTypePointer Function %7
  589. %10 = OpConstant %6 0
  590. %11 = OpConstant %6 1
  591. %12 = OpConstantComposite %7 %10 %11
  592. %13 = OpTypeBool
  593. %14 = OpConstantFalse %13
  594. %4 = OpFunction %2 None %3
  595. %5 = OpLabel
  596. %9 = OpVariable %8 Function
  597. OpStore %9 %12
  598. OpSelectionMerge %16 None
  599. OpBranchConditional %14 %15 %16
  600. %15 = OpLabel
  601. OpBranch %16
  602. %16 = OpLabel
  603. OpReturn
  604. OpFunctionEnd
  605. )";
  606. const auto env = SPV_ENV_UNIVERSAL_1_4;
  607. const auto consumer = nullptr;
  608. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  609. spvtools::ValidatorOptions validator_options;
  610. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  611. kConsoleMessageConsumer));
  612. TransformationContext transformation_context(
  613. MakeUnique<FactManager>(context.get()), validator_options);
  614. transformation_context.GetFactManager()->AddFactBlockIsDead(15);
  615. TransformationCompositeExtract transformation(
  616. MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 100, 12, {0});
  617. ASSERT_TRUE(
  618. transformation.IsApplicable(context.get(), transformation_context));
  619. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  620. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  621. MakeDataDescriptor(100, {}), MakeDataDescriptor(12, {0})));
  622. }
  623. } // namespace
  624. } // namespace fuzz
  625. } // namespace spvtools