transformation_flatten_conditional_branch_test.cpp 79 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207
  1. // Copyright (c) 2020 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_flatten_conditional_branch.h"
  15. #include "gtest/gtest.h"
  16. #include "source/fuzz/counter_overflow_id_source.h"
  17. #include "source/fuzz/fuzzer_util.h"
  18. #include "source/fuzz/instruction_descriptor.h"
  19. #include "test/fuzz/fuzz_test_util.h"
  20. namespace spvtools {
  21. namespace fuzz {
  22. namespace {
  23. protobufs::SideEffectWrapperInfo MakeSideEffectWrapperInfo(
  24. const protobufs::InstructionDescriptor& instruction,
  25. uint32_t merge_block_id, uint32_t execute_block_id,
  26. uint32_t actual_result_id, uint32_t alternative_block_id,
  27. uint32_t placeholder_result_id, uint32_t value_to_copy_id) {
  28. protobufs::SideEffectWrapperInfo result;
  29. *result.mutable_instruction() = instruction;
  30. result.set_merge_block_id(merge_block_id);
  31. result.set_execute_block_id(execute_block_id);
  32. result.set_actual_result_id(actual_result_id);
  33. result.set_alternative_block_id(alternative_block_id);
  34. result.set_placeholder_result_id(placeholder_result_id);
  35. result.set_value_to_copy_id(value_to_copy_id);
  36. return result;
  37. }
  38. protobufs::SideEffectWrapperInfo MakeSideEffectWrapperInfo(
  39. const protobufs::InstructionDescriptor& instruction,
  40. uint32_t merge_block_id, uint32_t execute_block_id) {
  41. return MakeSideEffectWrapperInfo(instruction, merge_block_id,
  42. execute_block_id, 0, 0, 0, 0);
  43. }
  44. TEST(TransformationFlattenConditionalBranchTest, Inapplicable) {
  45. std::string shader = R"(
  46. OpCapability Shader
  47. %1 = OpExtInstImport "GLSL.std.450"
  48. OpMemoryModel Logical GLSL450
  49. OpEntryPoint Fragment %2 "main" %3
  50. OpExecutionMode %2 OriginUpperLeft
  51. OpSource ESSL 310
  52. OpName %2 "main"
  53. %4 = OpTypeVoid
  54. %5 = OpTypeFunction %4
  55. %6 = OpTypeInt 32 1
  56. %7 = OpTypeInt 32 0
  57. %8 = OpConstant %7 0
  58. %9 = OpTypeBool
  59. %10 = OpConstantTrue %9
  60. %11 = OpTypePointer Function %6
  61. %12 = OpTypePointer Workgroup %6
  62. %3 = OpVariable %12 Workgroup
  63. %13 = OpConstant %6 2
  64. %2 = OpFunction %4 None %5
  65. %14 = OpLabel
  66. OpBranch %15
  67. %15 = OpLabel
  68. OpSelectionMerge %16 None
  69. OpSwitch %13 %17 2 %18
  70. %17 = OpLabel
  71. OpBranch %16
  72. %18 = OpLabel
  73. OpBranch %16
  74. %16 = OpLabel
  75. OpLoopMerge %19 %16 None
  76. OpBranchConditional %10 %16 %19
  77. %19 = OpLabel
  78. OpSelectionMerge %20 None
  79. OpBranchConditional %10 %21 %20
  80. %21 = OpLabel
  81. OpReturn
  82. %20 = OpLabel
  83. OpSelectionMerge %22 None
  84. OpBranchConditional %10 %23 %22
  85. %23 = OpLabel
  86. OpSelectionMerge %24 None
  87. OpBranchConditional %10 %25 %24
  88. %25 = OpLabel
  89. OpBranch %24
  90. %24 = OpLabel
  91. OpBranch %22
  92. %22 = OpLabel
  93. OpSelectionMerge %26 None
  94. OpBranchConditional %10 %26 %27
  95. %27 = OpLabel
  96. OpBranch %28
  97. %28 = OpLabel
  98. OpLoopMerge %29 %28 None
  99. OpBranchConditional %10 %28 %29
  100. %29 = OpLabel
  101. OpBranch %26
  102. %26 = OpLabel
  103. OpSelectionMerge %30 None
  104. OpBranchConditional %10 %30 %31
  105. %31 = OpLabel
  106. OpBranch %32
  107. %32 = OpLabel
  108. %33 = OpAtomicLoad %6 %3 %8 %8
  109. OpBranch %30
  110. %30 = OpLabel
  111. OpSelectionMerge %34 None
  112. OpBranchConditional %10 %35 %34
  113. %35 = OpLabel
  114. OpMemoryBarrier %8 %8
  115. OpBranch %34
  116. %34 = OpLabel
  117. OpLoopMerge %40 %39 None
  118. OpBranchConditional %10 %36 %40
  119. %36 = OpLabel
  120. OpSelectionMerge %38 None
  121. OpBranchConditional %10 %37 %38
  122. %37 = OpLabel
  123. OpBranch %40
  124. %38 = OpLabel
  125. OpBranch %39
  126. %39 = OpLabel
  127. OpBranch %34
  128. %40 = OpLabel
  129. OpReturn
  130. OpFunctionEnd
  131. )";
  132. const auto env = SPV_ENV_UNIVERSAL_1_5;
  133. const auto consumer = nullptr;
  134. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  135. spvtools::ValidatorOptions validator_options;
  136. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  137. kConsoleMessageConsumer));
  138. TransformationContext transformation_context(
  139. MakeUnique<FactManager>(context.get()), validator_options);
  140. // Block %15 does not end with OpBranchConditional.
  141. ASSERT_FALSE(TransformationFlattenConditionalBranch(15, true, 0, 0, 0, {})
  142. .IsApplicable(context.get(), transformation_context));
  143. // Block %17 is not a selection header.
  144. ASSERT_FALSE(TransformationFlattenConditionalBranch(17, true, 0, 0, 0, {})
  145. .IsApplicable(context.get(), transformation_context));
  146. // Block %16 is a loop header, not a selection header.
  147. ASSERT_FALSE(TransformationFlattenConditionalBranch(16, true, 0, 0, 0, {})
  148. .IsApplicable(context.get(), transformation_context));
  149. // Block %19 and the corresponding merge block do not describe a single-entry,
  150. // single-exit region, because there is a return instruction in %21.
  151. ASSERT_FALSE(TransformationFlattenConditionalBranch(19, true, 0, 0, 0, {})
  152. .IsApplicable(context.get(), transformation_context));
  153. // Block %20 is the header of a construct containing an inner selection
  154. // construct.
  155. ASSERT_FALSE(TransformationFlattenConditionalBranch(20, true, 0, 0, 0, {})
  156. .IsApplicable(context.get(), transformation_context));
  157. // Block %22 is the header of a construct containing an inner loop.
  158. ASSERT_FALSE(TransformationFlattenConditionalBranch(22, true, 0, 0, 0, {})
  159. .IsApplicable(context.get(), transformation_context));
  160. // Block %30 is the header of a construct containing a barrier instruction.
  161. ASSERT_FALSE(TransformationFlattenConditionalBranch(30, true, 0, 0, 0, {})
  162. .IsApplicable(context.get(), transformation_context));
  163. // %33 is not a block.
  164. ASSERT_FALSE(TransformationFlattenConditionalBranch(33, true, 0, 0, 0, {})
  165. .IsApplicable(context.get(), transformation_context));
  166. // Block %36 and the corresponding merge block do not describe a single-entry,
  167. // single-exit region, because block %37 breaks out of the outer loop.
  168. ASSERT_FALSE(TransformationFlattenConditionalBranch(36, true, 0, 0, 0, {})
  169. .IsApplicable(context.get(), transformation_context));
  170. }
  171. TEST(TransformationFlattenConditionalBranchTest, Simple) {
  172. std::string shader = R"(
  173. OpCapability Shader
  174. %1 = OpExtInstImport "GLSL.std.450"
  175. OpMemoryModel Logical GLSL450
  176. OpEntryPoint Fragment %2 "main"
  177. OpExecutionMode %2 OriginUpperLeft
  178. OpSource ESSL 310
  179. OpName %2 "main"
  180. %3 = OpTypeBool
  181. %4 = OpConstantTrue %3
  182. %5 = OpTypeVoid
  183. %6 = OpTypeFunction %5
  184. %2 = OpFunction %5 None %6
  185. %7 = OpLabel
  186. OpSelectionMerge %8 None
  187. OpBranchConditional %4 %9 %10
  188. %10 = OpLabel
  189. %26 = OpPhi %3 %4 %7
  190. OpBranch %8
  191. %9 = OpLabel
  192. %27 = OpPhi %3 %4 %7
  193. %11 = OpCopyObject %3 %4
  194. OpBranch %8
  195. %8 = OpLabel
  196. %12 = OpPhi %3 %11 %9 %4 %10
  197. %23 = OpPhi %3 %4 %9 %4 %10
  198. OpBranch %13
  199. %13 = OpLabel
  200. %14 = OpCopyObject %3 %4
  201. OpSelectionMerge %15 None
  202. OpBranchConditional %4 %16 %17
  203. %16 = OpLabel
  204. %28 = OpPhi %3 %4 %13
  205. OpBranch %18
  206. %18 = OpLabel
  207. OpBranch %19
  208. %17 = OpLabel
  209. %29 = OpPhi %3 %4 %13
  210. %20 = OpCopyObject %3 %4
  211. OpBranch %19
  212. %19 = OpLabel
  213. %21 = OpPhi %3 %4 %18 %20 %17
  214. OpBranch %15
  215. %15 = OpLabel
  216. OpSelectionMerge %22 None
  217. OpBranchConditional %4 %22 %22
  218. %22 = OpLabel
  219. %30 = OpPhi %3 %4 %15
  220. OpSelectionMerge %25 None
  221. OpBranchConditional %4 %24 %24
  222. %24 = OpLabel
  223. OpBranch %25
  224. %25 = OpLabel
  225. OpReturn
  226. OpFunctionEnd
  227. )";
  228. const auto env = SPV_ENV_UNIVERSAL_1_5;
  229. const auto consumer = nullptr;
  230. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  231. spvtools::ValidatorOptions validator_options;
  232. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  233. kConsoleMessageConsumer));
  234. TransformationContext transformation_context(
  235. MakeUnique<FactManager>(context.get()), validator_options);
  236. auto transformation1 =
  237. TransformationFlattenConditionalBranch(7, true, 0, 0, 0, {});
  238. ASSERT_TRUE(
  239. transformation1.IsApplicable(context.get(), transformation_context));
  240. ApplyAndCheckFreshIds(transformation1, context.get(),
  241. &transformation_context);
  242. auto transformation2 =
  243. TransformationFlattenConditionalBranch(13, false, 0, 0, 0, {});
  244. ASSERT_TRUE(
  245. transformation2.IsApplicable(context.get(), transformation_context));
  246. ApplyAndCheckFreshIds(transformation2, context.get(),
  247. &transformation_context);
  248. auto transformation3 =
  249. TransformationFlattenConditionalBranch(15, true, 0, 0, 0, {});
  250. ASSERT_TRUE(
  251. transformation3.IsApplicable(context.get(), transformation_context));
  252. ApplyAndCheckFreshIds(transformation3, context.get(),
  253. &transformation_context);
  254. auto transformation4 =
  255. TransformationFlattenConditionalBranch(22, false, 0, 0, 0, {});
  256. ASSERT_TRUE(
  257. transformation4.IsApplicable(context.get(), transformation_context));
  258. ApplyAndCheckFreshIds(transformation4, context.get(),
  259. &transformation_context);
  260. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  261. kConsoleMessageConsumer));
  262. std::string after_transformations = R"(
  263. OpCapability Shader
  264. %1 = OpExtInstImport "GLSL.std.450"
  265. OpMemoryModel Logical GLSL450
  266. OpEntryPoint Fragment %2 "main"
  267. OpExecutionMode %2 OriginUpperLeft
  268. OpSource ESSL 310
  269. OpName %2 "main"
  270. %3 = OpTypeBool
  271. %4 = OpConstantTrue %3
  272. %5 = OpTypeVoid
  273. %6 = OpTypeFunction %5
  274. %2 = OpFunction %5 None %6
  275. %7 = OpLabel
  276. OpBranch %9
  277. %9 = OpLabel
  278. %27 = OpPhi %3 %4 %7
  279. %11 = OpCopyObject %3 %4
  280. OpBranch %10
  281. %10 = OpLabel
  282. %26 = OpPhi %3 %4 %9
  283. OpBranch %8
  284. %8 = OpLabel
  285. %12 = OpSelect %3 %4 %11 %4
  286. %23 = OpSelect %3 %4 %4 %4
  287. OpBranch %13
  288. %13 = OpLabel
  289. %14 = OpCopyObject %3 %4
  290. OpBranch %17
  291. %17 = OpLabel
  292. %29 = OpPhi %3 %4 %13
  293. %20 = OpCopyObject %3 %4
  294. OpBranch %16
  295. %16 = OpLabel
  296. %28 = OpPhi %3 %4 %17
  297. OpBranch %18
  298. %18 = OpLabel
  299. OpBranch %19
  300. %19 = OpLabel
  301. %21 = OpSelect %3 %4 %4 %20
  302. OpBranch %15
  303. %15 = OpLabel
  304. OpBranch %22
  305. %22 = OpLabel
  306. %30 = OpPhi %3 %4 %15
  307. OpBranch %24
  308. %24 = OpLabel
  309. OpBranch %25
  310. %25 = OpLabel
  311. OpReturn
  312. OpFunctionEnd
  313. )";
  314. ASSERT_TRUE(IsEqual(env, after_transformations, context.get()));
  315. }
  316. TEST(TransformationFlattenConditionalBranchTest, LoadStoreFunctionCall) {
  317. std::string shader = R"(
  318. OpCapability Shader
  319. %1 = OpExtInstImport "GLSL.std.450"
  320. OpMemoryModel Logical GLSL450
  321. OpEntryPoint Fragment %2 "main"
  322. OpExecutionMode %2 OriginUpperLeft
  323. OpSource ESSL 310
  324. %9 = OpTypeVoid
  325. %10 = OpTypeFunction %9
  326. %11 = OpTypeInt 32 1
  327. %12 = OpTypeVector %11 4
  328. %13 = OpTypeFunction %11
  329. %70 = OpConstant %11 0
  330. %14 = OpConstant %11 1
  331. %15 = OpTypeFloat 32
  332. %16 = OpTypeVector %15 2
  333. %17 = OpConstant %15 1
  334. %18 = OpConstantComposite %16 %17 %17
  335. %19 = OpTypeBool
  336. %20 = OpConstantTrue %19
  337. %21 = OpTypePointer Function %11
  338. %22 = OpTypeSampler
  339. %23 = OpTypeImage %9 2D 2 0 0 1 Unknown
  340. %24 = OpTypeSampledImage %23
  341. %25 = OpTypePointer Function %23
  342. %26 = OpTypePointer Function %22
  343. %27 = OpTypeInt 32 0
  344. %28 = OpConstant %27 2
  345. %29 = OpTypeArray %11 %28
  346. %30 = OpTypePointer Function %29
  347. %2 = OpFunction %9 None %10
  348. %31 = OpLabel
  349. %4 = OpVariable %21 Function
  350. %5 = OpVariable %30 Function
  351. %32 = OpVariable %25 Function
  352. %33 = OpVariable %26 Function
  353. %34 = OpLoad %23 %32
  354. %35 = OpLoad %22 %33
  355. OpSelectionMerge %36 None
  356. OpBranchConditional %20 %37 %36
  357. %37 = OpLabel
  358. %6 = OpLoad %11 %4
  359. %7 = OpIAdd %11 %6 %14
  360. OpStore %4 %7
  361. OpBranch %36
  362. %36 = OpLabel
  363. %42 = OpPhi %11 %14 %37 %14 %31
  364. OpSelectionMerge %43 None
  365. OpBranchConditional %20 %44 %45
  366. %44 = OpLabel
  367. %8 = OpFunctionCall %11 %3
  368. OpStore %4 %8
  369. OpBranch %46
  370. %45 = OpLabel
  371. %47 = OpAccessChain %21 %5 %14
  372. OpStore %47 %14
  373. OpBranch %46
  374. %46 = OpLabel
  375. OpStore %4 %14
  376. OpBranch %43
  377. %43 = OpLabel
  378. OpStore %4 %14
  379. OpSelectionMerge %48 None
  380. OpBranchConditional %20 %49 %48
  381. %49 = OpLabel
  382. OpBranch %48
  383. %48 = OpLabel
  384. OpSelectionMerge %50 None
  385. OpBranchConditional %20 %51 %50
  386. %51 = OpLabel
  387. %52 = OpSampledImage %24 %34 %35
  388. %53 = OpLoad %11 %4
  389. %54 = OpImageSampleImplicitLod %12 %52 %18
  390. OpBranch %50
  391. %50 = OpLabel
  392. OpReturn
  393. OpFunctionEnd
  394. %3 = OpFunction %11 None %13
  395. %55 = OpLabel
  396. OpReturnValue %14
  397. OpFunctionEnd
  398. )";
  399. const auto env = SPV_ENV_UNIVERSAL_1_5;
  400. const auto consumer = nullptr;
  401. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  402. spvtools::ValidatorOptions validator_options;
  403. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  404. kConsoleMessageConsumer));
  405. TransformationContext transformation_context(
  406. MakeUnique<FactManager>(context.get()), validator_options);
  407. #ifndef NDEBUG
  408. // The following checks lead to assertion failures, since some entries
  409. // requiring fresh ids are not present in the map, and the transformation
  410. // context does not have a source overflow ids.
  411. ASSERT_DEATH(TransformationFlattenConditionalBranch(31, true, 0, 0, 0, {})
  412. .IsApplicable(context.get(), transformation_context),
  413. "Bad attempt to query whether overflow ids are available.");
  414. ASSERT_DEATH(TransformationFlattenConditionalBranch(
  415. 31, true, 0, 0, 0,
  416. {{MakeSideEffectWrapperInfo(
  417. MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 100,
  418. 101, 102, 103, 104, 14)}})
  419. .IsApplicable(context.get(), transformation_context),
  420. "Bad attempt to query whether overflow ids are available.");
  421. #endif
  422. // The map maps from an instruction to a list with not enough fresh ids.
  423. ASSERT_FALSE(TransformationFlattenConditionalBranch(
  424. 31, true, 0, 0, 0,
  425. {{MakeSideEffectWrapperInfo(
  426. MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 100,
  427. 101, 102, 103, 0, 0)}})
  428. .IsApplicable(context.get(), transformation_context));
  429. // Not all fresh ids given are distinct.
  430. ASSERT_FALSE(TransformationFlattenConditionalBranch(
  431. 31, true, 0, 0, 0,
  432. {{MakeSideEffectWrapperInfo(
  433. MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 100,
  434. 100, 102, 103, 104, 0)}})
  435. .IsApplicable(context.get(), transformation_context));
  436. // %48 heads a construct containing an OpSampledImage instruction.
  437. ASSERT_FALSE(TransformationFlattenConditionalBranch(
  438. 48, true, 0, 0, 0,
  439. {{MakeSideEffectWrapperInfo(
  440. MakeInstructionDescriptor(53, spv::Op::OpLoad, 0), 100,
  441. 101, 102, 103, 104, 0)}})
  442. .IsApplicable(context.get(), transformation_context));
  443. // %0 is not a valid id.
  444. ASSERT_FALSE(
  445. TransformationFlattenConditionalBranch(
  446. 31, true, 0, 0, 0,
  447. {MakeSideEffectWrapperInfo(
  448. MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 104, 100, 101,
  449. 102, 103, 0),
  450. MakeSideEffectWrapperInfo(
  451. MakeInstructionDescriptor(6, spv::Op::OpStore, 0), 106, 105)})
  452. .IsApplicable(context.get(), transformation_context));
  453. // %17 is a float constant, while %6 has int type.
  454. ASSERT_FALSE(
  455. TransformationFlattenConditionalBranch(
  456. 31, true, 0, 0, 0,
  457. {MakeSideEffectWrapperInfo(
  458. MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 104, 100, 101,
  459. 102, 103, 17),
  460. MakeSideEffectWrapperInfo(
  461. MakeInstructionDescriptor(6, spv::Op::OpStore, 0), 106, 105)})
  462. .IsApplicable(context.get(), transformation_context));
  463. auto transformation1 = TransformationFlattenConditionalBranch(
  464. 31, true, 0, 0, 0,
  465. {MakeSideEffectWrapperInfo(
  466. MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 104, 100, 101, 102,
  467. 103, 70),
  468. MakeSideEffectWrapperInfo(
  469. MakeInstructionDescriptor(6, spv::Op::OpStore, 0), 106, 105)});
  470. ASSERT_TRUE(
  471. transformation1.IsApplicable(context.get(), transformation_context));
  472. ApplyAndCheckFreshIds(transformation1, context.get(),
  473. &transformation_context);
  474. // Check that the placeholder id was marked as irrelevant.
  475. ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(103));
  476. // Make a new transformation context with a source of overflow ids.
  477. auto overflow_ids_unique_ptr = MakeUnique<CounterOverflowIdSource>(1000);
  478. auto overflow_ids_ptr = overflow_ids_unique_ptr.get();
  479. TransformationContext new_transformation_context(
  480. MakeUnique<FactManager>(context.get()), validator_options,
  481. std::move(overflow_ids_unique_ptr));
  482. auto transformation2 = TransformationFlattenConditionalBranch(
  483. 36, false, 0, 0, 0,
  484. {MakeSideEffectWrapperInfo(
  485. MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 114, 113)});
  486. ASSERT_TRUE(
  487. transformation2.IsApplicable(context.get(), new_transformation_context));
  488. ApplyAndCheckFreshIds(transformation2, context.get(),
  489. &new_transformation_context,
  490. overflow_ids_ptr->GetIssuedOverflowIds());
  491. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  492. kConsoleMessageConsumer));
  493. std::string after_transformations = R"(
  494. OpCapability Shader
  495. %1 = OpExtInstImport "GLSL.std.450"
  496. OpMemoryModel Logical GLSL450
  497. OpEntryPoint Fragment %2 "main"
  498. OpExecutionMode %2 OriginUpperLeft
  499. OpSource ESSL 310
  500. %9 = OpTypeVoid
  501. %10 = OpTypeFunction %9
  502. %11 = OpTypeInt 32 1
  503. %12 = OpTypeVector %11 4
  504. %13 = OpTypeFunction %11
  505. %70 = OpConstant %11 0
  506. %14 = OpConstant %11 1
  507. %15 = OpTypeFloat 32
  508. %16 = OpTypeVector %15 2
  509. %17 = OpConstant %15 1
  510. %18 = OpConstantComposite %16 %17 %17
  511. %19 = OpTypeBool
  512. %20 = OpConstantTrue %19
  513. %21 = OpTypePointer Function %11
  514. %22 = OpTypeSampler
  515. %23 = OpTypeImage %9 2D 2 0 0 1 Unknown
  516. %24 = OpTypeSampledImage %23
  517. %25 = OpTypePointer Function %23
  518. %26 = OpTypePointer Function %22
  519. %27 = OpTypeInt 32 0
  520. %28 = OpConstant %27 2
  521. %29 = OpTypeArray %11 %28
  522. %30 = OpTypePointer Function %29
  523. %2 = OpFunction %9 None %10
  524. %31 = OpLabel
  525. %4 = OpVariable %21 Function
  526. %5 = OpVariable %30 Function
  527. %32 = OpVariable %25 Function
  528. %33 = OpVariable %26 Function
  529. %34 = OpLoad %23 %32
  530. %35 = OpLoad %22 %33
  531. OpBranch %37
  532. %37 = OpLabel
  533. OpSelectionMerge %104 None
  534. OpBranchConditional %20 %100 %102
  535. %100 = OpLabel
  536. %101 = OpLoad %11 %4
  537. OpBranch %104
  538. %102 = OpLabel
  539. %103 = OpCopyObject %11 %70
  540. OpBranch %104
  541. %104 = OpLabel
  542. %6 = OpPhi %11 %101 %100 %103 %102
  543. %7 = OpIAdd %11 %6 %14
  544. OpSelectionMerge %106 None
  545. OpBranchConditional %20 %105 %106
  546. %105 = OpLabel
  547. OpStore %4 %7
  548. OpBranch %106
  549. %106 = OpLabel
  550. OpBranch %36
  551. %36 = OpLabel
  552. %42 = OpSelect %11 %20 %14 %14
  553. OpBranch %45
  554. %45 = OpLabel
  555. %47 = OpAccessChain %21 %5 %14
  556. OpSelectionMerge %1005 None
  557. OpBranchConditional %20 %1005 %1006
  558. %1006 = OpLabel
  559. OpStore %47 %14
  560. OpBranch %1005
  561. %1005 = OpLabel
  562. OpBranch %44
  563. %44 = OpLabel
  564. OpSelectionMerge %1000 None
  565. OpBranchConditional %20 %1001 %1003
  566. %1001 = OpLabel
  567. %1002 = OpFunctionCall %11 %3
  568. OpBranch %1000
  569. %1003 = OpLabel
  570. %1004 = OpCopyObject %11 %70
  571. OpBranch %1000
  572. %1000 = OpLabel
  573. %8 = OpPhi %11 %1002 %1001 %1004 %1003
  574. OpSelectionMerge %114 None
  575. OpBranchConditional %20 %113 %114
  576. %113 = OpLabel
  577. OpStore %4 %8
  578. OpBranch %114
  579. %114 = OpLabel
  580. OpBranch %46
  581. %46 = OpLabel
  582. OpStore %4 %14
  583. OpBranch %43
  584. %43 = OpLabel
  585. OpStore %4 %14
  586. OpSelectionMerge %48 None
  587. OpBranchConditional %20 %49 %48
  588. %49 = OpLabel
  589. OpBranch %48
  590. %48 = OpLabel
  591. OpSelectionMerge %50 None
  592. OpBranchConditional %20 %51 %50
  593. %51 = OpLabel
  594. %52 = OpSampledImage %24 %34 %35
  595. %53 = OpLoad %11 %4
  596. %54 = OpImageSampleImplicitLod %12 %52 %18
  597. OpBranch %50
  598. %50 = OpLabel
  599. OpReturn
  600. OpFunctionEnd
  601. %3 = OpFunction %11 None %13
  602. %55 = OpLabel
  603. OpReturnValue %14
  604. OpFunctionEnd
  605. )";
  606. ASSERT_TRUE(IsEqual(env, after_transformations, context.get()));
  607. } // namespace
  608. TEST(TransformationFlattenConditionalBranchTest, EdgeCases) {
  609. std::string shader = R"(
  610. OpCapability Shader
  611. %1 = OpExtInstImport "GLSL.std.450"
  612. OpMemoryModel Logical GLSL450
  613. OpEntryPoint Fragment %2 "main"
  614. OpExecutionMode %2 OriginUpperLeft
  615. OpSource ESSL 310
  616. %3 = OpTypeVoid
  617. %4 = OpTypeBool
  618. %5 = OpConstantTrue %4
  619. %6 = OpTypeFunction %3
  620. %2 = OpFunction %3 None %6
  621. %7 = OpLabel
  622. OpSelectionMerge %8 None
  623. OpBranchConditional %5 %9 %8
  624. %9 = OpLabel
  625. %10 = OpFunctionCall %3 %11
  626. OpBranch %8
  627. %8 = OpLabel
  628. OpSelectionMerge %12 None
  629. OpBranchConditional %5 %13 %12
  630. %13 = OpLabel
  631. %14 = OpFunctionCall %3 %11
  632. OpBranch %12
  633. %12 = OpLabel
  634. OpReturn
  635. %16 = OpLabel
  636. OpSelectionMerge %17 None
  637. OpBranchConditional %5 %18 %17
  638. %18 = OpLabel
  639. OpBranch %17
  640. %17 = OpLabel
  641. OpReturn
  642. OpFunctionEnd
  643. %11 = OpFunction %3 None %6
  644. %19 = OpLabel
  645. OpBranch %20
  646. %20 = OpLabel
  647. OpSelectionMerge %25 None
  648. OpBranchConditional %5 %21 %22
  649. %21 = OpLabel
  650. OpBranch %22
  651. %22 = OpLabel
  652. OpSelectionMerge %24 None
  653. OpBranchConditional %5 %24 %23
  654. %23 = OpLabel
  655. OpBranch %24
  656. %24 = OpLabel
  657. OpBranch %25
  658. %25 = OpLabel
  659. OpReturn
  660. OpFunctionEnd
  661. )";
  662. const auto env = SPV_ENV_UNIVERSAL_1_5;
  663. const auto consumer = nullptr;
  664. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  665. spvtools::ValidatorOptions validator_options;
  666. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  667. kConsoleMessageConsumer));
  668. TransformationContext transformation_context(
  669. MakeUnique<FactManager>(context.get()), validator_options);
  670. #ifndef NDEBUG
  671. // The selection construct headed by %7 requires fresh ids because it contains
  672. // a function call. This causes an assertion failure because transformation
  673. // context does not have a source of overflow ids.
  674. ASSERT_DEATH(TransformationFlattenConditionalBranch(7, true, 0, 0, 0, {})
  675. .IsApplicable(context.get(), transformation_context),
  676. "Bad attempt to query whether overflow ids are available.");
  677. #endif
  678. auto transformation1 = TransformationFlattenConditionalBranch(
  679. 7, true, 0, 0, 0,
  680. {{MakeSideEffectWrapperInfo(
  681. MakeInstructionDescriptor(10, spv::Op::OpFunctionCall, 0), 100,
  682. 101)}});
  683. ASSERT_TRUE(
  684. transformation1.IsApplicable(context.get(), transformation_context));
  685. ApplyAndCheckFreshIds(transformation1, context.get(),
  686. &transformation_context);
  687. // The selection construct headed by %8 cannot be flattened because it
  688. // contains a function call returning void, whose result id is used.
  689. ASSERT_FALSE(
  690. TransformationFlattenConditionalBranch(
  691. 7, true, 0, 0, 0,
  692. {{MakeSideEffectWrapperInfo(
  693. MakeInstructionDescriptor(14, spv::Op::OpFunctionCall, 0), 102,
  694. 103)}})
  695. .IsApplicable(context.get(), transformation_context));
  696. // Block %16 is unreachable.
  697. ASSERT_FALSE(TransformationFlattenConditionalBranch(16, true, 0, 0, 0, {})
  698. .IsApplicable(context.get(), transformation_context));
  699. auto transformation2 =
  700. TransformationFlattenConditionalBranch(20, false, 0, 0, 0, {});
  701. ASSERT_TRUE(
  702. transformation2.IsApplicable(context.get(), transformation_context));
  703. ApplyAndCheckFreshIds(transformation2, context.get(),
  704. &transformation_context);
  705. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  706. kConsoleMessageConsumer));
  707. std::string after_transformation = R"(
  708. OpCapability Shader
  709. %1 = OpExtInstImport "GLSL.std.450"
  710. OpMemoryModel Logical GLSL450
  711. OpEntryPoint Fragment %2 "main"
  712. OpExecutionMode %2 OriginUpperLeft
  713. OpSource ESSL 310
  714. %3 = OpTypeVoid
  715. %4 = OpTypeBool
  716. %5 = OpConstantTrue %4
  717. %6 = OpTypeFunction %3
  718. %2 = OpFunction %3 None %6
  719. %7 = OpLabel
  720. OpBranch %9
  721. %9 = OpLabel
  722. OpSelectionMerge %100 None
  723. OpBranchConditional %5 %101 %100
  724. %101 = OpLabel
  725. %10 = OpFunctionCall %3 %11
  726. OpBranch %100
  727. %100 = OpLabel
  728. OpBranch %8
  729. %8 = OpLabel
  730. OpSelectionMerge %12 None
  731. OpBranchConditional %5 %13 %12
  732. %13 = OpLabel
  733. %14 = OpFunctionCall %3 %11
  734. OpBranch %12
  735. %12 = OpLabel
  736. OpReturn
  737. %16 = OpLabel
  738. OpSelectionMerge %17 None
  739. OpBranchConditional %5 %18 %17
  740. %18 = OpLabel
  741. OpBranch %17
  742. %17 = OpLabel
  743. OpReturn
  744. OpFunctionEnd
  745. %11 = OpFunction %3 None %6
  746. %19 = OpLabel
  747. OpBranch %20
  748. %20 = OpLabel
  749. OpBranch %21
  750. %21 = OpLabel
  751. OpBranch %22
  752. %22 = OpLabel
  753. OpSelectionMerge %24 None
  754. OpBranchConditional %5 %24 %23
  755. %23 = OpLabel
  756. OpBranch %24
  757. %24 = OpLabel
  758. OpBranch %25
  759. %25 = OpLabel
  760. OpReturn
  761. OpFunctionEnd
  762. )";
  763. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  764. }
  765. TEST(TransformationFlattenConditionalBranchTest, PhiToSelect1) {
  766. std::string shader = R"(
  767. OpCapability Shader
  768. %1 = OpExtInstImport "GLSL.std.450"
  769. OpMemoryModel Logical GLSL450
  770. OpEntryPoint Fragment %2 "main"
  771. OpExecutionMode %2 OriginUpperLeft
  772. OpSource ESSL 310
  773. %3 = OpTypeVoid
  774. %4 = OpTypeBool
  775. %5 = OpConstantTrue %4
  776. %10 = OpConstantFalse %4
  777. %6 = OpTypeFunction %3
  778. %2 = OpFunction %3 None %6
  779. %7 = OpLabel
  780. OpSelectionMerge %8 None
  781. OpBranchConditional %5 %9 %8
  782. %9 = OpLabel
  783. OpBranch %8
  784. %8 = OpLabel
  785. %11 = OpPhi %4 %5 %9 %10 %7
  786. OpReturn
  787. OpFunctionEnd
  788. )";
  789. const auto env = SPV_ENV_UNIVERSAL_1_5;
  790. const auto consumer = nullptr;
  791. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  792. spvtools::ValidatorOptions validator_options;
  793. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  794. kConsoleMessageConsumer));
  795. TransformationContext transformation_context(
  796. MakeUnique<FactManager>(context.get()), validator_options);
  797. auto transformation =
  798. TransformationFlattenConditionalBranch(7, true, 0, 0, 0, {});
  799. ASSERT_TRUE(
  800. transformation.IsApplicable(context.get(), transformation_context));
  801. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  802. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  803. kConsoleMessageConsumer));
  804. std::string after_transformation = R"(
  805. OpCapability Shader
  806. %1 = OpExtInstImport "GLSL.std.450"
  807. OpMemoryModel Logical GLSL450
  808. OpEntryPoint Fragment %2 "main"
  809. OpExecutionMode %2 OriginUpperLeft
  810. OpSource ESSL 310
  811. %3 = OpTypeVoid
  812. %4 = OpTypeBool
  813. %5 = OpConstantTrue %4
  814. %10 = OpConstantFalse %4
  815. %6 = OpTypeFunction %3
  816. %2 = OpFunction %3 None %6
  817. %7 = OpLabel
  818. OpBranch %9
  819. %9 = OpLabel
  820. OpBranch %8
  821. %8 = OpLabel
  822. %11 = OpSelect %4 %5 %5 %10
  823. OpReturn
  824. OpFunctionEnd
  825. )";
  826. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  827. }
  828. TEST(TransformationFlattenConditionalBranchTest, PhiToSelect2) {
  829. std::string shader = R"(
  830. OpCapability Shader
  831. %1 = OpExtInstImport "GLSL.std.450"
  832. OpMemoryModel Logical GLSL450
  833. OpEntryPoint Fragment %2 "main"
  834. OpExecutionMode %2 OriginUpperLeft
  835. OpSource ESSL 310
  836. %3 = OpTypeVoid
  837. %4 = OpTypeBool
  838. %5 = OpConstantTrue %4
  839. %10 = OpConstantFalse %4
  840. %6 = OpTypeFunction %3
  841. %2 = OpFunction %3 None %6
  842. %7 = OpLabel
  843. OpSelectionMerge %8 None
  844. OpBranchConditional %5 %9 %8
  845. %9 = OpLabel
  846. OpBranch %8
  847. %8 = OpLabel
  848. %11 = OpPhi %4 %10 %7 %5 %9
  849. OpReturn
  850. OpFunctionEnd
  851. )";
  852. const auto env = SPV_ENV_UNIVERSAL_1_5;
  853. const auto consumer = nullptr;
  854. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  855. spvtools::ValidatorOptions validator_options;
  856. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  857. kConsoleMessageConsumer));
  858. TransformationContext transformation_context(
  859. MakeUnique<FactManager>(context.get()), validator_options);
  860. auto transformation =
  861. TransformationFlattenConditionalBranch(7, true, 0, 0, 0, {});
  862. ASSERT_TRUE(
  863. transformation.IsApplicable(context.get(), transformation_context));
  864. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  865. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  866. kConsoleMessageConsumer));
  867. std::string after_transformation = R"(
  868. OpCapability Shader
  869. %1 = OpExtInstImport "GLSL.std.450"
  870. OpMemoryModel Logical GLSL450
  871. OpEntryPoint Fragment %2 "main"
  872. OpExecutionMode %2 OriginUpperLeft
  873. OpSource ESSL 310
  874. %3 = OpTypeVoid
  875. %4 = OpTypeBool
  876. %5 = OpConstantTrue %4
  877. %10 = OpConstantFalse %4
  878. %6 = OpTypeFunction %3
  879. %2 = OpFunction %3 None %6
  880. %7 = OpLabel
  881. OpBranch %9
  882. %9 = OpLabel
  883. OpBranch %8
  884. %8 = OpLabel
  885. %11 = OpSelect %4 %5 %5 %10
  886. OpReturn
  887. OpFunctionEnd
  888. )";
  889. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  890. }
  891. TEST(TransformationFlattenConditionalBranchTest, PhiToSelect3) {
  892. std::string shader = R"(
  893. OpCapability Shader
  894. %1 = OpExtInstImport "GLSL.std.450"
  895. OpMemoryModel Logical GLSL450
  896. OpEntryPoint Fragment %2 "main"
  897. OpExecutionMode %2 OriginUpperLeft
  898. OpSource ESSL 310
  899. %3 = OpTypeVoid
  900. %4 = OpTypeBool
  901. %5 = OpConstantTrue %4
  902. %10 = OpConstantFalse %4
  903. %6 = OpTypeFunction %3
  904. %2 = OpFunction %3 None %6
  905. %7 = OpLabel
  906. OpSelectionMerge %8 None
  907. OpBranchConditional %5 %9 %12
  908. %9 = OpLabel
  909. OpBranch %8
  910. %12 = OpLabel
  911. OpBranch %8
  912. %8 = OpLabel
  913. %11 = OpPhi %4 %10 %12 %5 %9
  914. OpReturn
  915. OpFunctionEnd
  916. )";
  917. const auto env = SPV_ENV_UNIVERSAL_1_5;
  918. const auto consumer = nullptr;
  919. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  920. spvtools::ValidatorOptions validator_options;
  921. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  922. kConsoleMessageConsumer));
  923. TransformationContext transformation_context(
  924. MakeUnique<FactManager>(context.get()), validator_options);
  925. auto transformation =
  926. TransformationFlattenConditionalBranch(7, true, 0, 0, 0, {});
  927. ASSERT_TRUE(
  928. transformation.IsApplicable(context.get(), transformation_context));
  929. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  930. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  931. kConsoleMessageConsumer));
  932. std::string after_transformation = R"(
  933. OpCapability Shader
  934. %1 = OpExtInstImport "GLSL.std.450"
  935. OpMemoryModel Logical GLSL450
  936. OpEntryPoint Fragment %2 "main"
  937. OpExecutionMode %2 OriginUpperLeft
  938. OpSource ESSL 310
  939. %3 = OpTypeVoid
  940. %4 = OpTypeBool
  941. %5 = OpConstantTrue %4
  942. %10 = OpConstantFalse %4
  943. %6 = OpTypeFunction %3
  944. %2 = OpFunction %3 None %6
  945. %7 = OpLabel
  946. OpBranch %9
  947. %9 = OpLabel
  948. OpBranch %12
  949. %12 = OpLabel
  950. OpBranch %8
  951. %8 = OpLabel
  952. %11 = OpSelect %4 %5 %5 %10
  953. OpReturn
  954. OpFunctionEnd
  955. )";
  956. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  957. }
  958. TEST(TransformationFlattenConditionalBranchTest, PhiToSelect4) {
  959. std::string shader = R"(
  960. OpCapability Shader
  961. %1 = OpExtInstImport "GLSL.std.450"
  962. OpMemoryModel Logical GLSL450
  963. OpEntryPoint Fragment %2 "main"
  964. OpExecutionMode %2 OriginUpperLeft
  965. OpSource ESSL 310
  966. %3 = OpTypeVoid
  967. %4 = OpTypeBool
  968. %5 = OpConstantTrue %4
  969. %10 = OpConstantFalse %4
  970. %6 = OpTypeFunction %3
  971. %2 = OpFunction %3 None %6
  972. %7 = OpLabel
  973. OpSelectionMerge %8 None
  974. OpBranchConditional %5 %9 %12
  975. %9 = OpLabel
  976. OpBranch %8
  977. %12 = OpLabel
  978. OpBranch %8
  979. %8 = OpLabel
  980. %11 = OpPhi %4 %5 %9 %10 %12
  981. OpReturn
  982. OpFunctionEnd
  983. )";
  984. const auto env = SPV_ENV_UNIVERSAL_1_5;
  985. const auto consumer = nullptr;
  986. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  987. spvtools::ValidatorOptions validator_options;
  988. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  989. kConsoleMessageConsumer));
  990. TransformationContext transformation_context(
  991. MakeUnique<FactManager>(context.get()), validator_options);
  992. auto transformation =
  993. TransformationFlattenConditionalBranch(7, true, 0, 0, 0, {});
  994. ASSERT_TRUE(
  995. transformation.IsApplicable(context.get(), transformation_context));
  996. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  997. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  998. kConsoleMessageConsumer));
  999. std::string after_transformation = R"(
  1000. OpCapability Shader
  1001. %1 = OpExtInstImport "GLSL.std.450"
  1002. OpMemoryModel Logical GLSL450
  1003. OpEntryPoint Fragment %2 "main"
  1004. OpExecutionMode %2 OriginUpperLeft
  1005. OpSource ESSL 310
  1006. %3 = OpTypeVoid
  1007. %4 = OpTypeBool
  1008. %5 = OpConstantTrue %4
  1009. %10 = OpConstantFalse %4
  1010. %6 = OpTypeFunction %3
  1011. %2 = OpFunction %3 None %6
  1012. %7 = OpLabel
  1013. OpBranch %9
  1014. %9 = OpLabel
  1015. OpBranch %12
  1016. %12 = OpLabel
  1017. OpBranch %8
  1018. %8 = OpLabel
  1019. %11 = OpSelect %4 %5 %5 %10
  1020. OpReturn
  1021. OpFunctionEnd
  1022. )";
  1023. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  1024. }
  1025. TEST(TransformationFlattenConditionalBranchTest, PhiToSelect5) {
  1026. std::string shader = R"(
  1027. OpCapability Shader
  1028. %1 = OpExtInstImport "GLSL.std.450"
  1029. OpMemoryModel Logical GLSL450
  1030. OpEntryPoint Fragment %2 "main"
  1031. OpExecutionMode %2 OriginUpperLeft
  1032. OpSource ESSL 310
  1033. %3 = OpTypeVoid
  1034. %4 = OpTypeBool
  1035. %5 = OpConstantTrue %4
  1036. %10 = OpConstantFalse %4
  1037. %6 = OpTypeFunction %3
  1038. %100 = OpTypePointer Function %4
  1039. %2 = OpFunction %3 None %6
  1040. %7 = OpLabel
  1041. %101 = OpVariable %100 Function
  1042. %102 = OpVariable %100 Function
  1043. OpSelectionMerge %470 None
  1044. OpBranchConditional %5 %454 %462
  1045. %454 = OpLabel
  1046. %522 = OpLoad %4 %101
  1047. OpBranch %470
  1048. %462 = OpLabel
  1049. %466 = OpLoad %4 %102
  1050. OpBranch %470
  1051. %470 = OpLabel
  1052. %534 = OpPhi %4 %522 %454 %466 %462
  1053. OpReturn
  1054. OpFunctionEnd
  1055. )";
  1056. const auto env = SPV_ENV_UNIVERSAL_1_5;
  1057. const auto consumer = nullptr;
  1058. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1059. spvtools::ValidatorOptions validator_options;
  1060. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1061. kConsoleMessageConsumer));
  1062. TransformationContext transformation_context(
  1063. MakeUnique<FactManager>(context.get()), validator_options);
  1064. auto transformation = TransformationFlattenConditionalBranch(
  1065. 7, true, 0, 0, 0,
  1066. {MakeSideEffectWrapperInfo(
  1067. MakeInstructionDescriptor(522, spv::Op::OpLoad, 0), 200, 201, 202,
  1068. 203, 204, 5),
  1069. MakeSideEffectWrapperInfo(
  1070. MakeInstructionDescriptor(466, spv::Op::OpLoad, 0), 300, 301, 302,
  1071. 303, 304, 5)});
  1072. ASSERT_TRUE(
  1073. transformation.IsApplicable(context.get(), transformation_context));
  1074. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1075. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1076. kConsoleMessageConsumer));
  1077. std::string after_transformation = R"(
  1078. OpCapability Shader
  1079. %1 = OpExtInstImport "GLSL.std.450"
  1080. OpMemoryModel Logical GLSL450
  1081. OpEntryPoint Fragment %2 "main"
  1082. OpExecutionMode %2 OriginUpperLeft
  1083. OpSource ESSL 310
  1084. %3 = OpTypeVoid
  1085. %4 = OpTypeBool
  1086. %5 = OpConstantTrue %4
  1087. %10 = OpConstantFalse %4
  1088. %6 = OpTypeFunction %3
  1089. %100 = OpTypePointer Function %4
  1090. %2 = OpFunction %3 None %6
  1091. %7 = OpLabel
  1092. %101 = OpVariable %100 Function
  1093. %102 = OpVariable %100 Function
  1094. OpBranch %454
  1095. %454 = OpLabel
  1096. OpSelectionMerge %200 None
  1097. OpBranchConditional %5 %201 %203
  1098. %201 = OpLabel
  1099. %202 = OpLoad %4 %101
  1100. OpBranch %200
  1101. %203 = OpLabel
  1102. %204 = OpCopyObject %4 %5
  1103. OpBranch %200
  1104. %200 = OpLabel
  1105. %522 = OpPhi %4 %202 %201 %204 %203
  1106. OpBranch %462
  1107. %462 = OpLabel
  1108. OpSelectionMerge %300 None
  1109. OpBranchConditional %5 %303 %301
  1110. %301 = OpLabel
  1111. %302 = OpLoad %4 %102
  1112. OpBranch %300
  1113. %303 = OpLabel
  1114. %304 = OpCopyObject %4 %5
  1115. OpBranch %300
  1116. %300 = OpLabel
  1117. %466 = OpPhi %4 %302 %301 %304 %303
  1118. OpBranch %470
  1119. %470 = OpLabel
  1120. %534 = OpSelect %4 %5 %522 %466
  1121. OpReturn
  1122. OpFunctionEnd
  1123. )";
  1124. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  1125. }
  1126. TEST(TransformationFlattenConditionalBranchTest,
  1127. LoadFromBufferBlockDecoratedStruct) {
  1128. std::string shader = R"(
  1129. OpCapability Shader
  1130. %1 = OpExtInstImport "GLSL.std.450"
  1131. OpMemoryModel Logical GLSL450
  1132. OpEntryPoint Fragment %4 "main"
  1133. OpExecutionMode %4 OriginUpperLeft
  1134. OpSource ESSL 320
  1135. OpMemberDecorate %11 0 Offset 0
  1136. OpDecorate %11 BufferBlock
  1137. OpDecorate %13 DescriptorSet 0
  1138. OpDecorate %13 Binding 0
  1139. %2 = OpTypeVoid
  1140. %3 = OpTypeFunction %2
  1141. %6 = OpTypeBool
  1142. %7 = OpConstantTrue %6
  1143. %10 = OpTypeInt 32 1
  1144. %11 = OpTypeStruct %10
  1145. %12 = OpTypePointer Uniform %11
  1146. %13 = OpVariable %12 Uniform
  1147. %21 = OpUndef %11
  1148. %4 = OpFunction %2 None %3
  1149. %5 = OpLabel
  1150. OpSelectionMerge %9 None
  1151. OpBranchConditional %7 %8 %9
  1152. %8 = OpLabel
  1153. %20 = OpLoad %11 %13
  1154. OpBranch %9
  1155. %9 = OpLabel
  1156. OpReturn
  1157. OpFunctionEnd
  1158. )";
  1159. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1160. const auto consumer = nullptr;
  1161. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1162. spvtools::ValidatorOptions validator_options;
  1163. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1164. kConsoleMessageConsumer));
  1165. TransformationContext transformation_context(
  1166. MakeUnique<FactManager>(context.get()), validator_options);
  1167. auto transformation = TransformationFlattenConditionalBranch(
  1168. 5, true, 0, 0, 0,
  1169. {MakeSideEffectWrapperInfo(
  1170. MakeInstructionDescriptor(20, spv::Op::OpLoad, 0), 100, 101, 102, 103,
  1171. 104, 21)});
  1172. ASSERT_TRUE(
  1173. transformation.IsApplicable(context.get(), transformation_context));
  1174. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1175. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1176. kConsoleMessageConsumer));
  1177. }
  1178. TEST(TransformationFlattenConditionalBranchTest, InapplicableSampledImageLoad) {
  1179. std::string shader = R"(
  1180. OpCapability Shader
  1181. %1 = OpExtInstImport "GLSL.std.450"
  1182. OpMemoryModel Logical GLSL450
  1183. OpEntryPoint Fragment %4 "main" %12 %96
  1184. OpExecutionMode %4 OriginUpperLeft
  1185. OpSource ESSL 320
  1186. OpDecorate %12 BuiltIn FragCoord
  1187. OpDecorate %91 DescriptorSet 0
  1188. OpDecorate %91 Binding 0
  1189. OpDecorate %96 Location 0
  1190. %2 = OpTypeVoid
  1191. %3 = OpTypeFunction %2
  1192. %6 = OpTypeFloat 32
  1193. %7 = OpTypeVector %6 2
  1194. %10 = OpTypeVector %6 4
  1195. %11 = OpTypePointer Input %10
  1196. %12 = OpVariable %11 Input
  1197. %21 = OpConstant %6 2
  1198. %24 = OpTypeInt 32 1
  1199. %33 = OpTypeBool
  1200. %35 = OpConstantTrue %33
  1201. %88 = OpTypeImage %6 2D 0 0 0 1 Unknown
  1202. %89 = OpTypeSampledImage %88
  1203. %90 = OpTypePointer UniformConstant %89
  1204. %91 = OpVariable %90 UniformConstant
  1205. %95 = OpTypePointer Output %10
  1206. %96 = OpVariable %95 Output
  1207. %200 = OpUndef %89
  1208. %4 = OpFunction %2 None %3
  1209. %5 = OpLabel
  1210. OpBranch %28
  1211. %28 = OpLabel
  1212. OpSelectionMerge %38 None
  1213. OpBranchConditional %35 %32 %37
  1214. %32 = OpLabel
  1215. %40 = OpLoad %89 %91
  1216. OpBranch %38
  1217. %37 = OpLabel
  1218. OpBranch %38
  1219. %38 = OpLabel
  1220. OpReturn
  1221. OpFunctionEnd
  1222. )";
  1223. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1224. const auto consumer = nullptr;
  1225. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1226. spvtools::ValidatorOptions validator_options;
  1227. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1228. kConsoleMessageConsumer));
  1229. TransformationContext transformation_context(
  1230. MakeUnique<FactManager>(context.get()), validator_options);
  1231. ASSERT_FALSE(TransformationFlattenConditionalBranch(
  1232. 28, true, 0, 0, 0,
  1233. {MakeSideEffectWrapperInfo(
  1234. MakeInstructionDescriptor(40, spv::Op::OpLoad, 0), 100,
  1235. 101, 102, 103, 104, 200)})
  1236. .IsApplicable(context.get(), transformation_context));
  1237. }
  1238. TEST(TransformationFlattenConditionalBranchTest,
  1239. InapplicablePhiToSelectVector) {
  1240. std::string shader = R"(
  1241. OpCapability Shader
  1242. %1 = OpExtInstImport "GLSL.std.450"
  1243. OpMemoryModel Logical GLSL450
  1244. OpEntryPoint Fragment %4 "main"
  1245. OpExecutionMode %4 OriginUpperLeft
  1246. OpSource ESSL 320
  1247. %2 = OpTypeVoid
  1248. %3 = OpTypeFunction %2
  1249. %6 = OpTypeBool
  1250. %7 = OpConstantTrue %6
  1251. %10 = OpTypeInt 32 1
  1252. %11 = OpTypeVector %10 3
  1253. %12 = OpUndef %11
  1254. %4 = OpFunction %2 None %3
  1255. %5 = OpLabel
  1256. OpSelectionMerge %20 None
  1257. OpBranchConditional %7 %8 %9
  1258. %8 = OpLabel
  1259. OpBranch %20
  1260. %9 = OpLabel
  1261. OpBranch %20
  1262. %20 = OpLabel
  1263. %21 = OpPhi %11 %12 %8 %12 %9
  1264. OpReturn
  1265. OpFunctionEnd
  1266. )";
  1267. for (auto env :
  1268. {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
  1269. SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}) {
  1270. const auto consumer = nullptr;
  1271. const auto context =
  1272. BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1273. spvtools::ValidatorOptions validator_options;
  1274. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  1275. context.get(), validator_options, kConsoleMessageConsumer));
  1276. TransformationContext transformation_context(
  1277. MakeUnique<FactManager>(context.get()), validator_options);
  1278. auto transformation =
  1279. TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {});
  1280. ASSERT_FALSE(
  1281. transformation.IsApplicable(context.get(), transformation_context));
  1282. }
  1283. }
  1284. TEST(TransformationFlattenConditionalBranchTest,
  1285. InapplicablePhiToSelectVector2) {
  1286. std::string shader = R"(
  1287. OpCapability Shader
  1288. %1 = OpExtInstImport "GLSL.std.450"
  1289. OpMemoryModel Logical GLSL450
  1290. OpEntryPoint Fragment %4 "main"
  1291. OpExecutionMode %4 OriginUpperLeft
  1292. OpSource ESSL 320
  1293. %2 = OpTypeVoid
  1294. %3 = OpTypeFunction %2
  1295. %6 = OpTypeBool
  1296. %30 = OpTypeVector %6 3
  1297. %31 = OpTypeVector %6 2
  1298. %7 = OpConstantTrue %6
  1299. %10 = OpTypeInt 32 1
  1300. %11 = OpTypeVector %10 3
  1301. %40 = OpTypeFloat 32
  1302. %41 = OpTypeVector %40 4
  1303. %12 = OpUndef %11
  1304. %60 = OpUndef %41
  1305. %61 = OpConstantComposite %31 %7 %7
  1306. %4 = OpFunction %2 None %3
  1307. %5 = OpLabel
  1308. OpSelectionMerge %20 None
  1309. OpBranchConditional %7 %8 %9
  1310. %8 = OpLabel
  1311. OpBranch %20
  1312. %9 = OpLabel
  1313. OpBranch %20
  1314. %20 = OpLabel
  1315. %21 = OpPhi %11 %12 %8 %12 %9
  1316. %22 = OpPhi %11 %12 %8 %12 %9
  1317. %23 = OpPhi %41 %60 %8 %60 %9
  1318. %24 = OpPhi %31 %61 %8 %61 %9
  1319. %25 = OpPhi %41 %60 %8 %60 %9
  1320. OpReturn
  1321. OpFunctionEnd
  1322. )";
  1323. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1324. const auto consumer = nullptr;
  1325. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1326. spvtools::ValidatorOptions validator_options;
  1327. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1328. kConsoleMessageConsumer));
  1329. TransformationContext transformation_context(
  1330. MakeUnique<FactManager>(context.get()), validator_options);
  1331. auto transformation =
  1332. TransformationFlattenConditionalBranch(5, true, 101, 102, 103, {});
  1333. // bvec4 is not present in the module.
  1334. ASSERT_FALSE(
  1335. transformation.IsApplicable(context.get(), transformation_context));
  1336. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1337. }
  1338. TEST(TransformationFlattenConditionalBranchTest,
  1339. InapplicablePhiToSelectMatrix) {
  1340. std::string shader = R"(
  1341. OpCapability Shader
  1342. %1 = OpExtInstImport "GLSL.std.450"
  1343. OpMemoryModel Logical GLSL450
  1344. OpEntryPoint Fragment %4 "main"
  1345. OpExecutionMode %4 OriginUpperLeft
  1346. OpSource ESSL 320
  1347. %2 = OpTypeVoid
  1348. %3 = OpTypeFunction %2
  1349. %6 = OpTypeBool
  1350. %7 = OpConstantTrue %6
  1351. %10 = OpTypeFloat 32
  1352. %30 = OpTypeVector %10 3
  1353. %11 = OpTypeMatrix %30 3
  1354. %12 = OpUndef %11
  1355. %4 = OpFunction %2 None %3
  1356. %5 = OpLabel
  1357. OpSelectionMerge %20 None
  1358. OpBranchConditional %7 %8 %9
  1359. %8 = OpLabel
  1360. OpBranch %20
  1361. %9 = OpLabel
  1362. OpBranch %20
  1363. %20 = OpLabel
  1364. %21 = OpPhi %11 %12 %8 %12 %9
  1365. OpReturn
  1366. OpFunctionEnd
  1367. )";
  1368. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1369. const auto consumer = nullptr;
  1370. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1371. spvtools::ValidatorOptions validator_options;
  1372. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1373. kConsoleMessageConsumer));
  1374. TransformationContext transformation_context(
  1375. MakeUnique<FactManager>(context.get()), validator_options);
  1376. auto transformation =
  1377. TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {});
  1378. ASSERT_FALSE(
  1379. transformation.IsApplicable(context.get(), transformation_context));
  1380. }
  1381. TEST(TransformationFlattenConditionalBranchTest, ApplicablePhiToSelectVector) {
  1382. std::string shader = R"(
  1383. OpCapability Shader
  1384. %1 = OpExtInstImport "GLSL.std.450"
  1385. OpMemoryModel Logical GLSL450
  1386. OpEntryPoint Fragment %4 "main"
  1387. OpExecutionMode %4 OriginUpperLeft
  1388. OpSource ESSL 320
  1389. %2 = OpTypeVoid
  1390. %3 = OpTypeFunction %2
  1391. %6 = OpTypeBool
  1392. %7 = OpConstantTrue %6
  1393. %10 = OpTypeInt 32 1
  1394. %11 = OpTypeVector %10 3
  1395. %12 = OpUndef %11
  1396. %4 = OpFunction %2 None %3
  1397. %5 = OpLabel
  1398. OpSelectionMerge %20 None
  1399. OpBranchConditional %7 %8 %9
  1400. %8 = OpLabel
  1401. OpBranch %20
  1402. %9 = OpLabel
  1403. OpBranch %20
  1404. %20 = OpLabel
  1405. %21 = OpPhi %11 %12 %8 %12 %9
  1406. OpReturn
  1407. OpFunctionEnd
  1408. )";
  1409. const auto env = SPV_ENV_UNIVERSAL_1_5;
  1410. const auto consumer = nullptr;
  1411. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1412. spvtools::ValidatorOptions validator_options;
  1413. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1414. kConsoleMessageConsumer));
  1415. TransformationContext transformation_context(
  1416. MakeUnique<FactManager>(context.get()), validator_options);
  1417. auto transformation =
  1418. TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {});
  1419. ASSERT_TRUE(
  1420. transformation.IsApplicable(context.get(), transformation_context));
  1421. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1422. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1423. kConsoleMessageConsumer));
  1424. std::string expected_shader = R"(
  1425. OpCapability Shader
  1426. %1 = OpExtInstImport "GLSL.std.450"
  1427. OpMemoryModel Logical GLSL450
  1428. OpEntryPoint Fragment %4 "main"
  1429. OpExecutionMode %4 OriginUpperLeft
  1430. OpSource ESSL 320
  1431. %2 = OpTypeVoid
  1432. %3 = OpTypeFunction %2
  1433. %6 = OpTypeBool
  1434. %7 = OpConstantTrue %6
  1435. %10 = OpTypeInt 32 1
  1436. %11 = OpTypeVector %10 3
  1437. %12 = OpUndef %11
  1438. %4 = OpFunction %2 None %3
  1439. %5 = OpLabel
  1440. OpBranch %8
  1441. %8 = OpLabel
  1442. OpBranch %9
  1443. %9 = OpLabel
  1444. OpBranch %20
  1445. %20 = OpLabel
  1446. %21 = OpSelect %11 %7 %12 %12
  1447. OpReturn
  1448. OpFunctionEnd
  1449. )";
  1450. ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
  1451. }
  1452. TEST(TransformationFlattenConditionalBranchTest, ApplicablePhiToSelectVector2) {
  1453. std::string shader = R"(
  1454. OpCapability Shader
  1455. %1 = OpExtInstImport "GLSL.std.450"
  1456. OpMemoryModel Logical GLSL450
  1457. OpEntryPoint Fragment %4 "main"
  1458. OpExecutionMode %4 OriginUpperLeft
  1459. OpSource ESSL 320
  1460. %2 = OpTypeVoid
  1461. %3 = OpTypeFunction %2
  1462. %6 = OpTypeBool
  1463. %30 = OpTypeVector %6 3
  1464. %31 = OpTypeVector %6 2
  1465. %32 = OpTypeVector %6 4
  1466. %7 = OpConstantTrue %6
  1467. %10 = OpTypeInt 32 1
  1468. %11 = OpTypeVector %10 3
  1469. %40 = OpTypeFloat 32
  1470. %41 = OpTypeVector %40 4
  1471. %12 = OpUndef %11
  1472. %60 = OpUndef %41
  1473. %61 = OpConstantComposite %31 %7 %7
  1474. %4 = OpFunction %2 None %3
  1475. %5 = OpLabel
  1476. OpSelectionMerge %20 None
  1477. OpBranchConditional %7 %8 %9
  1478. %8 = OpLabel
  1479. OpBranch %20
  1480. %9 = OpLabel
  1481. OpBranch %20
  1482. %20 = OpLabel
  1483. %21 = OpPhi %11 %12 %8 %12 %9
  1484. %22 = OpPhi %11 %12 %8 %12 %9
  1485. %23 = OpPhi %41 %60 %8 %60 %9
  1486. %24 = OpPhi %31 %61 %8 %61 %9
  1487. %25 = OpPhi %41 %60 %8 %60 %9
  1488. OpReturn
  1489. OpFunctionEnd
  1490. )";
  1491. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1492. const auto consumer = nullptr;
  1493. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1494. spvtools::ValidatorOptions validator_options;
  1495. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1496. kConsoleMessageConsumer));
  1497. TransformationContext transformation_context(
  1498. MakeUnique<FactManager>(context.get()), validator_options);
  1499. // No id for the 2D vector case is provided.
  1500. ASSERT_FALSE(TransformationFlattenConditionalBranch(5, true, 0, 102, 103, {})
  1501. .IsApplicable(context.get(), transformation_context));
  1502. // No id for the 3D vector case is provided.
  1503. ASSERT_FALSE(TransformationFlattenConditionalBranch(5, true, 101, 0, 103, {})
  1504. .IsApplicable(context.get(), transformation_context));
  1505. // No id for the 4D vector case is provided.
  1506. ASSERT_FALSE(TransformationFlattenConditionalBranch(5, true, 101, 102, 0, {})
  1507. .IsApplicable(context.get(), transformation_context));
  1508. // %10 is not fresh
  1509. ASSERT_FALSE(TransformationFlattenConditionalBranch(5, true, 10, 102, 103, {})
  1510. .IsApplicable(context.get(), transformation_context));
  1511. // %10 is not fresh
  1512. ASSERT_FALSE(TransformationFlattenConditionalBranch(5, true, 101, 10, 103, {})
  1513. .IsApplicable(context.get(), transformation_context));
  1514. // %10 is not fresh
  1515. ASSERT_FALSE(TransformationFlattenConditionalBranch(5, true, 101, 102, 10, {})
  1516. .IsApplicable(context.get(), transformation_context));
  1517. // Duplicate "fresh" ids used for boolean vector constructors
  1518. ASSERT_FALSE(
  1519. TransformationFlattenConditionalBranch(5, true, 101, 102, 102, {})
  1520. .IsApplicable(context.get(), transformation_context));
  1521. auto transformation =
  1522. TransformationFlattenConditionalBranch(5, true, 101, 102, 103, {});
  1523. ASSERT_TRUE(
  1524. transformation.IsApplicable(context.get(), transformation_context));
  1525. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1526. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1527. kConsoleMessageConsumer));
  1528. std::string expected_shader = R"(
  1529. OpCapability Shader
  1530. %1 = OpExtInstImport "GLSL.std.450"
  1531. OpMemoryModel Logical GLSL450
  1532. OpEntryPoint Fragment %4 "main"
  1533. OpExecutionMode %4 OriginUpperLeft
  1534. OpSource ESSL 320
  1535. %2 = OpTypeVoid
  1536. %3 = OpTypeFunction %2
  1537. %6 = OpTypeBool
  1538. %30 = OpTypeVector %6 3
  1539. %31 = OpTypeVector %6 2
  1540. %32 = OpTypeVector %6 4
  1541. %7 = OpConstantTrue %6
  1542. %10 = OpTypeInt 32 1
  1543. %11 = OpTypeVector %10 3
  1544. %40 = OpTypeFloat 32
  1545. %41 = OpTypeVector %40 4
  1546. %12 = OpUndef %11
  1547. %60 = OpUndef %41
  1548. %61 = OpConstantComposite %31 %7 %7
  1549. %4 = OpFunction %2 None %3
  1550. %5 = OpLabel
  1551. OpBranch %8
  1552. %8 = OpLabel
  1553. OpBranch %9
  1554. %9 = OpLabel
  1555. OpBranch %20
  1556. %20 = OpLabel
  1557. %103 = OpCompositeConstruct %32 %7 %7 %7 %7
  1558. %102 = OpCompositeConstruct %30 %7 %7 %7
  1559. %101 = OpCompositeConstruct %31 %7 %7
  1560. %21 = OpSelect %11 %102 %12 %12
  1561. %22 = OpSelect %11 %102 %12 %12
  1562. %23 = OpSelect %41 %103 %60 %60
  1563. %24 = OpSelect %31 %101 %61 %61
  1564. %25 = OpSelect %41 %103 %60 %60
  1565. OpReturn
  1566. OpFunctionEnd
  1567. )";
  1568. ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
  1569. }
  1570. TEST(TransformationFlattenConditionalBranchTest, ApplicablePhiToSelectVector3) {
  1571. std::string shader = R"(
  1572. OpCapability Shader
  1573. %1 = OpExtInstImport "GLSL.std.450"
  1574. OpMemoryModel Logical GLSL450
  1575. OpEntryPoint Fragment %4 "main"
  1576. OpExecutionMode %4 OriginUpperLeft
  1577. OpSource ESSL 320
  1578. %2 = OpTypeVoid
  1579. %3 = OpTypeFunction %2
  1580. %6 = OpTypeBool
  1581. %30 = OpTypeVector %6 3
  1582. %31 = OpTypeVector %6 2
  1583. %32 = OpTypeVector %6 4
  1584. %7 = OpConstantTrue %6
  1585. %10 = OpTypeInt 32 1
  1586. %11 = OpTypeVector %10 3
  1587. %40 = OpTypeFloat 32
  1588. %41 = OpTypeVector %40 4
  1589. %12 = OpUndef %11
  1590. %60 = OpUndef %41
  1591. %61 = OpConstantComposite %31 %7 %7
  1592. %4 = OpFunction %2 None %3
  1593. %5 = OpLabel
  1594. OpSelectionMerge %20 None
  1595. OpBranchConditional %7 %8 %9
  1596. %8 = OpLabel
  1597. OpBranch %20
  1598. %9 = OpLabel
  1599. OpBranch %20
  1600. %20 = OpLabel
  1601. %21 = OpPhi %11 %12 %8 %12 %9
  1602. %22 = OpPhi %11 %12 %8 %12 %9
  1603. %23 = OpPhi %41 %60 %8 %60 %9
  1604. %24 = OpPhi %31 %61 %8 %61 %9
  1605. %25 = OpPhi %41 %60 %8 %60 %9
  1606. OpReturn
  1607. OpFunctionEnd
  1608. )";
  1609. const auto env = SPV_ENV_UNIVERSAL_1_5;
  1610. const auto consumer = nullptr;
  1611. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1612. spvtools::ValidatorOptions validator_options;
  1613. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1614. kConsoleMessageConsumer));
  1615. TransformationContext transformation_context(
  1616. MakeUnique<FactManager>(context.get()), validator_options);
  1617. auto transformation =
  1618. TransformationFlattenConditionalBranch(5, true, 101, 0, 103, {});
  1619. ASSERT_TRUE(
  1620. transformation.IsApplicable(context.get(), transformation_context));
  1621. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1622. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1623. kConsoleMessageConsumer));
  1624. // Check that the in operands of any OpSelect instructions all have the
  1625. // appropriate operand type.
  1626. context->module()->ForEachInst([](opt::Instruction* inst) {
  1627. if (inst->opcode() == spv::Op::OpSelect) {
  1628. ASSERT_EQ(SPV_OPERAND_TYPE_ID, inst->GetInOperand(0).type);
  1629. ASSERT_EQ(SPV_OPERAND_TYPE_ID, inst->GetInOperand(1).type);
  1630. ASSERT_EQ(SPV_OPERAND_TYPE_ID, inst->GetInOperand(2).type);
  1631. }
  1632. });
  1633. std::string expected_shader = R"(
  1634. OpCapability Shader
  1635. %1 = OpExtInstImport "GLSL.std.450"
  1636. OpMemoryModel Logical GLSL450
  1637. OpEntryPoint Fragment %4 "main"
  1638. OpExecutionMode %4 OriginUpperLeft
  1639. OpSource ESSL 320
  1640. %2 = OpTypeVoid
  1641. %3 = OpTypeFunction %2
  1642. %6 = OpTypeBool
  1643. %30 = OpTypeVector %6 3
  1644. %31 = OpTypeVector %6 2
  1645. %32 = OpTypeVector %6 4
  1646. %7 = OpConstantTrue %6
  1647. %10 = OpTypeInt 32 1
  1648. %11 = OpTypeVector %10 3
  1649. %40 = OpTypeFloat 32
  1650. %41 = OpTypeVector %40 4
  1651. %12 = OpUndef %11
  1652. %60 = OpUndef %41
  1653. %61 = OpConstantComposite %31 %7 %7
  1654. %4 = OpFunction %2 None %3
  1655. %5 = OpLabel
  1656. OpBranch %8
  1657. %8 = OpLabel
  1658. OpBranch %9
  1659. %9 = OpLabel
  1660. OpBranch %20
  1661. %20 = OpLabel
  1662. %103 = OpCompositeConstruct %32 %7 %7 %7 %7
  1663. %101 = OpCompositeConstruct %31 %7 %7
  1664. %21 = OpSelect %11 %7 %12 %12
  1665. %22 = OpSelect %11 %7 %12 %12
  1666. %23 = OpSelect %41 %103 %60 %60
  1667. %24 = OpSelect %31 %101 %61 %61
  1668. %25 = OpSelect %41 %103 %60 %60
  1669. OpReturn
  1670. OpFunctionEnd
  1671. )";
  1672. ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
  1673. }
  1674. TEST(TransformationFlattenConditionalBranchTest, ApplicablePhiToSelectMatrix) {
  1675. std::string shader = R"(
  1676. OpCapability Shader
  1677. %1 = OpExtInstImport "GLSL.std.450"
  1678. OpMemoryModel Logical GLSL450
  1679. OpEntryPoint Fragment %4 "main"
  1680. OpExecutionMode %4 OriginUpperLeft
  1681. OpSource ESSL 320
  1682. %2 = OpTypeVoid
  1683. %3 = OpTypeFunction %2
  1684. %6 = OpTypeBool
  1685. %7 = OpConstantTrue %6
  1686. %10 = OpTypeFloat 32
  1687. %30 = OpTypeVector %10 3
  1688. %11 = OpTypeMatrix %30 3
  1689. %12 = OpUndef %11
  1690. %4 = OpFunction %2 None %3
  1691. %5 = OpLabel
  1692. OpSelectionMerge %20 None
  1693. OpBranchConditional %7 %8 %9
  1694. %8 = OpLabel
  1695. OpBranch %20
  1696. %9 = OpLabel
  1697. OpBranch %20
  1698. %20 = OpLabel
  1699. %21 = OpPhi %11 %12 %8 %12 %9
  1700. OpReturn
  1701. OpFunctionEnd
  1702. )";
  1703. const auto env = SPV_ENV_UNIVERSAL_1_5;
  1704. const auto consumer = nullptr;
  1705. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1706. spvtools::ValidatorOptions validator_options;
  1707. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1708. kConsoleMessageConsumer));
  1709. TransformationContext transformation_context(
  1710. MakeUnique<FactManager>(context.get()), validator_options);
  1711. auto transformation =
  1712. TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {});
  1713. ASSERT_TRUE(
  1714. transformation.IsApplicable(context.get(), transformation_context));
  1715. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1716. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1717. kConsoleMessageConsumer));
  1718. std::string expected_shader = R"(
  1719. OpCapability Shader
  1720. %1 = OpExtInstImport "GLSL.std.450"
  1721. OpMemoryModel Logical GLSL450
  1722. OpEntryPoint Fragment %4 "main"
  1723. OpExecutionMode %4 OriginUpperLeft
  1724. OpSource ESSL 320
  1725. %2 = OpTypeVoid
  1726. %3 = OpTypeFunction %2
  1727. %6 = OpTypeBool
  1728. %7 = OpConstantTrue %6
  1729. %10 = OpTypeFloat 32
  1730. %30 = OpTypeVector %10 3
  1731. %11 = OpTypeMatrix %30 3
  1732. %12 = OpUndef %11
  1733. %4 = OpFunction %2 None %3
  1734. %5 = OpLabel
  1735. OpBranch %8
  1736. %8 = OpLabel
  1737. OpBranch %9
  1738. %9 = OpLabel
  1739. OpBranch %20
  1740. %20 = OpLabel
  1741. %21 = OpSelect %11 %7 %12 %12
  1742. OpReturn
  1743. OpFunctionEnd
  1744. )";
  1745. ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
  1746. }
  1747. TEST(TransformationFlattenConditionalBranchTest,
  1748. InapplicableConditionIsIrrelevant) {
  1749. std::string shader = R"(
  1750. OpCapability Shader
  1751. %1 = OpExtInstImport "GLSL.std.450"
  1752. OpMemoryModel Logical GLSL450
  1753. OpEntryPoint Fragment %4 "main"
  1754. OpExecutionMode %4 OriginUpperLeft
  1755. OpSource ESSL 320
  1756. %2 = OpTypeVoid
  1757. %3 = OpTypeFunction %2
  1758. %6 = OpTypeBool
  1759. %7 = OpConstantTrue %6
  1760. %10 = OpTypeInt 32 1
  1761. %4 = OpFunction %2 None %3
  1762. %5 = OpLabel
  1763. OpSelectionMerge %9 None
  1764. OpBranchConditional %7 %8 %9
  1765. %8 = OpLabel
  1766. OpBranch %9
  1767. %9 = OpLabel
  1768. OpReturn
  1769. OpFunctionEnd
  1770. )";
  1771. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1772. const auto consumer = nullptr;
  1773. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1774. spvtools::ValidatorOptions validator_options;
  1775. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1776. kConsoleMessageConsumer));
  1777. TransformationContext transformation_context(
  1778. MakeUnique<FactManager>(context.get()), validator_options);
  1779. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(7);
  1780. // Inapplicable because the branch condition, %7, is irrelevant.
  1781. ASSERT_FALSE(TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {})
  1782. .IsApplicable(context.get(), transformation_context));
  1783. }
  1784. TEST(TransformationFlattenConditionalBranchTest,
  1785. OpPhiWhenTrueBranchIsConvergenceBlock) {
  1786. std::string shader = R"(
  1787. OpCapability Shader
  1788. %1 = OpExtInstImport "GLSL.std.450"
  1789. OpMemoryModel Logical GLSL450
  1790. OpEntryPoint Fragment %4 "main"
  1791. OpExecutionMode %4 OriginUpperLeft
  1792. OpSource ESSL 320
  1793. OpName %4 "main"
  1794. %2 = OpTypeVoid
  1795. %3 = OpTypeFunction %2
  1796. %6 = OpTypeBool
  1797. %7 = OpConstantTrue %6
  1798. %4 = OpFunction %2 None %3
  1799. %5 = OpLabel
  1800. OpSelectionMerge %9 None
  1801. OpBranchConditional %7 %9 %8
  1802. %8 = OpLabel
  1803. %10 = OpCopyObject %6 %7
  1804. OpBranch %9
  1805. %9 = OpLabel
  1806. %11 = OpPhi %6 %10 %8 %7 %5
  1807. %12 = OpPhi %6 %7 %5 %10 %8
  1808. OpReturn
  1809. OpFunctionEnd
  1810. )";
  1811. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1812. const auto consumer = nullptr;
  1813. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1814. spvtools::ValidatorOptions validator_options;
  1815. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1816. kConsoleMessageConsumer));
  1817. TransformationContext transformation_context(
  1818. MakeUnique<FactManager>(context.get()), validator_options);
  1819. TransformationFlattenConditionalBranch transformation(5, true, 0, 0, 0, {});
  1820. ASSERT_TRUE(
  1821. transformation.IsApplicable(context.get(), transformation_context));
  1822. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1823. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1824. kConsoleMessageConsumer));
  1825. std::string expected = R"(
  1826. OpCapability Shader
  1827. %1 = OpExtInstImport "GLSL.std.450"
  1828. OpMemoryModel Logical GLSL450
  1829. OpEntryPoint Fragment %4 "main"
  1830. OpExecutionMode %4 OriginUpperLeft
  1831. OpSource ESSL 320
  1832. OpName %4 "main"
  1833. %2 = OpTypeVoid
  1834. %3 = OpTypeFunction %2
  1835. %6 = OpTypeBool
  1836. %7 = OpConstantTrue %6
  1837. %4 = OpFunction %2 None %3
  1838. %5 = OpLabel
  1839. OpBranch %8
  1840. %8 = OpLabel
  1841. %10 = OpCopyObject %6 %7
  1842. OpBranch %9
  1843. %9 = OpLabel
  1844. %11 = OpSelect %6 %7 %7 %10
  1845. %12 = OpSelect %6 %7 %7 %10
  1846. OpReturn
  1847. OpFunctionEnd
  1848. )";
  1849. ASSERT_TRUE(IsEqual(env, expected, context.get()));
  1850. }
  1851. TEST(TransformationFlattenConditionalBranchTest,
  1852. OpPhiWhenFalseBranchIsConvergenceBlock) {
  1853. std::string shader = R"(
  1854. OpCapability Shader
  1855. %1 = OpExtInstImport "GLSL.std.450"
  1856. OpMemoryModel Logical GLSL450
  1857. OpEntryPoint Fragment %4 "main"
  1858. OpExecutionMode %4 OriginUpperLeft
  1859. OpSource ESSL 320
  1860. OpName %4 "main"
  1861. %2 = OpTypeVoid
  1862. %3 = OpTypeFunction %2
  1863. %6 = OpTypeBool
  1864. %7 = OpConstantTrue %6
  1865. %4 = OpFunction %2 None %3
  1866. %5 = OpLabel
  1867. OpSelectionMerge %9 None
  1868. OpBranchConditional %7 %8 %9
  1869. %8 = OpLabel
  1870. %10 = OpCopyObject %6 %7
  1871. OpBranch %9
  1872. %9 = OpLabel
  1873. %11 = OpPhi %6 %10 %8 %7 %5
  1874. %12 = OpPhi %6 %7 %5 %10 %8
  1875. OpReturn
  1876. OpFunctionEnd
  1877. )";
  1878. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1879. const auto consumer = nullptr;
  1880. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1881. spvtools::ValidatorOptions validator_options;
  1882. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1883. kConsoleMessageConsumer));
  1884. TransformationContext transformation_context(
  1885. MakeUnique<FactManager>(context.get()), validator_options);
  1886. TransformationFlattenConditionalBranch transformation(5, true, 0, 0, 0, {});
  1887. ASSERT_TRUE(
  1888. transformation.IsApplicable(context.get(), transformation_context));
  1889. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1890. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1891. kConsoleMessageConsumer));
  1892. std::string expected = R"(
  1893. OpCapability Shader
  1894. %1 = OpExtInstImport "GLSL.std.450"
  1895. OpMemoryModel Logical GLSL450
  1896. OpEntryPoint Fragment %4 "main"
  1897. OpExecutionMode %4 OriginUpperLeft
  1898. OpSource ESSL 320
  1899. OpName %4 "main"
  1900. %2 = OpTypeVoid
  1901. %3 = OpTypeFunction %2
  1902. %6 = OpTypeBool
  1903. %7 = OpConstantTrue %6
  1904. %4 = OpFunction %2 None %3
  1905. %5 = OpLabel
  1906. OpBranch %8
  1907. %8 = OpLabel
  1908. %10 = OpCopyObject %6 %7
  1909. OpBranch %9
  1910. %9 = OpLabel
  1911. %11 = OpSelect %6 %7 %10 %7
  1912. %12 = OpSelect %6 %7 %10 %7
  1913. OpReturn
  1914. OpFunctionEnd
  1915. )";
  1916. ASSERT_TRUE(IsEqual(env, expected, context.get()));
  1917. }
  1918. TEST(TransformationFlattenConditionalBranchTest, ContainsDeadBlocksTest) {
  1919. std::string shader = R"(
  1920. OpCapability Shader
  1921. %1 = OpExtInstImport "GLSL.std.450"
  1922. OpMemoryModel Logical GLSL450
  1923. OpEntryPoint Fragment %4 "main"
  1924. OpExecutionMode %4 OriginUpperLeft
  1925. OpSource ESSL 320
  1926. OpName %4 "main"
  1927. %2 = OpTypeVoid
  1928. %3 = OpTypeFunction %2
  1929. %6 = OpTypeBool
  1930. %7 = OpConstantFalse %6
  1931. %4 = OpFunction %2 None %3
  1932. %5 = OpLabel
  1933. OpSelectionMerge %9 None
  1934. OpBranchConditional %7 %8 %9
  1935. %8 = OpLabel
  1936. %10 = OpCopyObject %6 %7
  1937. OpBranch %9
  1938. %9 = OpLabel
  1939. %11 = OpPhi %6 %10 %8 %7 %5
  1940. %12 = OpPhi %6 %7 %5 %10 %8
  1941. OpReturn
  1942. OpFunctionEnd
  1943. )";
  1944. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1945. const auto consumer = nullptr;
  1946. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1947. spvtools::ValidatorOptions validator_options;
  1948. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1949. kConsoleMessageConsumer));
  1950. TransformationContext transformation_context(
  1951. MakeUnique<FactManager>(context.get()), validator_options);
  1952. TransformationFlattenConditionalBranch transformation(5, true, 0, 0, 0, {});
  1953. ASSERT_TRUE(
  1954. transformation.IsApplicable(context.get(), transformation_context));
  1955. transformation_context.GetFactManager()->AddFactBlockIsDead(8);
  1956. ASSERT_FALSE(
  1957. transformation.IsApplicable(context.get(), transformation_context));
  1958. }
  1959. TEST(TransformationFlattenConditionalBranchTest, ContainsContinueBlockTest) {
  1960. std::string shader = R"(
  1961. OpCapability Shader
  1962. %1 = OpExtInstImport "GLSL.std.450"
  1963. OpMemoryModel Logical GLSL450
  1964. OpEntryPoint Fragment %4 "main"
  1965. OpExecutionMode %4 OriginUpperLeft
  1966. OpSource ESSL 320
  1967. OpName %4 "main"
  1968. %2 = OpTypeVoid
  1969. %3 = OpTypeFunction %2
  1970. %6 = OpTypeBool
  1971. %7 = OpConstantFalse %6
  1972. %4 = OpFunction %2 None %3
  1973. %12 = OpLabel
  1974. OpBranch %13
  1975. %13 = OpLabel
  1976. OpLoopMerge %15 %14 None
  1977. OpBranchConditional %7 %5 %15
  1978. %5 = OpLabel
  1979. OpSelectionMerge %11 None
  1980. OpBranchConditional %7 %9 %10
  1981. %9 = OpLabel
  1982. OpBranch %11
  1983. %10 = OpLabel
  1984. OpBranch %14
  1985. %11 = OpLabel
  1986. OpBranch %14
  1987. %14 = OpLabel
  1988. OpBranch %13
  1989. %15 = OpLabel
  1990. OpReturn
  1991. OpFunctionEnd
  1992. )";
  1993. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1994. const auto consumer = nullptr;
  1995. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1996. spvtools::ValidatorOptions validator_options;
  1997. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1998. kConsoleMessageConsumer));
  1999. TransformationContext transformation_context(
  2000. MakeUnique<FactManager>(context.get()), validator_options);
  2001. ASSERT_FALSE(TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {})
  2002. .IsApplicable(context.get(), transformation_context));
  2003. }
  2004. TEST(TransformationFlattenConditionalBranchTest, ContainsSynonymCreation) {
  2005. std::string shader = R"(
  2006. OpCapability Shader
  2007. %1 = OpExtInstImport "GLSL.std.450"
  2008. OpMemoryModel Logical GLSL450
  2009. OpEntryPoint Fragment %4 "main"
  2010. OpExecutionMode %4 OriginUpperLeft
  2011. OpSource ESSL 320
  2012. OpName %4 "main"
  2013. %2 = OpTypeVoid
  2014. %3 = OpTypeFunction %2
  2015. %6 = OpTypeBool
  2016. %7 = OpConstantFalse %6
  2017. %8 = OpTypeInt 32 0
  2018. %9 = OpTypePointer Function %8
  2019. %10 = OpConstant %8 42
  2020. %80 = OpConstant %8 0
  2021. %4 = OpFunction %2 None %3
  2022. %11 = OpLabel
  2023. %20 = OpVariable %9 Function
  2024. OpBranch %12
  2025. %12 = OpLabel
  2026. OpSelectionMerge %31 None
  2027. OpBranchConditional %7 %30 %31
  2028. %30 = OpLabel
  2029. OpStore %20 %10
  2030. %21 = OpLoad %8 %20
  2031. OpBranch %31
  2032. %31 = OpLabel
  2033. OpBranch %14
  2034. %14 = OpLabel
  2035. OpReturn
  2036. OpFunctionEnd
  2037. )";
  2038. const auto env = SPV_ENV_UNIVERSAL_1_3;
  2039. const auto consumer = nullptr;
  2040. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  2041. spvtools::ValidatorOptions validator_options;
  2042. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  2043. kConsoleMessageConsumer));
  2044. TransformationContext transformation_context(
  2045. MakeUnique<FactManager>(context.get()), validator_options);
  2046. transformation_context.GetFactManager()->AddFactDataSynonym(
  2047. MakeDataDescriptor(10, {}), MakeDataDescriptor(21, {}));
  2048. ASSERT_FALSE(
  2049. TransformationFlattenConditionalBranch(
  2050. 12, true, 0, 0, 0,
  2051. {MakeSideEffectWrapperInfo(
  2052. MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 100, 101),
  2053. MakeSideEffectWrapperInfo(
  2054. MakeInstructionDescriptor(21, spv::Op::OpLoad, 0), 102, 103, 104,
  2055. 105, 106, 80)})
  2056. .IsApplicable(context.get(), transformation_context));
  2057. }
  2058. } // namespace
  2059. } // namespace fuzz
  2060. } // namespace spvtools