loop_fission.cpp 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489
  1. // Copyright (c) 2018 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/opt/loop_fission.h"
  15. #include <memory>
  16. #include <vector>
  17. #include "gmock/gmock.h"
  18. #include "source/opt/loop_utils.h"
  19. #include "test/opt/assembly_builder.h"
  20. #include "test/opt/function_utils.h"
  21. #include "test/opt/pass_fixture.h"
  22. #include "test/opt/pass_utils.h"
  23. namespace spvtools {
  24. namespace opt {
  25. namespace {
  26. using ::testing::UnorderedElementsAre;
  27. using FissionClassTest = PassTest<::testing::Test>;
  28. /*
  29. Generated from the following GLSL
  30. #version 430
  31. void main(void) {
  32. float A[10];
  33. float B[10];
  34. for (int i = 0; i < 10; i++) {
  35. A[i] = B[i];
  36. B[i] = A[i];
  37. }
  38. }
  39. Result should be equivalent to:
  40. void main(void) {
  41. float A[10];
  42. float B[10];
  43. for (int i = 0; i < 10; i++) {
  44. A[i] = B[i];
  45. }
  46. for (int i = 0; i < 10; i++) {
  47. B[i] = A[i];
  48. }
  49. }
  50. */
  51. TEST_F(FissionClassTest, SimpleFission) {
  52. // clang-format off
  53. // With LocalMultiStoreElimPass
  54. const std::string source = R"(OpCapability Shader
  55. %1 = OpExtInstImport "GLSL.std.450"
  56. OpMemoryModel Logical GLSL450
  57. OpEntryPoint Fragment %2 "main"
  58. OpExecutionMode %2 OriginUpperLeft
  59. OpSource GLSL 430
  60. OpName %2 "main"
  61. OpName %3 "i"
  62. OpName %4 "A"
  63. OpName %5 "B"
  64. %6 = OpTypeVoid
  65. %7 = OpTypeFunction %6
  66. %8 = OpTypeInt 32 1
  67. %9 = OpTypePointer Function %8
  68. %10 = OpConstant %8 0
  69. %11 = OpConstant %8 10
  70. %12 = OpTypeBool
  71. %13 = OpTypeFloat 32
  72. %14 = OpTypeInt 32 0
  73. %15 = OpConstant %14 10
  74. %16 = OpTypeArray %13 %15
  75. %17 = OpTypePointer Function %16
  76. %18 = OpTypePointer Function %13
  77. %19 = OpConstant %8 1
  78. %2 = OpFunction %6 None %7
  79. %20 = OpLabel
  80. %3 = OpVariable %9 Function
  81. %4 = OpVariable %17 Function
  82. %5 = OpVariable %17 Function
  83. OpBranch %21
  84. %21 = OpLabel
  85. %22 = OpPhi %8 %10 %20 %23 %24
  86. OpLoopMerge %25 %24 None
  87. OpBranch %26
  88. %26 = OpLabel
  89. %27 = OpSLessThan %12 %22 %11
  90. OpBranchConditional %27 %28 %25
  91. %28 = OpLabel
  92. %29 = OpAccessChain %18 %5 %22
  93. %30 = OpLoad %13 %29
  94. %31 = OpAccessChain %18 %4 %22
  95. OpStore %31 %30
  96. %32 = OpAccessChain %18 %4 %22
  97. %33 = OpLoad %13 %32
  98. %34 = OpAccessChain %18 %5 %22
  99. OpStore %34 %33
  100. OpBranch %24
  101. %24 = OpLabel
  102. %23 = OpIAdd %8 %22 %19
  103. OpBranch %21
  104. %25 = OpLabel
  105. OpReturn
  106. OpFunctionEnd
  107. )";
  108. const std::string expected = R"(OpCapability Shader
  109. %1 = OpExtInstImport "GLSL.std.450"
  110. OpMemoryModel Logical GLSL450
  111. OpEntryPoint Fragment %2 "main"
  112. OpExecutionMode %2 OriginUpperLeft
  113. OpSource GLSL 430
  114. OpName %2 "main"
  115. OpName %3 "i"
  116. OpName %4 "A"
  117. OpName %5 "B"
  118. %6 = OpTypeVoid
  119. %7 = OpTypeFunction %6
  120. %8 = OpTypeInt 32 1
  121. %9 = OpTypePointer Function %8
  122. %10 = OpConstant %8 0
  123. %11 = OpConstant %8 10
  124. %12 = OpTypeBool
  125. %13 = OpTypeFloat 32
  126. %14 = OpTypeInt 32 0
  127. %15 = OpConstant %14 10
  128. %16 = OpTypeArray %13 %15
  129. %17 = OpTypePointer Function %16
  130. %18 = OpTypePointer Function %13
  131. %19 = OpConstant %8 1
  132. %2 = OpFunction %6 None %7
  133. %20 = OpLabel
  134. %3 = OpVariable %9 Function
  135. %4 = OpVariable %17 Function
  136. %5 = OpVariable %17 Function
  137. OpBranch %35
  138. %35 = OpLabel
  139. %36 = OpPhi %8 %10 %20 %47 %46
  140. OpLoopMerge %48 %46 None
  141. OpBranch %37
  142. %37 = OpLabel
  143. %38 = OpSLessThan %12 %36 %11
  144. OpBranchConditional %38 %39 %48
  145. %39 = OpLabel
  146. %40 = OpAccessChain %18 %5 %36
  147. %41 = OpLoad %13 %40
  148. %42 = OpAccessChain %18 %4 %36
  149. OpStore %42 %41
  150. OpBranch %46
  151. %46 = OpLabel
  152. %47 = OpIAdd %8 %36 %19
  153. OpBranch %35
  154. %48 = OpLabel
  155. OpBranch %21
  156. %21 = OpLabel
  157. %22 = OpPhi %8 %10 %48 %23 %24
  158. OpLoopMerge %25 %24 None
  159. OpBranch %26
  160. %26 = OpLabel
  161. %27 = OpSLessThan %12 %22 %11
  162. OpBranchConditional %27 %28 %25
  163. %28 = OpLabel
  164. %32 = OpAccessChain %18 %4 %22
  165. %33 = OpLoad %13 %32
  166. %34 = OpAccessChain %18 %5 %22
  167. OpStore %34 %33
  168. OpBranch %24
  169. %24 = OpLabel
  170. %23 = OpIAdd %8 %22 %19
  171. OpBranch %21
  172. %25 = OpLabel
  173. OpReturn
  174. OpFunctionEnd
  175. )";
  176. // clang-format on
  177. std::unique_ptr<IRContext> context =
  178. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  179. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  180. Module* module = context->module();
  181. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  182. << source << std::endl;
  183. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  184. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  185. // Check that the loop will NOT be split when provided with a pass-through
  186. // register pressure functor which just returns false.
  187. SinglePassRunAndCheck<LoopFissionPass>(
  188. source, source, true,
  189. [](const RegisterLiveness::RegionRegisterLiveness&) { return false; });
  190. }
  191. /*
  192. Generated from the following GLSL
  193. #version 430
  194. void main(void) {
  195. float A[10];
  196. float B[10];
  197. for (int i = 0; i < 10; i++) {
  198. A[i] = B[i];
  199. B[i] = A[i+1];
  200. }
  201. }
  202. This loop should not be split, as the i+1 dependence would be broken by
  203. splitting the loop.
  204. */
  205. TEST_F(FissionClassTest, FissionInterdependency) {
  206. // clang-format off
  207. // With LocalMultiStoreElimPass
  208. const std::string source = R"(OpCapability Shader
  209. %1 = OpExtInstImport "GLSL.std.450"
  210. OpMemoryModel Logical GLSL450
  211. OpEntryPoint Fragment %2 "main"
  212. OpExecutionMode %2 OriginUpperLeft
  213. OpSource GLSL 430
  214. OpName %2 "main"
  215. OpName %3 "i"
  216. OpName %4 "A"
  217. OpName %5 "B"
  218. %6 = OpTypeVoid
  219. %7 = OpTypeFunction %6
  220. %8 = OpTypeInt 32 1
  221. %9 = OpTypePointer Function %8
  222. %10 = OpConstant %8 0
  223. %11 = OpConstant %8 10
  224. %12 = OpTypeBool
  225. %13 = OpTypeFloat 32
  226. %14 = OpTypeInt 32 0
  227. %15 = OpConstant %14 10
  228. %16 = OpTypeArray %13 %15
  229. %17 = OpTypePointer Function %16
  230. %18 = OpTypePointer Function %13
  231. %19 = OpConstant %8 1
  232. %2 = OpFunction %6 None %7
  233. %20 = OpLabel
  234. %3 = OpVariable %9 Function
  235. %4 = OpVariable %17 Function
  236. %5 = OpVariable %17 Function
  237. OpBranch %21
  238. %21 = OpLabel
  239. %22 = OpPhi %8 %10 %20 %23 %24
  240. OpLoopMerge %25 %24 None
  241. OpBranch %26
  242. %26 = OpLabel
  243. %27 = OpSLessThan %12 %22 %11
  244. OpBranchConditional %27 %28 %25
  245. %28 = OpLabel
  246. %29 = OpAccessChain %18 %5 %22
  247. %30 = OpLoad %13 %29
  248. %31 = OpAccessChain %18 %4 %22
  249. OpStore %31 %30
  250. %32 = OpIAdd %8 %22 %19
  251. %33 = OpAccessChain %18 %4 %32
  252. %34 = OpLoad %13 %33
  253. %35 = OpAccessChain %18 %5 %22
  254. OpStore %35 %34
  255. OpBranch %24
  256. %24 = OpLabel
  257. %23 = OpIAdd %8 %22 %19
  258. OpBranch %21
  259. %25 = OpLabel
  260. OpReturn
  261. OpFunctionEnd
  262. )";
  263. // clang-format on
  264. std::unique_ptr<IRContext> context =
  265. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  266. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  267. Module* module = context->module();
  268. EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
  269. << source << std::endl;
  270. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  271. SinglePassRunAndCheck<LoopFissionPass>(source, source, true);
  272. }
  273. /*
  274. Generated from the following GLSL
  275. #version 430
  276. void main(void) {
  277. float A[10];
  278. float B[10];
  279. for (int i = 0; i < 10; i++) {
  280. A[i] = B[i];
  281. B[i+1] = A[i];
  282. }
  283. }
  284. This should not be split as the load B[i] is dependent on the store B[i+1]
  285. */
  286. TEST_F(FissionClassTest, FissionInterdependency2) {
  287. // clang-format off
  288. // With LocalMultiStoreElimPass
  289. const std::string source = R"(OpCapability Shader
  290. %1 = OpExtInstImport "GLSL.std.450"
  291. OpMemoryModel Logical GLSL450
  292. OpEntryPoint Fragment %2 "main"
  293. OpExecutionMode %2 OriginUpperLeft
  294. OpSource GLSL 430
  295. OpName %2 "main"
  296. OpName %3 "i"
  297. OpName %4 "A"
  298. OpName %5 "B"
  299. %6 = OpTypeVoid
  300. %7 = OpTypeFunction %6
  301. %8 = OpTypeInt 32 1
  302. %9 = OpTypePointer Function %8
  303. %10 = OpConstant %8 0
  304. %11 = OpConstant %8 10
  305. %12 = OpTypeBool
  306. %13 = OpTypeFloat 32
  307. %14 = OpTypeInt 32 0
  308. %15 = OpConstant %14 10
  309. %16 = OpTypeArray %13 %15
  310. %17 = OpTypePointer Function %16
  311. %18 = OpTypePointer Function %13
  312. %19 = OpConstant %8 1
  313. %2 = OpFunction %6 None %7
  314. %20 = OpLabel
  315. %3 = OpVariable %9 Function
  316. %4 = OpVariable %17 Function
  317. %5 = OpVariable %17 Function
  318. OpBranch %21
  319. %21 = OpLabel
  320. %22 = OpPhi %8 %10 %20 %23 %24
  321. OpLoopMerge %25 %24 None
  322. OpBranch %26
  323. %26 = OpLabel
  324. %27 = OpSLessThan %12 %22 %11
  325. OpBranchConditional %27 %28 %25
  326. %28 = OpLabel
  327. %29 = OpAccessChain %18 %5 %22
  328. %30 = OpLoad %13 %29
  329. %31 = OpAccessChain %18 %4 %22
  330. OpStore %31 %30
  331. %32 = OpIAdd %8 %22 %19
  332. %33 = OpAccessChain %18 %4 %22
  333. %34 = OpLoad %13 %33
  334. %35 = OpAccessChain %18 %5 %32
  335. OpStore %35 %34
  336. OpBranch %24
  337. %24 = OpLabel
  338. %23 = OpIAdd %8 %22 %19
  339. OpBranch %21
  340. %25 = OpLabel
  341. OpReturn
  342. OpFunctionEnd
  343. )";
  344. // clang-format on
  345. std::unique_ptr<IRContext> context =
  346. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  347. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  348. Module* module = context->module();
  349. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  350. << source << std::endl;
  351. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  352. SinglePassRunAndCheck<LoopFissionPass>(source, source, true);
  353. }
  354. /*
  355. #version 430
  356. void main(void) {
  357. float A[10];
  358. float B[10];
  359. float C[10]
  360. float D[10]
  361. for (int i = 0; i < 10; i++) {
  362. A[i] = B[i];
  363. B[i] = A[i];
  364. C[i] = D[i];
  365. D[i] = C[i];
  366. }
  367. }
  368. This should be split into the equivalent of:
  369. for (int i = 0; i < 10; i++) {
  370. A[i] = B[i];
  371. B[i] = A[i];
  372. }
  373. for (int i = 0; i < 10; i++) {
  374. C[i] = D[i];
  375. D[i] = C[i];
  376. }
  377. We then check that the loop is broken into four for loops like so, if the pass
  378. is run twice:
  379. for (int i = 0; i < 10; i++)
  380. A[i] = B[i];
  381. for (int i = 0; i < 10; i++)
  382. B[i] = A[i];
  383. for (int i = 0; i < 10; i++)
  384. C[i] = D[i];
  385. for (int i = 0; i < 10; i++)
  386. D[i] = C[i];
  387. */
  388. TEST_F(FissionClassTest, FissionMultipleLoadStores) {
  389. // clang-format off
  390. // With LocalMultiStoreElimPass
  391. const std::string source = R"(
  392. OpCapability Shader
  393. %1 = OpExtInstImport "GLSL.std.450"
  394. OpMemoryModel Logical GLSL450
  395. OpEntryPoint Fragment %2 "main"
  396. OpExecutionMode %2 OriginUpperLeft
  397. OpSource GLSL 430
  398. OpName %2 "main"
  399. OpName %3 "i"
  400. OpName %4 "A"
  401. OpName %5 "B"
  402. OpName %6 "C"
  403. OpName %7 "D"
  404. %8 = OpTypeVoid
  405. %9 = OpTypeFunction %8
  406. %10 = OpTypeInt 32 1
  407. %11 = OpTypePointer Function %10
  408. %12 = OpConstant %10 0
  409. %13 = OpConstant %10 10
  410. %14 = OpTypeBool
  411. %15 = OpTypeFloat 32
  412. %16 = OpTypeInt 32 0
  413. %17 = OpConstant %16 10
  414. %18 = OpTypeArray %15 %17
  415. %19 = OpTypePointer Function %18
  416. %20 = OpTypePointer Function %15
  417. %21 = OpConstant %10 1
  418. %2 = OpFunction %8 None %9
  419. %22 = OpLabel
  420. %3 = OpVariable %11 Function
  421. %4 = OpVariable %19 Function
  422. %5 = OpVariable %19 Function
  423. %6 = OpVariable %19 Function
  424. %7 = OpVariable %19 Function
  425. OpBranch %23
  426. %23 = OpLabel
  427. %24 = OpPhi %10 %12 %22 %25 %26
  428. OpLoopMerge %27 %26 None
  429. OpBranch %28
  430. %28 = OpLabel
  431. %29 = OpSLessThan %14 %24 %13
  432. OpBranchConditional %29 %30 %27
  433. %30 = OpLabel
  434. %31 = OpAccessChain %20 %5 %24
  435. %32 = OpLoad %15 %31
  436. %33 = OpAccessChain %20 %4 %24
  437. OpStore %33 %32
  438. %34 = OpAccessChain %20 %4 %24
  439. %35 = OpLoad %15 %34
  440. %36 = OpAccessChain %20 %5 %24
  441. OpStore %36 %35
  442. %37 = OpAccessChain %20 %7 %24
  443. %38 = OpLoad %15 %37
  444. %39 = OpAccessChain %20 %6 %24
  445. OpStore %39 %38
  446. %40 = OpAccessChain %20 %6 %24
  447. %41 = OpLoad %15 %40
  448. %42 = OpAccessChain %20 %7 %24
  449. OpStore %42 %41
  450. OpBranch %26
  451. %26 = OpLabel
  452. %25 = OpIAdd %10 %24 %21
  453. OpBranch %23
  454. %27 = OpLabel
  455. OpReturn
  456. OpFunctionEnd
  457. )";
  458. const std::string expected = R"(OpCapability Shader
  459. %1 = OpExtInstImport "GLSL.std.450"
  460. OpMemoryModel Logical GLSL450
  461. OpEntryPoint Fragment %2 "main"
  462. OpExecutionMode %2 OriginUpperLeft
  463. OpSource GLSL 430
  464. OpName %2 "main"
  465. OpName %3 "i"
  466. OpName %4 "A"
  467. OpName %5 "B"
  468. OpName %6 "C"
  469. OpName %7 "D"
  470. %8 = OpTypeVoid
  471. %9 = OpTypeFunction %8
  472. %10 = OpTypeInt 32 1
  473. %11 = OpTypePointer Function %10
  474. %12 = OpConstant %10 0
  475. %13 = OpConstant %10 10
  476. %14 = OpTypeBool
  477. %15 = OpTypeFloat 32
  478. %16 = OpTypeInt 32 0
  479. %17 = OpConstant %16 10
  480. %18 = OpTypeArray %15 %17
  481. %19 = OpTypePointer Function %18
  482. %20 = OpTypePointer Function %15
  483. %21 = OpConstant %10 1
  484. %2 = OpFunction %8 None %9
  485. %22 = OpLabel
  486. %3 = OpVariable %11 Function
  487. %4 = OpVariable %19 Function
  488. %5 = OpVariable %19 Function
  489. %6 = OpVariable %19 Function
  490. %7 = OpVariable %19 Function
  491. OpBranch %43
  492. %43 = OpLabel
  493. %44 = OpPhi %10 %12 %22 %61 %60
  494. OpLoopMerge %62 %60 None
  495. OpBranch %45
  496. %45 = OpLabel
  497. %46 = OpSLessThan %14 %44 %13
  498. OpBranchConditional %46 %47 %62
  499. %47 = OpLabel
  500. %48 = OpAccessChain %20 %5 %44
  501. %49 = OpLoad %15 %48
  502. %50 = OpAccessChain %20 %4 %44
  503. OpStore %50 %49
  504. %51 = OpAccessChain %20 %4 %44
  505. %52 = OpLoad %15 %51
  506. %53 = OpAccessChain %20 %5 %44
  507. OpStore %53 %52
  508. OpBranch %60
  509. %60 = OpLabel
  510. %61 = OpIAdd %10 %44 %21
  511. OpBranch %43
  512. %62 = OpLabel
  513. OpBranch %23
  514. %23 = OpLabel
  515. %24 = OpPhi %10 %12 %62 %25 %26
  516. OpLoopMerge %27 %26 None
  517. OpBranch %28
  518. %28 = OpLabel
  519. %29 = OpSLessThan %14 %24 %13
  520. OpBranchConditional %29 %30 %27
  521. %30 = OpLabel
  522. %37 = OpAccessChain %20 %7 %24
  523. %38 = OpLoad %15 %37
  524. %39 = OpAccessChain %20 %6 %24
  525. OpStore %39 %38
  526. %40 = OpAccessChain %20 %6 %24
  527. %41 = OpLoad %15 %40
  528. %42 = OpAccessChain %20 %7 %24
  529. OpStore %42 %41
  530. OpBranch %26
  531. %26 = OpLabel
  532. %25 = OpIAdd %10 %24 %21
  533. OpBranch %23
  534. %27 = OpLabel
  535. OpReturn
  536. OpFunctionEnd
  537. )";
  538. const std::string expected_multiple_passes = R"(OpCapability Shader
  539. %1 = OpExtInstImport "GLSL.std.450"
  540. OpMemoryModel Logical GLSL450
  541. OpEntryPoint Fragment %2 "main"
  542. OpExecutionMode %2 OriginUpperLeft
  543. OpSource GLSL 430
  544. OpName %2 "main"
  545. OpName %3 "i"
  546. OpName %4 "A"
  547. OpName %5 "B"
  548. OpName %6 "C"
  549. OpName %7 "D"
  550. %8 = OpTypeVoid
  551. %9 = OpTypeFunction %8
  552. %10 = OpTypeInt 32 1
  553. %11 = OpTypePointer Function %10
  554. %12 = OpConstant %10 0
  555. %13 = OpConstant %10 10
  556. %14 = OpTypeBool
  557. %15 = OpTypeFloat 32
  558. %16 = OpTypeInt 32 0
  559. %17 = OpConstant %16 10
  560. %18 = OpTypeArray %15 %17
  561. %19 = OpTypePointer Function %18
  562. %20 = OpTypePointer Function %15
  563. %21 = OpConstant %10 1
  564. %2 = OpFunction %8 None %9
  565. %22 = OpLabel
  566. %3 = OpVariable %11 Function
  567. %4 = OpVariable %19 Function
  568. %5 = OpVariable %19 Function
  569. %6 = OpVariable %19 Function
  570. %7 = OpVariable %19 Function
  571. OpBranch %63
  572. %63 = OpLabel
  573. %64 = OpPhi %10 %12 %22 %75 %74
  574. OpLoopMerge %76 %74 None
  575. OpBranch %65
  576. %65 = OpLabel
  577. %66 = OpSLessThan %14 %64 %13
  578. OpBranchConditional %66 %67 %76
  579. %67 = OpLabel
  580. %68 = OpAccessChain %20 %5 %64
  581. %69 = OpLoad %15 %68
  582. %70 = OpAccessChain %20 %4 %64
  583. OpStore %70 %69
  584. OpBranch %74
  585. %74 = OpLabel
  586. %75 = OpIAdd %10 %64 %21
  587. OpBranch %63
  588. %76 = OpLabel
  589. OpBranch %43
  590. %43 = OpLabel
  591. %44 = OpPhi %10 %12 %76 %61 %60
  592. OpLoopMerge %62 %60 None
  593. OpBranch %45
  594. %45 = OpLabel
  595. %46 = OpSLessThan %14 %44 %13
  596. OpBranchConditional %46 %47 %62
  597. %47 = OpLabel
  598. %51 = OpAccessChain %20 %4 %44
  599. %52 = OpLoad %15 %51
  600. %53 = OpAccessChain %20 %5 %44
  601. OpStore %53 %52
  602. OpBranch %60
  603. %60 = OpLabel
  604. %61 = OpIAdd %10 %44 %21
  605. OpBranch %43
  606. %62 = OpLabel
  607. OpBranch %77
  608. %77 = OpLabel
  609. %78 = OpPhi %10 %12 %62 %89 %88
  610. OpLoopMerge %90 %88 None
  611. OpBranch %79
  612. %79 = OpLabel
  613. %80 = OpSLessThan %14 %78 %13
  614. OpBranchConditional %80 %81 %90
  615. %81 = OpLabel
  616. %82 = OpAccessChain %20 %7 %78
  617. %83 = OpLoad %15 %82
  618. %84 = OpAccessChain %20 %6 %78
  619. OpStore %84 %83
  620. OpBranch %88
  621. %88 = OpLabel
  622. %89 = OpIAdd %10 %78 %21
  623. OpBranch %77
  624. %90 = OpLabel
  625. OpBranch %23
  626. %23 = OpLabel
  627. %24 = OpPhi %10 %12 %90 %25 %26
  628. OpLoopMerge %27 %26 None
  629. OpBranch %28
  630. %28 = OpLabel
  631. %29 = OpSLessThan %14 %24 %13
  632. OpBranchConditional %29 %30 %27
  633. %30 = OpLabel
  634. %40 = OpAccessChain %20 %6 %24
  635. %41 = OpLoad %15 %40
  636. %42 = OpAccessChain %20 %7 %24
  637. OpStore %42 %41
  638. OpBranch %26
  639. %26 = OpLabel
  640. %25 = OpIAdd %10 %24 %21
  641. OpBranch %23
  642. %27 = OpLabel
  643. OpReturn
  644. OpFunctionEnd
  645. )";
  646. // clang-format on
  647. std::unique_ptr<IRContext> context =
  648. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  649. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  650. Module* module = context->module();
  651. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  652. << source << std::endl;
  653. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  654. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  655. // By passing 1 as argument we are using the constructor which makes the
  656. // criteria to split the loop be if the registers in the loop exceede 1. By
  657. // using this constructor we are also enabling multiple passes (disabled by
  658. // default).
  659. SinglePassRunAndCheck<LoopFissionPass>(source, expected_multiple_passes, true,
  660. 1);
  661. }
  662. /*
  663. #version 430
  664. void main(void) {
  665. int accumulator = 0;
  666. float X[10];
  667. float Y[10];
  668. for (int i = 0; i < 10; i++) {
  669. X[i] = Y[i];
  670. Y[i] = X[i];
  671. accumulator += i;
  672. }
  673. }
  674. This should be split into the equivalent of:
  675. #version 430
  676. void main(void) {
  677. int accumulator = 0;
  678. float X[10];
  679. float Y[10];
  680. for (int i = 0; i < 10; i++) {
  681. X[i] = Y[i];
  682. }
  683. for (int i = 0; i < 10; i++) {
  684. Y[i] = X[i];
  685. accumulator += i;
  686. }
  687. }
  688. */
  689. TEST_F(FissionClassTest, FissionWithAccumulator) {
  690. // clang-format off
  691. // With LocalMultiStoreElimPass
  692. const std::string source = R"(OpCapability Shader
  693. %1 = OpExtInstImport "GLSL.std.450"
  694. OpMemoryModel Logical GLSL450
  695. OpEntryPoint Fragment %2 "main"
  696. OpExecutionMode %2 OriginUpperLeft
  697. OpSource GLSL 430
  698. OpName %2 "main"
  699. OpName %3 "accumulator"
  700. OpName %4 "i"
  701. OpName %5 "X"
  702. OpName %6 "Y"
  703. %7 = OpTypeVoid
  704. %8 = OpTypeFunction %7
  705. %9 = OpTypeInt 32 1
  706. %10 = OpTypePointer Function %9
  707. %11 = OpConstant %9 0
  708. %12 = OpConstant %9 10
  709. %13 = OpTypeBool
  710. %14 = OpTypeFloat 32
  711. %15 = OpTypeInt 32 0
  712. %16 = OpConstant %15 10
  713. %17 = OpTypeArray %14 %16
  714. %18 = OpTypePointer Function %17
  715. %19 = OpTypePointer Function %14
  716. %20 = OpConstant %9 1
  717. %2 = OpFunction %7 None %8
  718. %21 = OpLabel
  719. %3 = OpVariable %10 Function
  720. %4 = OpVariable %10 Function
  721. %5 = OpVariable %18 Function
  722. %6 = OpVariable %18 Function
  723. OpBranch %22
  724. %22 = OpLabel
  725. %23 = OpPhi %9 %11 %21 %24 %25
  726. %26 = OpPhi %9 %11 %21 %27 %25
  727. OpLoopMerge %28 %25 None
  728. OpBranch %29
  729. %29 = OpLabel
  730. %30 = OpSLessThan %13 %26 %12
  731. OpBranchConditional %30 %31 %28
  732. %31 = OpLabel
  733. %32 = OpAccessChain %19 %6 %26
  734. %33 = OpLoad %14 %32
  735. %34 = OpAccessChain %19 %5 %26
  736. OpStore %34 %33
  737. %35 = OpAccessChain %19 %5 %26
  738. %36 = OpLoad %14 %35
  739. %37 = OpAccessChain %19 %6 %26
  740. OpStore %37 %36
  741. %24 = OpIAdd %9 %23 %26
  742. OpBranch %25
  743. %25 = OpLabel
  744. %27 = OpIAdd %9 %26 %20
  745. OpBranch %22
  746. %28 = OpLabel
  747. OpReturn
  748. OpFunctionEnd
  749. )";
  750. const std::string expected = R"(OpCapability Shader
  751. %1 = OpExtInstImport "GLSL.std.450"
  752. OpMemoryModel Logical GLSL450
  753. OpEntryPoint Fragment %2 "main"
  754. OpExecutionMode %2 OriginUpperLeft
  755. OpSource GLSL 430
  756. OpName %2 "main"
  757. OpName %3 "accumulator"
  758. OpName %4 "i"
  759. OpName %5 "X"
  760. OpName %6 "Y"
  761. %7 = OpTypeVoid
  762. %8 = OpTypeFunction %7
  763. %9 = OpTypeInt 32 1
  764. %10 = OpTypePointer Function %9
  765. %11 = OpConstant %9 0
  766. %12 = OpConstant %9 10
  767. %13 = OpTypeBool
  768. %14 = OpTypeFloat 32
  769. %15 = OpTypeInt 32 0
  770. %16 = OpConstant %15 10
  771. %17 = OpTypeArray %14 %16
  772. %18 = OpTypePointer Function %17
  773. %19 = OpTypePointer Function %14
  774. %20 = OpConstant %9 1
  775. %2 = OpFunction %7 None %8
  776. %21 = OpLabel
  777. %3 = OpVariable %10 Function
  778. %4 = OpVariable %10 Function
  779. %5 = OpVariable %18 Function
  780. %6 = OpVariable %18 Function
  781. OpBranch %38
  782. %38 = OpLabel
  783. %40 = OpPhi %9 %11 %21 %52 %51
  784. OpLoopMerge %53 %51 None
  785. OpBranch %41
  786. %41 = OpLabel
  787. %42 = OpSLessThan %13 %40 %12
  788. OpBranchConditional %42 %43 %53
  789. %43 = OpLabel
  790. %44 = OpAccessChain %19 %6 %40
  791. %45 = OpLoad %14 %44
  792. %46 = OpAccessChain %19 %5 %40
  793. OpStore %46 %45
  794. OpBranch %51
  795. %51 = OpLabel
  796. %52 = OpIAdd %9 %40 %20
  797. OpBranch %38
  798. %53 = OpLabel
  799. OpBranch %22
  800. %22 = OpLabel
  801. %23 = OpPhi %9 %11 %53 %24 %25
  802. %26 = OpPhi %9 %11 %53 %27 %25
  803. OpLoopMerge %28 %25 None
  804. OpBranch %29
  805. %29 = OpLabel
  806. %30 = OpSLessThan %13 %26 %12
  807. OpBranchConditional %30 %31 %28
  808. %31 = OpLabel
  809. %35 = OpAccessChain %19 %5 %26
  810. %36 = OpLoad %14 %35
  811. %37 = OpAccessChain %19 %6 %26
  812. OpStore %37 %36
  813. %24 = OpIAdd %9 %23 %26
  814. OpBranch %25
  815. %25 = OpLabel
  816. %27 = OpIAdd %9 %26 %20
  817. OpBranch %22
  818. %28 = OpLabel
  819. OpReturn
  820. OpFunctionEnd
  821. )";
  822. // clang-format on
  823. std::unique_ptr<IRContext> context =
  824. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  825. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  826. Module* module = context->module();
  827. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  828. << source << std::endl;
  829. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  830. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  831. }
  832. /*
  833. Generated from the following glsl:
  834. #version 430
  835. layout(location=0) out float x;
  836. layout(location=1) out float y;
  837. void main(void) {
  838. float accumulator_1 = 0;
  839. float accumulator_2 = 0;
  840. for (int i = 0; i < 10; i++) {
  841. accumulator_1 += i;
  842. accumulator_2 += i;
  843. }
  844. x = accumulator_1;
  845. y = accumulator_2;
  846. }
  847. Should be split into equivalent of:
  848. void main(void) {
  849. float accumulator_1 = 0;
  850. float accumulator_2 = 0;
  851. for (int i = 0; i < 10; i++) {
  852. accumulator_1 += i;
  853. }
  854. for (int i = 0; i < 10; i++) {
  855. accumulator_2 += i;
  856. }
  857. x = accumulator_1;
  858. y = accumulator_2;
  859. }
  860. */
  861. TEST_F(FissionClassTest, FissionWithPhisUsedOutwithLoop) {
  862. // clang-format off
  863. // With LocalMultiStoreElimPass
  864. const std::string source = R"(OpCapability Shader
  865. %1 = OpExtInstImport "GLSL.std.450"
  866. OpMemoryModel Logical GLSL450
  867. OpEntryPoint Fragment %2 "main" %3 %4
  868. OpExecutionMode %2 OriginUpperLeft
  869. OpSource GLSL 430
  870. OpName %2 "main"
  871. OpName %5 "accumulator_1"
  872. OpName %6 "accumulator_2"
  873. OpName %7 "i"
  874. OpName %3 "x"
  875. OpName %4 "y"
  876. OpDecorate %3 Location 0
  877. OpDecorate %4 Location 1
  878. %8 = OpTypeVoid
  879. %9 = OpTypeFunction %8
  880. %10 = OpTypeFloat 32
  881. %11 = OpTypePointer Function %10
  882. %12 = OpConstant %10 0
  883. %13 = OpTypeInt 32 1
  884. %14 = OpTypePointer Function %13
  885. %15 = OpConstant %13 0
  886. %16 = OpConstant %13 10
  887. %17 = OpTypeBool
  888. %18 = OpConstant %13 1
  889. %19 = OpTypePointer Output %10
  890. %3 = OpVariable %19 Output
  891. %4 = OpVariable %19 Output
  892. %2 = OpFunction %8 None %9
  893. %20 = OpLabel
  894. %5 = OpVariable %11 Function
  895. %6 = OpVariable %11 Function
  896. %7 = OpVariable %14 Function
  897. OpBranch %21
  898. %21 = OpLabel
  899. %22 = OpPhi %10 %12 %20 %23 %24
  900. %25 = OpPhi %10 %12 %20 %26 %24
  901. %27 = OpPhi %13 %15 %20 %28 %24
  902. OpLoopMerge %29 %24 None
  903. OpBranch %30
  904. %30 = OpLabel
  905. %31 = OpSLessThan %17 %27 %16
  906. OpBranchConditional %31 %32 %29
  907. %32 = OpLabel
  908. %33 = OpConvertSToF %10 %27
  909. %26 = OpFAdd %10 %25 %33
  910. %34 = OpConvertSToF %10 %27
  911. %23 = OpFAdd %10 %22 %34
  912. OpBranch %24
  913. %24 = OpLabel
  914. %28 = OpIAdd %13 %27 %18
  915. OpStore %7 %28
  916. OpBranch %21
  917. %29 = OpLabel
  918. OpStore %3 %25
  919. OpStore %4 %22
  920. OpReturn
  921. OpFunctionEnd
  922. )";
  923. const std::string expected = R"(OpCapability Shader
  924. %1 = OpExtInstImport "GLSL.std.450"
  925. OpMemoryModel Logical GLSL450
  926. OpEntryPoint Fragment %2 "main" %3 %4
  927. OpExecutionMode %2 OriginUpperLeft
  928. OpSource GLSL 430
  929. OpName %2 "main"
  930. OpName %5 "accumulator_1"
  931. OpName %6 "accumulator_2"
  932. OpName %7 "i"
  933. OpName %3 "x"
  934. OpName %4 "y"
  935. OpDecorate %3 Location 0
  936. OpDecorate %4 Location 1
  937. %8 = OpTypeVoid
  938. %9 = OpTypeFunction %8
  939. %10 = OpTypeFloat 32
  940. %11 = OpTypePointer Function %10
  941. %12 = OpConstant %10 0
  942. %13 = OpTypeInt 32 1
  943. %14 = OpTypePointer Function %13
  944. %15 = OpConstant %13 0
  945. %16 = OpConstant %13 10
  946. %17 = OpTypeBool
  947. %18 = OpConstant %13 1
  948. %19 = OpTypePointer Output %10
  949. %3 = OpVariable %19 Output
  950. %4 = OpVariable %19 Output
  951. %2 = OpFunction %8 None %9
  952. %20 = OpLabel
  953. %5 = OpVariable %11 Function
  954. %6 = OpVariable %11 Function
  955. %7 = OpVariable %14 Function
  956. OpBranch %35
  957. %35 = OpLabel
  958. %37 = OpPhi %10 %12 %20 %43 %46
  959. %38 = OpPhi %13 %15 %20 %47 %46
  960. OpLoopMerge %48 %46 None
  961. OpBranch %39
  962. %39 = OpLabel
  963. %40 = OpSLessThan %17 %38 %16
  964. OpBranchConditional %40 %41 %48
  965. %41 = OpLabel
  966. %42 = OpConvertSToF %10 %38
  967. %43 = OpFAdd %10 %37 %42
  968. OpBranch %46
  969. %46 = OpLabel
  970. %47 = OpIAdd %13 %38 %18
  971. OpStore %7 %47
  972. OpBranch %35
  973. %48 = OpLabel
  974. OpBranch %21
  975. %21 = OpLabel
  976. %22 = OpPhi %10 %12 %48 %23 %24
  977. %27 = OpPhi %13 %15 %48 %28 %24
  978. OpLoopMerge %29 %24 None
  979. OpBranch %30
  980. %30 = OpLabel
  981. %31 = OpSLessThan %17 %27 %16
  982. OpBranchConditional %31 %32 %29
  983. %32 = OpLabel
  984. %34 = OpConvertSToF %10 %27
  985. %23 = OpFAdd %10 %22 %34
  986. OpBranch %24
  987. %24 = OpLabel
  988. %28 = OpIAdd %13 %27 %18
  989. OpStore %7 %28
  990. OpBranch %21
  991. %29 = OpLabel
  992. OpStore %3 %37
  993. OpStore %4 %22
  994. OpReturn
  995. OpFunctionEnd
  996. )";
  997. // clang-format on
  998. std::unique_ptr<IRContext> context =
  999. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  1000. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1001. Module* module = context->module();
  1002. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1003. << source << std::endl;
  1004. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  1005. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  1006. }
  1007. /*
  1008. #version 430
  1009. void main(void) {
  1010. float A[10][10];
  1011. float B[10][10];
  1012. for (int i = 0; i < 10; i++) {
  1013. for (int j = 0; j < 10; j++) {
  1014. A[i][j] = B[i][j];
  1015. B[i][j] = A[i][j];
  1016. }
  1017. }
  1018. }
  1019. Should be split into equivalent of:
  1020. #version 430
  1021. void main(void) {
  1022. float A[10][10];
  1023. float B[10][10];
  1024. for (int i = 0; i < 10; i++) {
  1025. for (int j = 0; j < 10; j++) {
  1026. A[i][j] = B[i][j];
  1027. }
  1028. for (int j = 0; j < 10; j++) {
  1029. B[i][j] = A[i][j];
  1030. }
  1031. }
  1032. }
  1033. */
  1034. TEST_F(FissionClassTest, FissionNested) {
  1035. // clang-format off
  1036. // With LocalMultiStoreElimPass
  1037. const std::string source = R"(
  1038. OpCapability Shader
  1039. %1 = OpExtInstImport "GLSL.std.450"
  1040. OpMemoryModel Logical GLSL450
  1041. OpEntryPoint Fragment %2 "main"
  1042. OpExecutionMode %2 OriginUpperLeft
  1043. OpSource GLSL 430
  1044. OpName %2 "main"
  1045. OpName %3 "i"
  1046. OpName %4 "j"
  1047. OpName %5 "A"
  1048. OpName %6 "B"
  1049. %7 = OpTypeVoid
  1050. %8 = OpTypeFunction %7
  1051. %9 = OpTypeInt 32 1
  1052. %10 = OpTypePointer Function %9
  1053. %11 = OpConstant %9 0
  1054. %12 = OpConstant %9 10
  1055. %13 = OpTypeBool
  1056. %14 = OpTypeFloat 32
  1057. %15 = OpTypeInt 32 0
  1058. %16 = OpConstant %15 10
  1059. %17 = OpTypeArray %14 %16
  1060. %18 = OpTypeArray %17 %16
  1061. %19 = OpTypePointer Function %18
  1062. %20 = OpTypePointer Function %14
  1063. %21 = OpConstant %9 1
  1064. %2 = OpFunction %7 None %8
  1065. %22 = OpLabel
  1066. %3 = OpVariable %10 Function
  1067. %4 = OpVariable %10 Function
  1068. %5 = OpVariable %19 Function
  1069. %6 = OpVariable %19 Function
  1070. OpStore %3 %11
  1071. OpBranch %23
  1072. %23 = OpLabel
  1073. %24 = OpPhi %9 %11 %22 %25 %26
  1074. OpLoopMerge %27 %26 None
  1075. OpBranch %28
  1076. %28 = OpLabel
  1077. %29 = OpSLessThan %13 %24 %12
  1078. OpBranchConditional %29 %30 %27
  1079. %30 = OpLabel
  1080. OpStore %4 %11
  1081. OpBranch %31
  1082. %31 = OpLabel
  1083. %32 = OpPhi %9 %11 %30 %33 %34
  1084. OpLoopMerge %35 %34 None
  1085. OpBranch %36
  1086. %36 = OpLabel
  1087. %37 = OpSLessThan %13 %32 %12
  1088. OpBranchConditional %37 %38 %35
  1089. %38 = OpLabel
  1090. %39 = OpAccessChain %20 %6 %24 %32
  1091. %40 = OpLoad %14 %39
  1092. %41 = OpAccessChain %20 %5 %24 %32
  1093. OpStore %41 %40
  1094. %42 = OpAccessChain %20 %5 %24 %32
  1095. %43 = OpLoad %14 %42
  1096. %44 = OpAccessChain %20 %6 %24 %32
  1097. OpStore %44 %43
  1098. OpBranch %34
  1099. %34 = OpLabel
  1100. %33 = OpIAdd %9 %32 %21
  1101. OpStore %4 %33
  1102. OpBranch %31
  1103. %35 = OpLabel
  1104. OpBranch %26
  1105. %26 = OpLabel
  1106. %25 = OpIAdd %9 %24 %21
  1107. OpStore %3 %25
  1108. OpBranch %23
  1109. %27 = OpLabel
  1110. OpReturn
  1111. OpFunctionEnd
  1112. )";
  1113. const std::string expected = R"(OpCapability Shader
  1114. %1 = OpExtInstImport "GLSL.std.450"
  1115. OpMemoryModel Logical GLSL450
  1116. OpEntryPoint Fragment %2 "main"
  1117. OpExecutionMode %2 OriginUpperLeft
  1118. OpSource GLSL 430
  1119. OpName %2 "main"
  1120. OpName %3 "i"
  1121. OpName %4 "j"
  1122. OpName %5 "A"
  1123. OpName %6 "B"
  1124. %7 = OpTypeVoid
  1125. %8 = OpTypeFunction %7
  1126. %9 = OpTypeInt 32 1
  1127. %10 = OpTypePointer Function %9
  1128. %11 = OpConstant %9 0
  1129. %12 = OpConstant %9 10
  1130. %13 = OpTypeBool
  1131. %14 = OpTypeFloat 32
  1132. %15 = OpTypeInt 32 0
  1133. %16 = OpConstant %15 10
  1134. %17 = OpTypeArray %14 %16
  1135. %18 = OpTypeArray %17 %16
  1136. %19 = OpTypePointer Function %18
  1137. %20 = OpTypePointer Function %14
  1138. %21 = OpConstant %9 1
  1139. %2 = OpFunction %7 None %8
  1140. %22 = OpLabel
  1141. %3 = OpVariable %10 Function
  1142. %4 = OpVariable %10 Function
  1143. %5 = OpVariable %19 Function
  1144. %6 = OpVariable %19 Function
  1145. OpStore %3 %11
  1146. OpBranch %23
  1147. %23 = OpLabel
  1148. %24 = OpPhi %9 %11 %22 %25 %26
  1149. OpLoopMerge %27 %26 None
  1150. OpBranch %28
  1151. %28 = OpLabel
  1152. %29 = OpSLessThan %13 %24 %12
  1153. OpBranchConditional %29 %30 %27
  1154. %30 = OpLabel
  1155. OpStore %4 %11
  1156. OpBranch %45
  1157. %45 = OpLabel
  1158. %46 = OpPhi %9 %11 %30 %57 %56
  1159. OpLoopMerge %58 %56 None
  1160. OpBranch %47
  1161. %47 = OpLabel
  1162. %48 = OpSLessThan %13 %46 %12
  1163. OpBranchConditional %48 %49 %58
  1164. %49 = OpLabel
  1165. %50 = OpAccessChain %20 %6 %24 %46
  1166. %51 = OpLoad %14 %50
  1167. %52 = OpAccessChain %20 %5 %24 %46
  1168. OpStore %52 %51
  1169. OpBranch %56
  1170. %56 = OpLabel
  1171. %57 = OpIAdd %9 %46 %21
  1172. OpStore %4 %57
  1173. OpBranch %45
  1174. %58 = OpLabel
  1175. OpBranch %31
  1176. %31 = OpLabel
  1177. %32 = OpPhi %9 %11 %58 %33 %34
  1178. OpLoopMerge %35 %34 None
  1179. OpBranch %36
  1180. %36 = OpLabel
  1181. %37 = OpSLessThan %13 %32 %12
  1182. OpBranchConditional %37 %38 %35
  1183. %38 = OpLabel
  1184. %42 = OpAccessChain %20 %5 %24 %32
  1185. %43 = OpLoad %14 %42
  1186. %44 = OpAccessChain %20 %6 %24 %32
  1187. OpStore %44 %43
  1188. OpBranch %34
  1189. %34 = OpLabel
  1190. %33 = OpIAdd %9 %32 %21
  1191. OpStore %4 %33
  1192. OpBranch %31
  1193. %35 = OpLabel
  1194. OpBranch %26
  1195. %26 = OpLabel
  1196. %25 = OpIAdd %9 %24 %21
  1197. OpStore %3 %25
  1198. OpBranch %23
  1199. %27 = OpLabel
  1200. OpReturn
  1201. OpFunctionEnd
  1202. )";
  1203. // clang-format on
  1204. std::unique_ptr<IRContext> context =
  1205. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  1206. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1207. Module* module = context->module();
  1208. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1209. << source << std::endl;
  1210. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  1211. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  1212. }
  1213. /*
  1214. #version 430
  1215. void main(void) {
  1216. int accumulator = 0;
  1217. float A[10];
  1218. float B[10];
  1219. float C[10];
  1220. for (int i = 0; i < 10; i++) {
  1221. int c = C[i];
  1222. A[i] = B[i];
  1223. B[i] = A[i] + c;
  1224. }
  1225. }
  1226. This loop should not be split as we would have to break the order of the loads
  1227. to do so. It would be grouped into two sets:
  1228. 1
  1229. int c = C[i];
  1230. B[i] = A[i] + c;
  1231. 2
  1232. A[i] = B[i];
  1233. To keep the load C[i] in the same order we would need to put B[i] ahead of that
  1234. */
  1235. TEST_F(FissionClassTest, FissionLoad) {
  1236. // clang-format off
  1237. // With LocalMultiStoreElimPass
  1238. const std::string source = R"(OpCapability Shader
  1239. %1 = OpExtInstImport "GLSL.std.450"
  1240. OpMemoryModel Logical GLSL450
  1241. OpEntryPoint Fragment %2 "main"
  1242. OpExecutionMode %2 OriginUpperLeft
  1243. OpSource GLSL 430
  1244. OpName %2 "main"
  1245. OpName %3 "i"
  1246. OpName %4 "c"
  1247. OpName %5 "C"
  1248. OpName %6 "A"
  1249. OpName %7 "B"
  1250. %8 = OpTypeVoid
  1251. %9 = OpTypeFunction %8
  1252. %10 = OpTypeInt 32 1
  1253. %11 = OpTypePointer Function %10
  1254. %12 = OpConstant %10 0
  1255. %13 = OpConstant %10 10
  1256. %14 = OpTypeBool
  1257. %15 = OpTypeFloat 32
  1258. %16 = OpTypePointer Function %15
  1259. %17 = OpTypeInt 32 0
  1260. %18 = OpConstant %17 10
  1261. %19 = OpTypeArray %15 %18
  1262. %20 = OpTypePointer Function %19
  1263. %21 = OpConstant %10 1
  1264. %2 = OpFunction %8 None %9
  1265. %22 = OpLabel
  1266. %3 = OpVariable %11 Function
  1267. %4 = OpVariable %16 Function
  1268. %5 = OpVariable %20 Function
  1269. %6 = OpVariable %20 Function
  1270. %7 = OpVariable %20 Function
  1271. OpBranch %23
  1272. %23 = OpLabel
  1273. %24 = OpPhi %10 %12 %22 %25 %26
  1274. OpLoopMerge %27 %26 None
  1275. OpBranch %28
  1276. %28 = OpLabel
  1277. %29 = OpSLessThan %14 %24 %13
  1278. OpBranchConditional %29 %30 %27
  1279. %30 = OpLabel
  1280. %31 = OpAccessChain %16 %5 %24
  1281. %32 = OpLoad %15 %31
  1282. OpStore %4 %32
  1283. %33 = OpAccessChain %16 %7 %24
  1284. %34 = OpLoad %15 %33
  1285. %35 = OpAccessChain %16 %6 %24
  1286. OpStore %35 %34
  1287. %36 = OpAccessChain %16 %6 %24
  1288. %37 = OpLoad %15 %36
  1289. %38 = OpFAdd %15 %37 %32
  1290. %39 = OpAccessChain %16 %7 %24
  1291. OpStore %39 %38
  1292. OpBranch %26
  1293. %26 = OpLabel
  1294. %25 = OpIAdd %10 %24 %21
  1295. OpBranch %23
  1296. %27 = OpLabel
  1297. OpReturn
  1298. OpFunctionEnd
  1299. )";
  1300. // clang-format on
  1301. std::unique_ptr<IRContext> context =
  1302. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  1303. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1304. Module* module = context->module();
  1305. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1306. << source << std::endl;
  1307. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  1308. SinglePassRunAndCheck<LoopFissionPass>(source, source, true);
  1309. }
  1310. /*
  1311. #version 430
  1312. layout(location=0) flat in int condition;
  1313. void main(void) {
  1314. float A[10];
  1315. float B[10];
  1316. for (int i = 0; i < 10; i++) {
  1317. if (condition == 1)
  1318. A[i] = B[i];
  1319. else
  1320. B[i] = A[i];
  1321. }
  1322. }
  1323. When this is split we leave the condition check and control flow inplace and
  1324. leave its removal for dead code elimination.
  1325. #version 430
  1326. layout(location=0) flat in int condition;
  1327. void main(void) {
  1328. float A[10];
  1329. float B[10];
  1330. for (int i = 0; i < 10; i++) {
  1331. if (condition == 1)
  1332. A[i] = B[i];
  1333. else
  1334. ;
  1335. }
  1336. for (int i = 0; i < 10; i++) {
  1337. if (condition == 1)
  1338. ;
  1339. else
  1340. B[i] = A[i];
  1341. }
  1342. }
  1343. */
  1344. TEST_F(FissionClassTest, FissionControlFlow) {
  1345. // clang-format off
  1346. // With LocalMultiStoreElimPass
  1347. const std::string source = R"(
  1348. OpCapability Shader
  1349. %1 = OpExtInstImport "GLSL.std.450"
  1350. OpMemoryModel Logical GLSL450
  1351. OpEntryPoint Fragment %2 "main" %3
  1352. OpExecutionMode %2 OriginUpperLeft
  1353. OpSource GLSL 430
  1354. OpName %2 "main"
  1355. OpName %4 "i"
  1356. OpName %3 "condition"
  1357. OpName %5 "A"
  1358. OpName %6 "B"
  1359. OpDecorate %3 Flat
  1360. OpDecorate %3 Location 0
  1361. %7 = OpTypeVoid
  1362. %8 = OpTypeFunction %7
  1363. %9 = OpTypeInt 32 1
  1364. %10 = OpTypePointer Function %9
  1365. %11 = OpConstant %9 0
  1366. %12 = OpConstant %9 10
  1367. %13 = OpTypeBool
  1368. %14 = OpTypePointer Input %9
  1369. %3 = OpVariable %14 Input
  1370. %15 = OpConstant %9 1
  1371. %16 = OpTypeFloat 32
  1372. %17 = OpTypeInt 32 0
  1373. %18 = OpConstant %17 10
  1374. %19 = OpTypeArray %16 %18
  1375. %20 = OpTypePointer Function %19
  1376. %21 = OpTypePointer Function %16
  1377. %2 = OpFunction %7 None %8
  1378. %22 = OpLabel
  1379. %4 = OpVariable %10 Function
  1380. %5 = OpVariable %20 Function
  1381. %6 = OpVariable %20 Function
  1382. %31 = OpLoad %9 %3
  1383. OpStore %4 %11
  1384. OpBranch %23
  1385. %23 = OpLabel
  1386. %24 = OpPhi %9 %11 %22 %25 %26
  1387. OpLoopMerge %27 %26 None
  1388. OpBranch %28
  1389. %28 = OpLabel
  1390. %29 = OpSLessThan %13 %24 %12
  1391. OpBranchConditional %29 %30 %27
  1392. %30 = OpLabel
  1393. %32 = OpIEqual %13 %31 %15
  1394. OpSelectionMerge %33 None
  1395. OpBranchConditional %32 %34 %35
  1396. %34 = OpLabel
  1397. %36 = OpAccessChain %21 %6 %24
  1398. %37 = OpLoad %16 %36
  1399. %38 = OpAccessChain %21 %5 %24
  1400. OpStore %38 %37
  1401. OpBranch %33
  1402. %35 = OpLabel
  1403. %39 = OpAccessChain %21 %5 %24
  1404. %40 = OpLoad %16 %39
  1405. %41 = OpAccessChain %21 %6 %24
  1406. OpStore %41 %40
  1407. OpBranch %33
  1408. %33 = OpLabel
  1409. OpBranch %26
  1410. %26 = OpLabel
  1411. %25 = OpIAdd %9 %24 %15
  1412. OpStore %4 %25
  1413. OpBranch %23
  1414. %27 = OpLabel
  1415. OpReturn
  1416. OpFunctionEnd
  1417. )";
  1418. const std::string expected = R"(OpCapability Shader
  1419. %1 = OpExtInstImport "GLSL.std.450"
  1420. OpMemoryModel Logical GLSL450
  1421. OpEntryPoint Fragment %2 "main" %3
  1422. OpExecutionMode %2 OriginUpperLeft
  1423. OpSource GLSL 430
  1424. OpName %2 "main"
  1425. OpName %4 "i"
  1426. OpName %3 "condition"
  1427. OpName %5 "A"
  1428. OpName %6 "B"
  1429. OpDecorate %3 Flat
  1430. OpDecorate %3 Location 0
  1431. %7 = OpTypeVoid
  1432. %8 = OpTypeFunction %7
  1433. %9 = OpTypeInt 32 1
  1434. %10 = OpTypePointer Function %9
  1435. %11 = OpConstant %9 0
  1436. %12 = OpConstant %9 10
  1437. %13 = OpTypeBool
  1438. %14 = OpTypePointer Input %9
  1439. %3 = OpVariable %14 Input
  1440. %15 = OpConstant %9 1
  1441. %16 = OpTypeFloat 32
  1442. %17 = OpTypeInt 32 0
  1443. %18 = OpConstant %17 10
  1444. %19 = OpTypeArray %16 %18
  1445. %20 = OpTypePointer Function %19
  1446. %21 = OpTypePointer Function %16
  1447. %2 = OpFunction %7 None %8
  1448. %22 = OpLabel
  1449. %4 = OpVariable %10 Function
  1450. %5 = OpVariable %20 Function
  1451. %6 = OpVariable %20 Function
  1452. %23 = OpLoad %9 %3
  1453. OpStore %4 %11
  1454. OpBranch %42
  1455. %42 = OpLabel
  1456. %43 = OpPhi %9 %11 %22 %58 %57
  1457. OpLoopMerge %59 %57 None
  1458. OpBranch %44
  1459. %44 = OpLabel
  1460. %45 = OpSLessThan %13 %43 %12
  1461. OpBranchConditional %45 %46 %59
  1462. %46 = OpLabel
  1463. %47 = OpIEqual %13 %23 %15
  1464. OpSelectionMerge %56 None
  1465. OpBranchConditional %47 %52 %48
  1466. %48 = OpLabel
  1467. OpBranch %56
  1468. %52 = OpLabel
  1469. %53 = OpAccessChain %21 %6 %43
  1470. %54 = OpLoad %16 %53
  1471. %55 = OpAccessChain %21 %5 %43
  1472. OpStore %55 %54
  1473. OpBranch %56
  1474. %56 = OpLabel
  1475. OpBranch %57
  1476. %57 = OpLabel
  1477. %58 = OpIAdd %9 %43 %15
  1478. OpStore %4 %58
  1479. OpBranch %42
  1480. %59 = OpLabel
  1481. OpBranch %24
  1482. %24 = OpLabel
  1483. %25 = OpPhi %9 %11 %59 %26 %27
  1484. OpLoopMerge %28 %27 None
  1485. OpBranch %29
  1486. %29 = OpLabel
  1487. %30 = OpSLessThan %13 %25 %12
  1488. OpBranchConditional %30 %31 %28
  1489. %31 = OpLabel
  1490. %32 = OpIEqual %13 %23 %15
  1491. OpSelectionMerge %33 None
  1492. OpBranchConditional %32 %34 %35
  1493. %34 = OpLabel
  1494. OpBranch %33
  1495. %35 = OpLabel
  1496. %39 = OpAccessChain %21 %5 %25
  1497. %40 = OpLoad %16 %39
  1498. %41 = OpAccessChain %21 %6 %25
  1499. OpStore %41 %40
  1500. OpBranch %33
  1501. %33 = OpLabel
  1502. OpBranch %27
  1503. %27 = OpLabel
  1504. %26 = OpIAdd %9 %25 %15
  1505. OpStore %4 %26
  1506. OpBranch %24
  1507. %28 = OpLabel
  1508. OpReturn
  1509. OpFunctionEnd
  1510. )";
  1511. // clang-format on
  1512. std::unique_ptr<IRContext> context =
  1513. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  1514. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1515. Module* module = context->module();
  1516. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1517. << source << std::endl;
  1518. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  1519. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  1520. }
  1521. /*
  1522. #version 430
  1523. void main(void) {
  1524. float A[10];
  1525. float B[10];
  1526. for (int i = 0; i < 10; i++) {
  1527. if (i == 1)
  1528. B[i] = A[i];
  1529. else if (i == 2)
  1530. A[i] = B[i];
  1531. else
  1532. A[i] = 0;
  1533. }
  1534. }
  1535. After running the pass with multiple splits enabled (via register threshold of
  1536. 1) we expect the equivalent of:
  1537. #version 430
  1538. void main(void) {
  1539. float A[10];
  1540. float B[10];
  1541. for (int i = 0; i < 10; i++) {
  1542. if (i == 1)
  1543. B[i] = A[i];
  1544. else if (i == 2)
  1545. else
  1546. }
  1547. for (int i = 0; i < 10; i++) {
  1548. if (i == 1)
  1549. else if (i == 2)
  1550. A[i] = B[i];
  1551. else
  1552. }
  1553. for (int i = 0; i < 10; i++) {
  1554. if (i == 1)
  1555. else if (i == 2)
  1556. else
  1557. A[i] = 0;
  1558. }
  1559. }
  1560. */
  1561. TEST_F(FissionClassTest, FissionControlFlow2) {
  1562. // clang-format off
  1563. // With LocalMultiStoreElimPass
  1564. const std::string source = R"(OpCapability Shader
  1565. %1 = OpExtInstImport "GLSL.std.450"
  1566. OpMemoryModel Logical GLSL450
  1567. OpEntryPoint Fragment %2 "main"
  1568. OpExecutionMode %2 OriginUpperLeft
  1569. OpSource GLSL 430
  1570. OpName %2 "main"
  1571. OpName %3 "i"
  1572. OpName %4 "B"
  1573. OpName %5 "A"
  1574. %6 = OpTypeVoid
  1575. %7 = OpTypeFunction %6
  1576. %8 = OpTypeInt 32 1
  1577. %9 = OpTypePointer Function %8
  1578. %10 = OpConstant %8 0
  1579. %11 = OpConstant %8 10
  1580. %12 = OpTypeBool
  1581. %13 = OpConstant %8 1
  1582. %14 = OpTypeFloat 32
  1583. %15 = OpTypeInt 32 0
  1584. %16 = OpConstant %15 10
  1585. %17 = OpTypeArray %14 %16
  1586. %18 = OpTypePointer Function %17
  1587. %19 = OpTypePointer Function %14
  1588. %20 = OpConstant %8 2
  1589. %21 = OpConstant %14 0
  1590. %2 = OpFunction %6 None %7
  1591. %22 = OpLabel
  1592. %3 = OpVariable %9 Function
  1593. %4 = OpVariable %18 Function
  1594. %5 = OpVariable %18 Function
  1595. OpStore %3 %10
  1596. OpBranch %23
  1597. %23 = OpLabel
  1598. %24 = OpPhi %8 %10 %22 %25 %26
  1599. OpLoopMerge %27 %26 None
  1600. OpBranch %28
  1601. %28 = OpLabel
  1602. %29 = OpSLessThan %12 %24 %11
  1603. OpBranchConditional %29 %30 %27
  1604. %30 = OpLabel
  1605. %31 = OpIEqual %12 %24 %13
  1606. OpSelectionMerge %32 None
  1607. OpBranchConditional %31 %33 %34
  1608. %33 = OpLabel
  1609. %35 = OpAccessChain %19 %5 %24
  1610. %36 = OpLoad %14 %35
  1611. %37 = OpAccessChain %19 %4 %24
  1612. OpStore %37 %36
  1613. OpBranch %32
  1614. %34 = OpLabel
  1615. %38 = OpIEqual %12 %24 %20
  1616. OpSelectionMerge %39 None
  1617. OpBranchConditional %38 %40 %41
  1618. %40 = OpLabel
  1619. %42 = OpAccessChain %19 %4 %24
  1620. %43 = OpLoad %14 %42
  1621. %44 = OpAccessChain %19 %5 %24
  1622. OpStore %44 %43
  1623. OpBranch %39
  1624. %41 = OpLabel
  1625. %45 = OpAccessChain %19 %5 %24
  1626. OpStore %45 %21
  1627. OpBranch %39
  1628. %39 = OpLabel
  1629. OpBranch %32
  1630. %32 = OpLabel
  1631. OpBranch %26
  1632. %26 = OpLabel
  1633. %25 = OpIAdd %8 %24 %13
  1634. OpStore %3 %25
  1635. OpBranch %23
  1636. %27 = OpLabel
  1637. OpReturn
  1638. OpFunctionEnd
  1639. )";
  1640. const std::string expected = R"(OpCapability Shader
  1641. %1 = OpExtInstImport "GLSL.std.450"
  1642. OpMemoryModel Logical GLSL450
  1643. OpEntryPoint Fragment %2 "main"
  1644. OpExecutionMode %2 OriginUpperLeft
  1645. OpSource GLSL 430
  1646. OpName %2 "main"
  1647. OpName %3 "i"
  1648. OpName %4 "B"
  1649. OpName %5 "A"
  1650. %6 = OpTypeVoid
  1651. %7 = OpTypeFunction %6
  1652. %8 = OpTypeInt 32 1
  1653. %9 = OpTypePointer Function %8
  1654. %10 = OpConstant %8 0
  1655. %11 = OpConstant %8 10
  1656. %12 = OpTypeBool
  1657. %13 = OpConstant %8 1
  1658. %14 = OpTypeFloat 32
  1659. %15 = OpTypeInt 32 0
  1660. %16 = OpConstant %15 10
  1661. %17 = OpTypeArray %14 %16
  1662. %18 = OpTypePointer Function %17
  1663. %19 = OpTypePointer Function %14
  1664. %20 = OpConstant %8 2
  1665. %21 = OpConstant %14 0
  1666. %2 = OpFunction %6 None %7
  1667. %22 = OpLabel
  1668. %3 = OpVariable %9 Function
  1669. %4 = OpVariable %18 Function
  1670. %5 = OpVariable %18 Function
  1671. OpStore %3 %10
  1672. OpBranch %46
  1673. %46 = OpLabel
  1674. %47 = OpPhi %8 %10 %22 %67 %66
  1675. OpLoopMerge %68 %66 None
  1676. OpBranch %48
  1677. %48 = OpLabel
  1678. %49 = OpSLessThan %12 %47 %11
  1679. OpBranchConditional %49 %50 %68
  1680. %50 = OpLabel
  1681. %51 = OpIEqual %12 %47 %13
  1682. OpSelectionMerge %65 None
  1683. OpBranchConditional %51 %61 %52
  1684. %52 = OpLabel
  1685. %53 = OpIEqual %12 %47 %20
  1686. OpSelectionMerge %60 None
  1687. OpBranchConditional %53 %56 %54
  1688. %54 = OpLabel
  1689. OpBranch %60
  1690. %56 = OpLabel
  1691. OpBranch %60
  1692. %60 = OpLabel
  1693. OpBranch %65
  1694. %61 = OpLabel
  1695. %62 = OpAccessChain %19 %5 %47
  1696. %63 = OpLoad %14 %62
  1697. %64 = OpAccessChain %19 %4 %47
  1698. OpStore %64 %63
  1699. OpBranch %65
  1700. %65 = OpLabel
  1701. OpBranch %66
  1702. %66 = OpLabel
  1703. %67 = OpIAdd %8 %47 %13
  1704. OpStore %3 %67
  1705. OpBranch %46
  1706. %68 = OpLabel
  1707. OpBranch %69
  1708. %69 = OpLabel
  1709. %70 = OpPhi %8 %10 %68 %87 %86
  1710. OpLoopMerge %88 %86 None
  1711. OpBranch %71
  1712. %71 = OpLabel
  1713. %72 = OpSLessThan %12 %70 %11
  1714. OpBranchConditional %72 %73 %88
  1715. %73 = OpLabel
  1716. %74 = OpIEqual %12 %70 %13
  1717. OpSelectionMerge %85 None
  1718. OpBranchConditional %74 %84 %75
  1719. %75 = OpLabel
  1720. %76 = OpIEqual %12 %70 %20
  1721. OpSelectionMerge %83 None
  1722. OpBranchConditional %76 %79 %77
  1723. %77 = OpLabel
  1724. OpBranch %83
  1725. %79 = OpLabel
  1726. %80 = OpAccessChain %19 %4 %70
  1727. %81 = OpLoad %14 %80
  1728. %82 = OpAccessChain %19 %5 %70
  1729. OpStore %82 %81
  1730. OpBranch %83
  1731. %83 = OpLabel
  1732. OpBranch %85
  1733. %84 = OpLabel
  1734. OpBranch %85
  1735. %85 = OpLabel
  1736. OpBranch %86
  1737. %86 = OpLabel
  1738. %87 = OpIAdd %8 %70 %13
  1739. OpStore %3 %87
  1740. OpBranch %69
  1741. %88 = OpLabel
  1742. OpBranch %23
  1743. %23 = OpLabel
  1744. %24 = OpPhi %8 %10 %88 %25 %26
  1745. OpLoopMerge %27 %26 None
  1746. OpBranch %28
  1747. %28 = OpLabel
  1748. %29 = OpSLessThan %12 %24 %11
  1749. OpBranchConditional %29 %30 %27
  1750. %30 = OpLabel
  1751. %31 = OpIEqual %12 %24 %13
  1752. OpSelectionMerge %32 None
  1753. OpBranchConditional %31 %33 %34
  1754. %33 = OpLabel
  1755. OpBranch %32
  1756. %34 = OpLabel
  1757. %38 = OpIEqual %12 %24 %20
  1758. OpSelectionMerge %39 None
  1759. OpBranchConditional %38 %40 %41
  1760. %40 = OpLabel
  1761. OpBranch %39
  1762. %41 = OpLabel
  1763. %45 = OpAccessChain %19 %5 %24
  1764. OpStore %45 %21
  1765. OpBranch %39
  1766. %39 = OpLabel
  1767. OpBranch %32
  1768. %32 = OpLabel
  1769. OpBranch %26
  1770. %26 = OpLabel
  1771. %25 = OpIAdd %8 %24 %13
  1772. OpStore %3 %25
  1773. OpBranch %23
  1774. %27 = OpLabel
  1775. OpReturn
  1776. OpFunctionEnd
  1777. )";
  1778. // clang-format on
  1779. std::unique_ptr<IRContext> context =
  1780. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  1781. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1782. Module* module = context->module();
  1783. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1784. << source << std::endl;
  1785. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  1786. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true, 1);
  1787. }
  1788. /*
  1789. #version 430
  1790. layout(location=0) flat in int condition;
  1791. void main(void) {
  1792. float A[10];
  1793. float B[10];
  1794. for (int i = 0; i < 10; i++) {
  1795. B[i] = A[i];
  1796. memoryBarrier();
  1797. A[i] = B[i];
  1798. }
  1799. }
  1800. This should not be split due to the memory barrier.
  1801. */
  1802. TEST_F(FissionClassTest, FissionBarrier) {
  1803. // clang-format off
  1804. // With LocalMultiStoreElimPass
  1805. const std::string source = R"(OpCapability Shader
  1806. %1 = OpExtInstImport "GLSL.std.450"
  1807. OpMemoryModel Logical GLSL450
  1808. OpEntryPoint Fragment %2 "main" %3
  1809. OpExecutionMode %2 OriginUpperLeft
  1810. OpSource GLSL 430
  1811. OpName %2 "main"
  1812. OpName %4 "i"
  1813. OpName %5 "B"
  1814. OpName %6 "A"
  1815. OpName %3 "condition"
  1816. OpDecorate %3 Flat
  1817. OpDecorate %3 Location 0
  1818. %7 = OpTypeVoid
  1819. %8 = OpTypeFunction %7
  1820. %9 = OpTypeInt 32 1
  1821. %10 = OpTypePointer Function %9
  1822. %11 = OpConstant %9 0
  1823. %12 = OpConstant %9 10
  1824. %13 = OpTypeBool
  1825. %14 = OpTypeFloat 32
  1826. %15 = OpTypeInt 32 0
  1827. %16 = OpConstant %15 10
  1828. %17 = OpTypeArray %14 %16
  1829. %18 = OpTypePointer Function %17
  1830. %19 = OpTypePointer Function %14
  1831. %20 = OpConstant %15 1
  1832. %21 = OpConstant %15 4048
  1833. %22 = OpConstant %9 1
  1834. %23 = OpTypePointer Input %9
  1835. %3 = OpVariable %23 Input
  1836. %2 = OpFunction %7 None %8
  1837. %24 = OpLabel
  1838. %4 = OpVariable %10 Function
  1839. %5 = OpVariable %18 Function
  1840. %6 = OpVariable %18 Function
  1841. OpStore %4 %11
  1842. OpBranch %25
  1843. %25 = OpLabel
  1844. %26 = OpPhi %9 %11 %24 %27 %28
  1845. OpLoopMerge %29 %28 None
  1846. OpBranch %30
  1847. %30 = OpLabel
  1848. %31 = OpSLessThan %13 %26 %12
  1849. OpBranchConditional %31 %32 %29
  1850. %32 = OpLabel
  1851. %33 = OpAccessChain %19 %6 %26
  1852. %34 = OpLoad %14 %33
  1853. %35 = OpAccessChain %19 %5 %26
  1854. OpStore %35 %34
  1855. OpMemoryBarrier %20 %21
  1856. %36 = OpAccessChain %19 %5 %26
  1857. %37 = OpLoad %14 %36
  1858. %38 = OpAccessChain %19 %6 %26
  1859. OpStore %38 %37
  1860. OpBranch %28
  1861. %28 = OpLabel
  1862. %27 = OpIAdd %9 %26 %22
  1863. OpStore %4 %27
  1864. OpBranch %25
  1865. %29 = OpLabel
  1866. OpReturn
  1867. OpFunctionEnd
  1868. )";
  1869. // clang-format on
  1870. std::unique_ptr<IRContext> context =
  1871. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  1872. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1873. Module* module = context->module();
  1874. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1875. << source << std::endl;
  1876. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  1877. SinglePassRunAndCheck<LoopFissionPass>(source, source, true);
  1878. }
  1879. /*
  1880. #version 430
  1881. void main(void) {
  1882. float A[10];
  1883. float B[10];
  1884. for (int i = 0; i < 10; i++) {
  1885. B[i] = A[i];
  1886. if ( i== 1)
  1887. break;
  1888. A[i] = B[i];
  1889. }
  1890. }
  1891. This should not be split due to the break.
  1892. */
  1893. TEST_F(FissionClassTest, FissionBreak) {
  1894. // clang-format off
  1895. // With LocalMultiStoreElimPass
  1896. const std::string source = R"(OpCapability Shader
  1897. %1 = OpExtInstImport "GLSL.std.450"
  1898. OpMemoryModel Logical GLSL450
  1899. OpEntryPoint Fragment %2 "main"
  1900. OpExecutionMode %2 OriginUpperLeft
  1901. OpSource GLSL 430
  1902. OpName %2 "main"
  1903. OpName %3 "i"
  1904. OpName %4 "B"
  1905. OpName %5 "A"
  1906. %6 = OpTypeVoid
  1907. %7 = OpTypeFunction %6
  1908. %8 = OpTypeInt 32 1
  1909. %9 = OpTypePointer Function %8
  1910. %10 = OpConstant %8 0
  1911. %11 = OpConstant %8 10
  1912. %12 = OpTypeBool
  1913. %13 = OpTypeFloat 32
  1914. %14 = OpTypeInt 32 0
  1915. %15 = OpConstant %14 10
  1916. %16 = OpTypeArray %13 %15
  1917. %17 = OpTypePointer Function %16
  1918. %18 = OpTypePointer Function %13
  1919. %19 = OpConstant %8 1
  1920. %2 = OpFunction %6 None %7
  1921. %20 = OpLabel
  1922. %3 = OpVariable %9 Function
  1923. %4 = OpVariable %17 Function
  1924. %5 = OpVariable %17 Function
  1925. OpStore %3 %10
  1926. OpBranch %21
  1927. %21 = OpLabel
  1928. %22 = OpPhi %8 %10 %20 %23 %24
  1929. OpLoopMerge %25 %24 None
  1930. OpBranch %26
  1931. %26 = OpLabel
  1932. %27 = OpSLessThan %12 %22 %11
  1933. OpBranchConditional %27 %28 %25
  1934. %28 = OpLabel
  1935. %29 = OpAccessChain %18 %5 %22
  1936. %30 = OpLoad %13 %29
  1937. %31 = OpAccessChain %18 %4 %22
  1938. OpStore %31 %30
  1939. %32 = OpIEqual %12 %22 %19
  1940. OpSelectionMerge %33 None
  1941. OpBranchConditional %32 %34 %33
  1942. %34 = OpLabel
  1943. OpBranch %25
  1944. %33 = OpLabel
  1945. %35 = OpAccessChain %18 %4 %22
  1946. %36 = OpLoad %13 %35
  1947. %37 = OpAccessChain %18 %5 %22
  1948. OpStore %37 %36
  1949. OpBranch %24
  1950. %24 = OpLabel
  1951. %23 = OpIAdd %8 %22 %19
  1952. OpStore %3 %23
  1953. OpBranch %21
  1954. %25 = OpLabel
  1955. OpReturn
  1956. OpFunctionEnd
  1957. )";
  1958. // clang-format on
  1959. std::unique_ptr<IRContext> context =
  1960. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  1961. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1962. Module* module = context->module();
  1963. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1964. << source << std::endl;
  1965. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  1966. SinglePassRunAndCheck<LoopFissionPass>(source, source, true);
  1967. }
  1968. /*
  1969. #version 430
  1970. void main(void) {
  1971. float A[10];
  1972. float B[10];
  1973. for (int i = 0; i < 10; i++) {
  1974. B[i] = A[i];
  1975. if ( i== 1)
  1976. continue;
  1977. A[i] = B[i];
  1978. }
  1979. }
  1980. This loop should be split into:
  1981. for (int i = 0; i < 10; i++) {
  1982. B[i] = A[i];
  1983. if ( i== 1)
  1984. continue;
  1985. }
  1986. for (int i = 0; i < 10; i++) {
  1987. if ( i== 1)
  1988. continue;
  1989. A[i] = B[i];
  1990. }
  1991. The continue block in the first loop is left to DCE.
  1992. }
  1993. */
  1994. TEST_F(FissionClassTest, FissionContinue) {
  1995. // clang-format off
  1996. // With LocalMultiStoreElimPass
  1997. const std::string source = R"(OpCapability Shader
  1998. %1 = OpExtInstImport "GLSL.std.450"
  1999. OpMemoryModel Logical GLSL450
  2000. OpEntryPoint Fragment %2 "main"
  2001. OpExecutionMode %2 OriginUpperLeft
  2002. OpSource GLSL 430
  2003. OpName %2 "main"
  2004. OpName %3 "i"
  2005. OpName %4 "B"
  2006. OpName %5 "A"
  2007. %6 = OpTypeVoid
  2008. %7 = OpTypeFunction %6
  2009. %8 = OpTypeInt 32 1
  2010. %9 = OpTypePointer Function %8
  2011. %10 = OpConstant %8 0
  2012. %11 = OpConstant %8 10
  2013. %12 = OpTypeBool
  2014. %13 = OpTypeFloat 32
  2015. %14 = OpTypeInt 32 0
  2016. %15 = OpConstant %14 10
  2017. %16 = OpTypeArray %13 %15
  2018. %17 = OpTypePointer Function %16
  2019. %18 = OpTypePointer Function %13
  2020. %19 = OpConstant %8 1
  2021. %2 = OpFunction %6 None %7
  2022. %20 = OpLabel
  2023. %3 = OpVariable %9 Function
  2024. %4 = OpVariable %17 Function
  2025. %5 = OpVariable %17 Function
  2026. OpStore %3 %10
  2027. OpBranch %21
  2028. %21 = OpLabel
  2029. %22 = OpPhi %8 %10 %20 %23 %24
  2030. OpLoopMerge %25 %24 None
  2031. OpBranch %26
  2032. %26 = OpLabel
  2033. %27 = OpSLessThan %12 %22 %11
  2034. OpBranchConditional %27 %28 %25
  2035. %28 = OpLabel
  2036. %29 = OpAccessChain %18 %5 %22
  2037. %30 = OpLoad %13 %29
  2038. %31 = OpAccessChain %18 %4 %22
  2039. OpStore %31 %30
  2040. %32 = OpIEqual %12 %22 %19
  2041. OpSelectionMerge %33 None
  2042. OpBranchConditional %32 %34 %33
  2043. %34 = OpLabel
  2044. OpBranch %24
  2045. %33 = OpLabel
  2046. %35 = OpAccessChain %18 %4 %22
  2047. %36 = OpLoad %13 %35
  2048. %37 = OpAccessChain %18 %5 %22
  2049. OpStore %37 %36
  2050. OpBranch %24
  2051. %24 = OpLabel
  2052. %23 = OpIAdd %8 %22 %19
  2053. OpStore %3 %23
  2054. OpBranch %21
  2055. %25 = OpLabel
  2056. OpReturn
  2057. OpFunctionEnd
  2058. )";
  2059. const std::string expected = R"(OpCapability Shader
  2060. %1 = OpExtInstImport "GLSL.std.450"
  2061. OpMemoryModel Logical GLSL450
  2062. OpEntryPoint Fragment %2 "main"
  2063. OpExecutionMode %2 OriginUpperLeft
  2064. OpSource GLSL 430
  2065. OpName %2 "main"
  2066. OpName %3 "i"
  2067. OpName %4 "B"
  2068. OpName %5 "A"
  2069. %6 = OpTypeVoid
  2070. %7 = OpTypeFunction %6
  2071. %8 = OpTypeInt 32 1
  2072. %9 = OpTypePointer Function %8
  2073. %10 = OpConstant %8 0
  2074. %11 = OpConstant %8 10
  2075. %12 = OpTypeBool
  2076. %13 = OpTypeFloat 32
  2077. %14 = OpTypeInt 32 0
  2078. %15 = OpConstant %14 10
  2079. %16 = OpTypeArray %13 %15
  2080. %17 = OpTypePointer Function %16
  2081. %18 = OpTypePointer Function %13
  2082. %19 = OpConstant %8 1
  2083. %2 = OpFunction %6 None %7
  2084. %20 = OpLabel
  2085. %3 = OpVariable %9 Function
  2086. %4 = OpVariable %17 Function
  2087. %5 = OpVariable %17 Function
  2088. OpStore %3 %10
  2089. OpBranch %38
  2090. %38 = OpLabel
  2091. %39 = OpPhi %8 %10 %20 %53 %52
  2092. OpLoopMerge %54 %52 None
  2093. OpBranch %40
  2094. %40 = OpLabel
  2095. %41 = OpSLessThan %12 %39 %11
  2096. OpBranchConditional %41 %42 %54
  2097. %42 = OpLabel
  2098. %43 = OpAccessChain %18 %5 %39
  2099. %44 = OpLoad %13 %43
  2100. %45 = OpAccessChain %18 %4 %39
  2101. OpStore %45 %44
  2102. %46 = OpIEqual %12 %39 %19
  2103. OpSelectionMerge %48 None
  2104. OpBranchConditional %46 %47 %48
  2105. %47 = OpLabel
  2106. OpBranch %52
  2107. %48 = OpLabel
  2108. OpBranch %52
  2109. %52 = OpLabel
  2110. %53 = OpIAdd %8 %39 %19
  2111. OpStore %3 %53
  2112. OpBranch %38
  2113. %54 = OpLabel
  2114. OpBranch %21
  2115. %21 = OpLabel
  2116. %22 = OpPhi %8 %10 %54 %23 %24
  2117. OpLoopMerge %25 %24 None
  2118. OpBranch %26
  2119. %26 = OpLabel
  2120. %27 = OpSLessThan %12 %22 %11
  2121. OpBranchConditional %27 %28 %25
  2122. %28 = OpLabel
  2123. %32 = OpIEqual %12 %22 %19
  2124. OpSelectionMerge %33 None
  2125. OpBranchConditional %32 %34 %33
  2126. %34 = OpLabel
  2127. OpBranch %24
  2128. %33 = OpLabel
  2129. %35 = OpAccessChain %18 %4 %22
  2130. %36 = OpLoad %13 %35
  2131. %37 = OpAccessChain %18 %5 %22
  2132. OpStore %37 %36
  2133. OpBranch %24
  2134. %24 = OpLabel
  2135. %23 = OpIAdd %8 %22 %19
  2136. OpStore %3 %23
  2137. OpBranch %21
  2138. %25 = OpLabel
  2139. OpReturn
  2140. OpFunctionEnd
  2141. )";
  2142. // clang-format on
  2143. std::unique_ptr<IRContext> context =
  2144. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  2145. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2146. Module* module = context->module();
  2147. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  2148. << source << std::endl;
  2149. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  2150. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  2151. }
  2152. /*
  2153. #version 430
  2154. void main(void) {
  2155. float A[10];
  2156. float B[10];
  2157. int i = 0;
  2158. do {
  2159. B[i] = A[i];
  2160. A[i] = B[i];
  2161. ++i;
  2162. } while (i < 10);
  2163. }
  2164. Check that this is split into:
  2165. int i = 0;
  2166. do {
  2167. B[i] = A[i];
  2168. ++i;
  2169. } while (i < 10);
  2170. i = 0;
  2171. do {
  2172. A[i] = B[i];
  2173. ++i;
  2174. } while (i < 10);
  2175. */
  2176. TEST_F(FissionClassTest, FissionDoWhile) {
  2177. // clang-format off
  2178. // With LocalMultiStoreElimPass
  2179. const std::string source = R"(OpCapability Shader
  2180. %1 = OpExtInstImport "GLSL.std.450"
  2181. OpMemoryModel Logical GLSL450
  2182. OpEntryPoint Fragment %2 "main"
  2183. OpExecutionMode %2 OriginUpperLeft
  2184. OpSource GLSL 430
  2185. OpName %2 "main"
  2186. OpName %3 "i"
  2187. OpName %4 "B"
  2188. OpName %5 "A"
  2189. %6 = OpTypeVoid
  2190. %7 = OpTypeFunction %6
  2191. %8 = OpTypeInt 32 1
  2192. %9 = OpTypePointer Function %8
  2193. %10 = OpConstant %8 0
  2194. %11 = OpTypeFloat 32
  2195. %12 = OpTypeInt 32 0
  2196. %13 = OpConstant %12 10
  2197. %14 = OpTypeArray %11 %13
  2198. %15 = OpTypePointer Function %14
  2199. %16 = OpTypePointer Function %11
  2200. %17 = OpConstant %8 1
  2201. %18 = OpConstant %8 10
  2202. %19 = OpTypeBool
  2203. %2 = OpFunction %6 None %7
  2204. %20 = OpLabel
  2205. %3 = OpVariable %9 Function
  2206. %4 = OpVariable %15 Function
  2207. %5 = OpVariable %15 Function
  2208. OpStore %3 %10
  2209. OpBranch %21
  2210. %21 = OpLabel
  2211. %22 = OpPhi %8 %10 %20 %23 %24
  2212. OpLoopMerge %25 %24 None
  2213. OpBranch %26
  2214. %26 = OpLabel
  2215. %27 = OpAccessChain %16 %5 %22
  2216. %28 = OpLoad %11 %27
  2217. %29 = OpAccessChain %16 %4 %22
  2218. OpStore %29 %28
  2219. %30 = OpAccessChain %16 %4 %22
  2220. %31 = OpLoad %11 %30
  2221. %32 = OpAccessChain %16 %5 %22
  2222. OpStore %32 %31
  2223. %23 = OpIAdd %8 %22 %17
  2224. OpStore %3 %23
  2225. OpBranch %24
  2226. %24 = OpLabel
  2227. %33 = OpSLessThan %19 %23 %18
  2228. OpBranchConditional %33 %21 %25
  2229. %25 = OpLabel
  2230. OpReturn
  2231. OpFunctionEnd
  2232. )";
  2233. const std::string expected = R"(OpCapability Shader
  2234. %1 = OpExtInstImport "GLSL.std.450"
  2235. OpMemoryModel Logical GLSL450
  2236. OpEntryPoint Fragment %2 "main"
  2237. OpExecutionMode %2 OriginUpperLeft
  2238. OpSource GLSL 430
  2239. OpName %2 "main"
  2240. OpName %3 "i"
  2241. OpName %4 "B"
  2242. OpName %5 "A"
  2243. %6 = OpTypeVoid
  2244. %7 = OpTypeFunction %6
  2245. %8 = OpTypeInt 32 1
  2246. %9 = OpTypePointer Function %8
  2247. %10 = OpConstant %8 0
  2248. %11 = OpTypeFloat 32
  2249. %12 = OpTypeInt 32 0
  2250. %13 = OpConstant %12 10
  2251. %14 = OpTypeArray %11 %13
  2252. %15 = OpTypePointer Function %14
  2253. %16 = OpTypePointer Function %11
  2254. %17 = OpConstant %8 1
  2255. %18 = OpConstant %8 10
  2256. %19 = OpTypeBool
  2257. %2 = OpFunction %6 None %7
  2258. %20 = OpLabel
  2259. %3 = OpVariable %9 Function
  2260. %4 = OpVariable %15 Function
  2261. %5 = OpVariable %15 Function
  2262. OpStore %3 %10
  2263. OpBranch %34
  2264. %34 = OpLabel
  2265. %35 = OpPhi %8 %10 %20 %43 %44
  2266. OpLoopMerge %46 %44 None
  2267. OpBranch %36
  2268. %36 = OpLabel
  2269. %37 = OpAccessChain %16 %5 %35
  2270. %38 = OpLoad %11 %37
  2271. %39 = OpAccessChain %16 %4 %35
  2272. OpStore %39 %38
  2273. %43 = OpIAdd %8 %35 %17
  2274. OpStore %3 %43
  2275. OpBranch %44
  2276. %44 = OpLabel
  2277. %45 = OpSLessThan %19 %43 %18
  2278. OpBranchConditional %45 %34 %46
  2279. %46 = OpLabel
  2280. OpBranch %21
  2281. %21 = OpLabel
  2282. %22 = OpPhi %8 %10 %46 %23 %24
  2283. OpLoopMerge %25 %24 None
  2284. OpBranch %26
  2285. %26 = OpLabel
  2286. %30 = OpAccessChain %16 %4 %22
  2287. %31 = OpLoad %11 %30
  2288. %32 = OpAccessChain %16 %5 %22
  2289. OpStore %32 %31
  2290. %23 = OpIAdd %8 %22 %17
  2291. OpStore %3 %23
  2292. OpBranch %24
  2293. %24 = OpLabel
  2294. %33 = OpSLessThan %19 %23 %18
  2295. OpBranchConditional %33 %21 %25
  2296. %25 = OpLabel
  2297. OpReturn
  2298. OpFunctionEnd
  2299. )";
  2300. // clang-format on
  2301. std::unique_ptr<IRContext> context =
  2302. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  2303. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2304. Module* module = context->module();
  2305. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  2306. << source << std::endl;
  2307. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  2308. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  2309. }
  2310. /*
  2311. #version 430
  2312. void main(void) {
  2313. float A[10][10];
  2314. float B[10][10];
  2315. for (int j = 0; j < 10; ++j) {
  2316. for (int i = 0; i < 10; ++i) {
  2317. B[i][j] = A[i][i];
  2318. A[i][i] = B[i][j + 1];
  2319. }
  2320. }
  2321. }
  2322. This loop can't be split because the load B[i][j + 1] is dependent on the store
  2323. B[i][j].
  2324. */
  2325. TEST_F(FissionClassTest, FissionNestedDependency) {
  2326. // clang-format off
  2327. // With LocalMultiStoreElimPass
  2328. const std::string source = R"(OpCapability Shader
  2329. %1 = OpExtInstImport "GLSL.std.450"
  2330. OpMemoryModel Logical GLSL450
  2331. OpEntryPoint Fragment %2 "main"
  2332. OpExecutionMode %2 OriginUpperLeft
  2333. OpSource GLSL 430
  2334. OpName %2 "main"
  2335. OpName %3 "j"
  2336. OpName %4 "i"
  2337. OpName %5 "B"
  2338. OpName %6 "A"
  2339. %7 = OpTypeVoid
  2340. %8 = OpTypeFunction %7
  2341. %9 = OpTypeInt 32 1
  2342. %10 = OpTypePointer Function %9
  2343. %11 = OpConstant %9 0
  2344. %12 = OpConstant %9 10
  2345. %13 = OpTypeBool
  2346. %14 = OpTypeFloat 32
  2347. %15 = OpTypeInt 32 0
  2348. %16 = OpConstant %15 10
  2349. %17 = OpTypeArray %14 %16
  2350. %18 = OpTypeArray %17 %16
  2351. %19 = OpTypePointer Function %18
  2352. %20 = OpTypePointer Function %14
  2353. %21 = OpConstant %9 1
  2354. %2 = OpFunction %7 None %8
  2355. %22 = OpLabel
  2356. %3 = OpVariable %10 Function
  2357. %4 = OpVariable %10 Function
  2358. %5 = OpVariable %19 Function
  2359. %6 = OpVariable %19 Function
  2360. OpBranch %23
  2361. %23 = OpLabel
  2362. %24 = OpPhi %9 %11 %22 %25 %26
  2363. OpLoopMerge %27 %26 None
  2364. OpBranch %28
  2365. %28 = OpLabel
  2366. %29 = OpSLessThan %13 %24 %12
  2367. OpBranchConditional %29 %30 %27
  2368. %30 = OpLabel
  2369. OpBranch %31
  2370. %31 = OpLabel
  2371. %32 = OpPhi %9 %11 %30 %33 %34
  2372. OpLoopMerge %35 %34 None
  2373. OpBranch %36
  2374. %36 = OpLabel
  2375. %37 = OpSLessThan %13 %32 %12
  2376. OpBranchConditional %37 %38 %35
  2377. %38 = OpLabel
  2378. %39 = OpAccessChain %20 %6 %32 %32
  2379. %40 = OpLoad %14 %39
  2380. %41 = OpAccessChain %20 %5 %32 %24
  2381. OpStore %41 %40
  2382. %42 = OpIAdd %9 %24 %21
  2383. %43 = OpAccessChain %20 %5 %32 %42
  2384. %44 = OpLoad %14 %43
  2385. %45 = OpAccessChain %20 %6 %32 %32
  2386. OpStore %45 %44
  2387. OpBranch %34
  2388. %34 = OpLabel
  2389. %33 = OpIAdd %9 %32 %21
  2390. OpBranch %31
  2391. %35 = OpLabel
  2392. OpBranch %26
  2393. %26 = OpLabel
  2394. %25 = OpIAdd %9 %24 %21
  2395. OpBranch %23
  2396. %27 = OpLabel
  2397. OpReturn
  2398. OpFunctionEnd
  2399. )";
  2400. // clang-format on
  2401. std::unique_ptr<IRContext> context =
  2402. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  2403. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2404. Module* module = context->module();
  2405. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  2406. << source << std::endl;
  2407. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  2408. SinglePassRunAndCheck<LoopFissionPass>(source, source, true);
  2409. }
  2410. /*
  2411. #version 430
  2412. void main(void) {
  2413. float A[10][10];
  2414. float B[10][10];
  2415. for (int j = 0; j < 10; ++j) {
  2416. for (int i = 0; i < 10; ++i) {
  2417. B[i][i] = A[i][j];
  2418. A[i][j+1] = B[i][i];
  2419. }
  2420. }
  2421. }
  2422. This loop should not be split as the load A[i][j+1] would be reading a value
  2423. written in the store A[i][j] which would be hit before A[i][j+1] if the loops
  2424. where split but would not get hit before the read currently.
  2425. */
  2426. TEST_F(FissionClassTest, FissionNestedDependency2) {
  2427. // clang-format off
  2428. // With LocalMultiStoreElimPass
  2429. const std::string source = R"(OpCapability Shader
  2430. %1 = OpExtInstImport "GLSL.std.450"
  2431. OpMemoryModel Logical GLSL450
  2432. OpEntryPoint Fragment %2 "main"
  2433. OpExecutionMode %2 OriginUpperLeft
  2434. OpSource GLSL 430
  2435. OpName %2 "main"
  2436. OpName %3 "j"
  2437. OpName %4 "i"
  2438. OpName %5 "B"
  2439. OpName %6 "A"
  2440. %7 = OpTypeVoid
  2441. %8 = OpTypeFunction %7
  2442. %9 = OpTypeInt 32 1
  2443. %10 = OpTypePointer Function %9
  2444. %11 = OpConstant %9 0
  2445. %12 = OpConstant %9 10
  2446. %13 = OpTypeBool
  2447. %14 = OpTypeFloat 32
  2448. %15 = OpTypeInt 32 0
  2449. %16 = OpConstant %15 10
  2450. %17 = OpTypeArray %14 %16
  2451. %18 = OpTypeArray %17 %16
  2452. %19 = OpTypePointer Function %18
  2453. %20 = OpTypePointer Function %14
  2454. %21 = OpConstant %9 1
  2455. %2 = OpFunction %7 None %8
  2456. %22 = OpLabel
  2457. %3 = OpVariable %10 Function
  2458. %4 = OpVariable %10 Function
  2459. %5 = OpVariable %19 Function
  2460. %6 = OpVariable %19 Function
  2461. OpStore %3 %11
  2462. OpBranch %23
  2463. %23 = OpLabel
  2464. %24 = OpPhi %9 %11 %22 %25 %26
  2465. OpLoopMerge %27 %26 None
  2466. OpBranch %28
  2467. %28 = OpLabel
  2468. %29 = OpSLessThan %13 %24 %12
  2469. OpBranchConditional %29 %30 %27
  2470. %30 = OpLabel
  2471. OpStore %4 %11
  2472. OpBranch %31
  2473. %31 = OpLabel
  2474. %32 = OpPhi %9 %11 %30 %33 %34
  2475. OpLoopMerge %35 %34 None
  2476. OpBranch %36
  2477. %36 = OpLabel
  2478. %37 = OpSLessThan %13 %32 %12
  2479. OpBranchConditional %37 %38 %35
  2480. %38 = OpLabel
  2481. %39 = OpAccessChain %20 %6 %32 %24
  2482. %40 = OpLoad %14 %39
  2483. %41 = OpAccessChain %20 %5 %32 %32
  2484. OpStore %41 %40
  2485. %42 = OpIAdd %9 %24 %21
  2486. %43 = OpAccessChain %20 %5 %32 %32
  2487. %44 = OpLoad %14 %43
  2488. %45 = OpAccessChain %20 %6 %32 %42
  2489. OpStore %45 %44
  2490. OpBranch %34
  2491. %34 = OpLabel
  2492. %33 = OpIAdd %9 %32 %21
  2493. OpStore %4 %33
  2494. OpBranch %31
  2495. %35 = OpLabel
  2496. OpBranch %26
  2497. %26 = OpLabel
  2498. %25 = OpIAdd %9 %24 %21
  2499. OpStore %3 %25
  2500. OpBranch %23
  2501. %27 = OpLabel
  2502. OpReturn
  2503. OpFunctionEnd
  2504. )";
  2505. // clang-format on
  2506. std::unique_ptr<IRContext> context =
  2507. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  2508. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2509. Module* module = context->module();
  2510. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  2511. << source << std::endl;
  2512. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  2513. SinglePassRunAndCheck<LoopFissionPass>(source, source, true);
  2514. }
  2515. /*
  2516. #version 430
  2517. void main(void) {
  2518. float A[10][10];
  2519. float B[10][10];
  2520. for (int j = 0; j < 10; ++j) {
  2521. for (int i = 0; i < 10; ++i) {
  2522. B[i][j] = A[i][j];
  2523. A[i][j] = B[i][j];
  2524. }
  2525. for (int i = 0; i < 10; ++i) {
  2526. B[i][j] = A[i][j];
  2527. A[i][j] = B[i][j];
  2528. }
  2529. }
  2530. }
  2531. Should be split into:
  2532. for (int j = 0; j < 10; ++j) {
  2533. for (int i = 0; i < 10; ++i)
  2534. B[i][j] = A[i][j];
  2535. for (int i = 0; i < 10; ++i)
  2536. A[i][j] = B[i][j];
  2537. for (int i = 0; i < 10; ++i)
  2538. B[i][j] = A[i][j];
  2539. for (int i = 0; i < 10; ++i)
  2540. A[i][j] = B[i][j];
  2541. */
  2542. TEST_F(FissionClassTest, FissionMultipleLoopsNested) {
  2543. // clang-format off
  2544. // With LocalMultiStoreElimPass
  2545. const std::string source = R"(OpCapability Shader
  2546. %1 = OpExtInstImport "GLSL.std.450"
  2547. OpMemoryModel Logical GLSL450
  2548. OpEntryPoint Fragment %2 "main"
  2549. OpExecutionMode %2 OriginUpperLeft
  2550. OpSource GLSL 430
  2551. OpName %2 "main"
  2552. OpName %3 "j"
  2553. OpName %4 "i"
  2554. OpName %5 "B"
  2555. OpName %6 "A"
  2556. OpName %7 "i"
  2557. %8 = OpTypeVoid
  2558. %9 = OpTypeFunction %8
  2559. %10 = OpTypeInt 32 1
  2560. %11 = OpTypePointer Function %10
  2561. %12 = OpConstant %10 0
  2562. %13 = OpConstant %10 10
  2563. %14 = OpTypeBool
  2564. %15 = OpTypeFloat 32
  2565. %16 = OpTypeInt 32 0
  2566. %17 = OpConstant %16 10
  2567. %18 = OpTypeArray %15 %17
  2568. %19 = OpTypeArray %18 %17
  2569. %20 = OpTypePointer Function %19
  2570. %21 = OpTypePointer Function %15
  2571. %22 = OpConstant %10 1
  2572. %2 = OpFunction %8 None %9
  2573. %23 = OpLabel
  2574. %3 = OpVariable %11 Function
  2575. %4 = OpVariable %11 Function
  2576. %5 = OpVariable %20 Function
  2577. %6 = OpVariable %20 Function
  2578. %7 = OpVariable %11 Function
  2579. OpStore %3 %12
  2580. OpBranch %24
  2581. %24 = OpLabel
  2582. %25 = OpPhi %10 %12 %23 %26 %27
  2583. OpLoopMerge %28 %27 None
  2584. OpBranch %29
  2585. %29 = OpLabel
  2586. %30 = OpSLessThan %14 %25 %13
  2587. OpBranchConditional %30 %31 %28
  2588. %31 = OpLabel
  2589. OpStore %4 %12
  2590. OpBranch %32
  2591. %32 = OpLabel
  2592. %33 = OpPhi %10 %12 %31 %34 %35
  2593. OpLoopMerge %36 %35 None
  2594. OpBranch %37
  2595. %37 = OpLabel
  2596. %38 = OpSLessThan %14 %33 %13
  2597. OpBranchConditional %38 %39 %36
  2598. %39 = OpLabel
  2599. %40 = OpAccessChain %21 %6 %33 %25
  2600. %41 = OpLoad %15 %40
  2601. %42 = OpAccessChain %21 %5 %33 %25
  2602. OpStore %42 %41
  2603. %43 = OpAccessChain %21 %5 %33 %25
  2604. %44 = OpLoad %15 %43
  2605. %45 = OpAccessChain %21 %6 %33 %25
  2606. OpStore %45 %44
  2607. OpBranch %35
  2608. %35 = OpLabel
  2609. %34 = OpIAdd %10 %33 %22
  2610. OpStore %4 %34
  2611. OpBranch %32
  2612. %36 = OpLabel
  2613. OpStore %7 %12
  2614. OpBranch %46
  2615. %46 = OpLabel
  2616. %47 = OpPhi %10 %12 %36 %48 %49
  2617. OpLoopMerge %50 %49 None
  2618. OpBranch %51
  2619. %51 = OpLabel
  2620. %52 = OpSLessThan %14 %47 %13
  2621. OpBranchConditional %52 %53 %50
  2622. %53 = OpLabel
  2623. %54 = OpAccessChain %21 %6 %47 %25
  2624. %55 = OpLoad %15 %54
  2625. %56 = OpAccessChain %21 %5 %47 %25
  2626. OpStore %56 %55
  2627. %57 = OpAccessChain %21 %5 %47 %25
  2628. %58 = OpLoad %15 %57
  2629. %59 = OpAccessChain %21 %6 %47 %25
  2630. OpStore %59 %58
  2631. OpBranch %49
  2632. %49 = OpLabel
  2633. %48 = OpIAdd %10 %47 %22
  2634. OpStore %7 %48
  2635. OpBranch %46
  2636. %50 = OpLabel
  2637. OpBranch %27
  2638. %27 = OpLabel
  2639. %26 = OpIAdd %10 %25 %22
  2640. OpStore %3 %26
  2641. OpBranch %24
  2642. %28 = OpLabel
  2643. OpReturn
  2644. OpFunctionEnd
  2645. )";
  2646. const std::string expected = R"(OpCapability Shader
  2647. %1 = OpExtInstImport "GLSL.std.450"
  2648. OpMemoryModel Logical GLSL450
  2649. OpEntryPoint Fragment %2 "main"
  2650. OpExecutionMode %2 OriginUpperLeft
  2651. OpSource GLSL 430
  2652. OpName %2 "main"
  2653. OpName %3 "j"
  2654. OpName %4 "i"
  2655. OpName %5 "B"
  2656. OpName %6 "A"
  2657. OpName %7 "i"
  2658. %8 = OpTypeVoid
  2659. %9 = OpTypeFunction %8
  2660. %10 = OpTypeInt 32 1
  2661. %11 = OpTypePointer Function %10
  2662. %12 = OpConstant %10 0
  2663. %13 = OpConstant %10 10
  2664. %14 = OpTypeBool
  2665. %15 = OpTypeFloat 32
  2666. %16 = OpTypeInt 32 0
  2667. %17 = OpConstant %16 10
  2668. %18 = OpTypeArray %15 %17
  2669. %19 = OpTypeArray %18 %17
  2670. %20 = OpTypePointer Function %19
  2671. %21 = OpTypePointer Function %15
  2672. %22 = OpConstant %10 1
  2673. %2 = OpFunction %8 None %9
  2674. %23 = OpLabel
  2675. %3 = OpVariable %11 Function
  2676. %4 = OpVariable %11 Function
  2677. %5 = OpVariable %20 Function
  2678. %6 = OpVariable %20 Function
  2679. %7 = OpVariable %11 Function
  2680. OpStore %3 %12
  2681. OpBranch %24
  2682. %24 = OpLabel
  2683. %25 = OpPhi %10 %12 %23 %26 %27
  2684. OpLoopMerge %28 %27 None
  2685. OpBranch %29
  2686. %29 = OpLabel
  2687. %30 = OpSLessThan %14 %25 %13
  2688. OpBranchConditional %30 %31 %28
  2689. %31 = OpLabel
  2690. OpStore %4 %12
  2691. OpBranch %60
  2692. %60 = OpLabel
  2693. %61 = OpPhi %10 %12 %31 %72 %71
  2694. OpLoopMerge %73 %71 None
  2695. OpBranch %62
  2696. %62 = OpLabel
  2697. %63 = OpSLessThan %14 %61 %13
  2698. OpBranchConditional %63 %64 %73
  2699. %64 = OpLabel
  2700. %65 = OpAccessChain %21 %6 %61 %25
  2701. %66 = OpLoad %15 %65
  2702. %67 = OpAccessChain %21 %5 %61 %25
  2703. OpStore %67 %66
  2704. OpBranch %71
  2705. %71 = OpLabel
  2706. %72 = OpIAdd %10 %61 %22
  2707. OpStore %4 %72
  2708. OpBranch %60
  2709. %73 = OpLabel
  2710. OpBranch %32
  2711. %32 = OpLabel
  2712. %33 = OpPhi %10 %12 %73 %34 %35
  2713. OpLoopMerge %36 %35 None
  2714. OpBranch %37
  2715. %37 = OpLabel
  2716. %38 = OpSLessThan %14 %33 %13
  2717. OpBranchConditional %38 %39 %36
  2718. %39 = OpLabel
  2719. %43 = OpAccessChain %21 %5 %33 %25
  2720. %44 = OpLoad %15 %43
  2721. %45 = OpAccessChain %21 %6 %33 %25
  2722. OpStore %45 %44
  2723. OpBranch %35
  2724. %35 = OpLabel
  2725. %34 = OpIAdd %10 %33 %22
  2726. OpStore %4 %34
  2727. OpBranch %32
  2728. %36 = OpLabel
  2729. OpStore %7 %12
  2730. OpBranch %74
  2731. %74 = OpLabel
  2732. %75 = OpPhi %10 %12 %36 %86 %85
  2733. OpLoopMerge %87 %85 None
  2734. OpBranch %76
  2735. %76 = OpLabel
  2736. %77 = OpSLessThan %14 %75 %13
  2737. OpBranchConditional %77 %78 %87
  2738. %78 = OpLabel
  2739. %79 = OpAccessChain %21 %6 %75 %25
  2740. %80 = OpLoad %15 %79
  2741. %81 = OpAccessChain %21 %5 %75 %25
  2742. OpStore %81 %80
  2743. OpBranch %85
  2744. %85 = OpLabel
  2745. %86 = OpIAdd %10 %75 %22
  2746. OpStore %7 %86
  2747. OpBranch %74
  2748. %87 = OpLabel
  2749. OpBranch %46
  2750. %46 = OpLabel
  2751. %47 = OpPhi %10 %12 %87 %48 %49
  2752. OpLoopMerge %50 %49 None
  2753. OpBranch %51
  2754. %51 = OpLabel
  2755. %52 = OpSLessThan %14 %47 %13
  2756. OpBranchConditional %52 %53 %50
  2757. %53 = OpLabel
  2758. %57 = OpAccessChain %21 %5 %47 %25
  2759. %58 = OpLoad %15 %57
  2760. %59 = OpAccessChain %21 %6 %47 %25
  2761. OpStore %59 %58
  2762. OpBranch %49
  2763. %49 = OpLabel
  2764. %48 = OpIAdd %10 %47 %22
  2765. OpStore %7 %48
  2766. OpBranch %46
  2767. %50 = OpLabel
  2768. OpBranch %27
  2769. %27 = OpLabel
  2770. %26 = OpIAdd %10 %25 %22
  2771. OpStore %3 %26
  2772. OpBranch %24
  2773. %28 = OpLabel
  2774. OpReturn
  2775. OpFunctionEnd
  2776. )";
  2777. // clang-format on
  2778. std::unique_ptr<IRContext> context =
  2779. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  2780. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2781. Module* module = context->module();
  2782. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  2783. << source << std::endl;
  2784. const Function* function = spvtest::GetFunction(module, 2);
  2785. LoopDescriptor& pre_pass_descriptor = *context->GetLoopDescriptor(function);
  2786. EXPECT_EQ(pre_pass_descriptor.NumLoops(), 3u);
  2787. EXPECT_EQ(pre_pass_descriptor.pre_begin()->NumImmediateChildren(), 2u);
  2788. // Test that the pass transforms the ir into the expected output.
  2789. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  2790. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  2791. // Test that the loop descriptor is correctly maintained and updated by the
  2792. // pass.
  2793. LoopFissionPass loop_fission;
  2794. loop_fission.SetContextForTesting(context.get());
  2795. loop_fission.Process();
  2796. function = spvtest::GetFunction(module, 2);
  2797. LoopDescriptor& post_pass_descriptor = *context->GetLoopDescriptor(function);
  2798. EXPECT_EQ(post_pass_descriptor.NumLoops(), 5u);
  2799. EXPECT_EQ(post_pass_descriptor.pre_begin()->NumImmediateChildren(), 4u);
  2800. }
  2801. /*
  2802. #version 430
  2803. void main(void) {
  2804. float A[10][10];
  2805. float B[10][10];
  2806. for (int i = 0; i < 10; ++i) {
  2807. B[i][i] = A[i][i];
  2808. A[i][i] = B[i][i];
  2809. }
  2810. for (int i = 0; i < 10; ++i) {
  2811. B[i][i] = A[i][i];
  2812. A[i][i] = B[i][i]
  2813. }
  2814. }
  2815. Should be split into:
  2816. for (int i = 0; i < 10; ++i)
  2817. B[i][i] = A[i][i];
  2818. for (int i = 0; i < 10; ++i)
  2819. A[i][i] = B[i][i];
  2820. for (int i = 0; i < 10; ++i)
  2821. B[i][i] = A[i][i];
  2822. for (int i = 0; i < 10; ++i)
  2823. A[i][i] = B[i][i];
  2824. */
  2825. TEST_F(FissionClassTest, FissionMultipleLoops) {
  2826. // clang-format off
  2827. // With LocalMultiStoreElimPass
  2828. const std::string source = R"(OpCapability Shader
  2829. %1 = OpExtInstImport "GLSL.std.450"
  2830. OpMemoryModel Logical GLSL450
  2831. OpEntryPoint Fragment %2 "main"
  2832. OpExecutionMode %2 OriginUpperLeft
  2833. OpSource GLSL 430
  2834. OpName %2 "main"
  2835. OpName %3 "i"
  2836. OpName %4 "B"
  2837. OpName %5 "A"
  2838. OpName %6 "i"
  2839. %7 = OpTypeVoid
  2840. %8 = OpTypeFunction %7
  2841. %9 = OpTypeInt 32 1
  2842. %10 = OpTypePointer Function %9
  2843. %11 = OpConstant %9 0
  2844. %12 = OpConstant %9 10
  2845. %13 = OpTypeBool
  2846. %14 = OpTypeFloat 32
  2847. %15 = OpTypeInt 32 0
  2848. %16 = OpConstant %15 10
  2849. %17 = OpTypeArray %14 %16
  2850. %18 = OpTypePointer Function %17
  2851. %19 = OpTypePointer Function %14
  2852. %20 = OpConstant %9 1
  2853. %2 = OpFunction %7 None %8
  2854. %21 = OpLabel
  2855. %3 = OpVariable %10 Function
  2856. %4 = OpVariable %18 Function
  2857. %5 = OpVariable %18 Function
  2858. %6 = OpVariable %10 Function
  2859. OpStore %3 %11
  2860. OpBranch %22
  2861. %22 = OpLabel
  2862. %23 = OpPhi %9 %11 %21 %24 %25
  2863. OpLoopMerge %26 %25 None
  2864. OpBranch %27
  2865. %27 = OpLabel
  2866. %28 = OpSLessThan %13 %23 %12
  2867. OpBranchConditional %28 %29 %26
  2868. %29 = OpLabel
  2869. %30 = OpAccessChain %19 %5 %23
  2870. %31 = OpLoad %14 %30
  2871. %32 = OpAccessChain %19 %4 %23
  2872. OpStore %32 %31
  2873. %33 = OpAccessChain %19 %4 %23
  2874. %34 = OpLoad %14 %33
  2875. %35 = OpAccessChain %19 %5 %23
  2876. OpStore %35 %34
  2877. OpBranch %25
  2878. %25 = OpLabel
  2879. %24 = OpIAdd %9 %23 %20
  2880. OpStore %3 %24
  2881. OpBranch %22
  2882. %26 = OpLabel
  2883. OpStore %6 %11
  2884. OpBranch %36
  2885. %36 = OpLabel
  2886. %37 = OpPhi %9 %11 %26 %38 %39
  2887. OpLoopMerge %40 %39 None
  2888. OpBranch %41
  2889. %41 = OpLabel
  2890. %42 = OpSLessThan %13 %37 %12
  2891. OpBranchConditional %42 %43 %40
  2892. %43 = OpLabel
  2893. %44 = OpAccessChain %19 %5 %37
  2894. %45 = OpLoad %14 %44
  2895. %46 = OpAccessChain %19 %4 %37
  2896. OpStore %46 %45
  2897. %47 = OpAccessChain %19 %4 %37
  2898. %48 = OpLoad %14 %47
  2899. %49 = OpAccessChain %19 %5 %37
  2900. OpStore %49 %48
  2901. OpBranch %39
  2902. %39 = OpLabel
  2903. %38 = OpIAdd %9 %37 %20
  2904. OpStore %6 %38
  2905. OpBranch %36
  2906. %40 = OpLabel
  2907. OpReturn
  2908. OpFunctionEnd
  2909. )";
  2910. const std::string expected = R"(OpCapability Shader
  2911. %1 = OpExtInstImport "GLSL.std.450"
  2912. OpMemoryModel Logical GLSL450
  2913. OpEntryPoint Fragment %2 "main"
  2914. OpExecutionMode %2 OriginUpperLeft
  2915. OpSource GLSL 430
  2916. OpName %2 "main"
  2917. OpName %3 "i"
  2918. OpName %4 "B"
  2919. OpName %5 "A"
  2920. OpName %6 "i"
  2921. %7 = OpTypeVoid
  2922. %8 = OpTypeFunction %7
  2923. %9 = OpTypeInt 32 1
  2924. %10 = OpTypePointer Function %9
  2925. %11 = OpConstant %9 0
  2926. %12 = OpConstant %9 10
  2927. %13 = OpTypeBool
  2928. %14 = OpTypeFloat 32
  2929. %15 = OpTypeInt 32 0
  2930. %16 = OpConstant %15 10
  2931. %17 = OpTypeArray %14 %16
  2932. %18 = OpTypePointer Function %17
  2933. %19 = OpTypePointer Function %14
  2934. %20 = OpConstant %9 1
  2935. %2 = OpFunction %7 None %8
  2936. %21 = OpLabel
  2937. %3 = OpVariable %10 Function
  2938. %4 = OpVariable %18 Function
  2939. %5 = OpVariable %18 Function
  2940. %6 = OpVariable %10 Function
  2941. OpStore %3 %11
  2942. OpBranch %64
  2943. %64 = OpLabel
  2944. %65 = OpPhi %9 %11 %21 %76 %75
  2945. OpLoopMerge %77 %75 None
  2946. OpBranch %66
  2947. %66 = OpLabel
  2948. %67 = OpSLessThan %13 %65 %12
  2949. OpBranchConditional %67 %68 %77
  2950. %68 = OpLabel
  2951. %69 = OpAccessChain %19 %5 %65
  2952. %70 = OpLoad %14 %69
  2953. %71 = OpAccessChain %19 %4 %65
  2954. OpStore %71 %70
  2955. OpBranch %75
  2956. %75 = OpLabel
  2957. %76 = OpIAdd %9 %65 %20
  2958. OpStore %3 %76
  2959. OpBranch %64
  2960. %77 = OpLabel
  2961. OpBranch %22
  2962. %22 = OpLabel
  2963. %23 = OpPhi %9 %11 %77 %24 %25
  2964. OpLoopMerge %26 %25 None
  2965. OpBranch %27
  2966. %27 = OpLabel
  2967. %28 = OpSLessThan %13 %23 %12
  2968. OpBranchConditional %28 %29 %26
  2969. %29 = OpLabel
  2970. %33 = OpAccessChain %19 %4 %23
  2971. %34 = OpLoad %14 %33
  2972. %35 = OpAccessChain %19 %5 %23
  2973. OpStore %35 %34
  2974. OpBranch %25
  2975. %25 = OpLabel
  2976. %24 = OpIAdd %9 %23 %20
  2977. OpStore %3 %24
  2978. OpBranch %22
  2979. %26 = OpLabel
  2980. OpStore %6 %11
  2981. OpBranch %50
  2982. %50 = OpLabel
  2983. %51 = OpPhi %9 %11 %26 %62 %61
  2984. OpLoopMerge %63 %61 None
  2985. OpBranch %52
  2986. %52 = OpLabel
  2987. %53 = OpSLessThan %13 %51 %12
  2988. OpBranchConditional %53 %54 %63
  2989. %54 = OpLabel
  2990. %55 = OpAccessChain %19 %5 %51
  2991. %56 = OpLoad %14 %55
  2992. %57 = OpAccessChain %19 %4 %51
  2993. OpStore %57 %56
  2994. OpBranch %61
  2995. %61 = OpLabel
  2996. %62 = OpIAdd %9 %51 %20
  2997. OpStore %6 %62
  2998. OpBranch %50
  2999. %63 = OpLabel
  3000. OpBranch %36
  3001. %36 = OpLabel
  3002. %37 = OpPhi %9 %11 %63 %38 %39
  3003. OpLoopMerge %40 %39 None
  3004. OpBranch %41
  3005. %41 = OpLabel
  3006. %42 = OpSLessThan %13 %37 %12
  3007. OpBranchConditional %42 %43 %40
  3008. %43 = OpLabel
  3009. %47 = OpAccessChain %19 %4 %37
  3010. %48 = OpLoad %14 %47
  3011. %49 = OpAccessChain %19 %5 %37
  3012. OpStore %49 %48
  3013. OpBranch %39
  3014. %39 = OpLabel
  3015. %38 = OpIAdd %9 %37 %20
  3016. OpStore %6 %38
  3017. OpBranch %36
  3018. %40 = OpLabel
  3019. OpReturn
  3020. OpFunctionEnd
  3021. )";
  3022. // clang-format on
  3023. std::unique_ptr<IRContext> context =
  3024. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  3025. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  3026. Module* module = context->module();
  3027. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  3028. << source << std::endl;
  3029. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  3030. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  3031. const Function* function = spvtest::GetFunction(module, 2);
  3032. LoopDescriptor& pre_pass_descriptor = *context->GetLoopDescriptor(function);
  3033. EXPECT_EQ(pre_pass_descriptor.NumLoops(), 2u);
  3034. EXPECT_EQ(pre_pass_descriptor.pre_begin()->NumImmediateChildren(), 0u);
  3035. // Test that the pass transforms the ir into the expected output.
  3036. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  3037. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  3038. // Test that the loop descriptor is correctly maintained and updated by the
  3039. // pass.
  3040. LoopFissionPass loop_fission;
  3041. loop_fission.SetContextForTesting(context.get());
  3042. loop_fission.Process();
  3043. function = spvtest::GetFunction(module, 2);
  3044. LoopDescriptor& post_pass_descriptor = *context->GetLoopDescriptor(function);
  3045. EXPECT_EQ(post_pass_descriptor.NumLoops(), 4u);
  3046. EXPECT_EQ(post_pass_descriptor.pre_begin()->NumImmediateChildren(), 0u);
  3047. }
  3048. /*
  3049. #version 430
  3050. int foo() { return 1; }
  3051. void main(void) {
  3052. float A[10];
  3053. float B[10];
  3054. for (int i = 0; i < 10; ++i) {
  3055. B[i] = A[i];
  3056. foo();
  3057. A[i] = B[i];
  3058. }
  3059. }
  3060. This should not be split as it has a function call in it so we can't determine
  3061. if it has side effects.
  3062. */
  3063. TEST_F(FissionClassTest, FissionFunctionCall) {
  3064. // clang-format off
  3065. // With LocalMultiStoreElimPass
  3066. const std::string source = R"(OpCapability Shader
  3067. %1 = OpExtInstImport "GLSL.std.450"
  3068. OpMemoryModel Logical GLSL450
  3069. OpEntryPoint Fragment %2 "main"
  3070. OpExecutionMode %2 OriginUpperLeft
  3071. OpSource GLSL 430
  3072. OpName %2 "main"
  3073. OpName %3 "foo("
  3074. OpName %4 "i"
  3075. OpName %5 "B"
  3076. OpName %6 "A"
  3077. %7 = OpTypeVoid
  3078. %8 = OpTypeFunction %7
  3079. %9 = OpTypeInt 32 1
  3080. %10 = OpTypeFunction %9
  3081. %11 = OpConstant %9 1
  3082. %12 = OpTypePointer Function %9
  3083. %13 = OpConstant %9 0
  3084. %14 = OpConstant %9 10
  3085. %15 = OpTypeBool
  3086. %16 = OpTypeFloat 32
  3087. %17 = OpTypeInt 32 0
  3088. %18 = OpConstant %17 10
  3089. %19 = OpTypeArray %16 %18
  3090. %20 = OpTypePointer Function %19
  3091. %21 = OpTypePointer Function %16
  3092. %2 = OpFunction %7 None %8
  3093. %22 = OpLabel
  3094. %4 = OpVariable %12 Function
  3095. %5 = OpVariable %20 Function
  3096. %6 = OpVariable %20 Function
  3097. OpStore %4 %13
  3098. OpBranch %23
  3099. %23 = OpLabel
  3100. %24 = OpPhi %9 %13 %22 %25 %26
  3101. OpLoopMerge %27 %26 None
  3102. OpBranch %28
  3103. %28 = OpLabel
  3104. %29 = OpSLessThan %15 %24 %14
  3105. OpBranchConditional %29 %30 %27
  3106. %30 = OpLabel
  3107. %31 = OpAccessChain %21 %6 %24
  3108. %32 = OpLoad %16 %31
  3109. %33 = OpAccessChain %21 %5 %24
  3110. OpStore %33 %32
  3111. %34 = OpFunctionCall %9 %3
  3112. %35 = OpAccessChain %21 %5 %24
  3113. %36 = OpLoad %16 %35
  3114. %37 = OpAccessChain %21 %6 %24
  3115. OpStore %37 %36
  3116. OpBranch %26
  3117. %26 = OpLabel
  3118. %25 = OpIAdd %9 %24 %11
  3119. OpStore %4 %25
  3120. OpBranch %23
  3121. %27 = OpLabel
  3122. OpReturn
  3123. OpFunctionEnd
  3124. %3 = OpFunction %9 None %10
  3125. %38 = OpLabel
  3126. OpReturnValue %11
  3127. OpFunctionEnd
  3128. )";
  3129. // clang-format on
  3130. std::unique_ptr<IRContext> context =
  3131. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  3132. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  3133. Module* module = context->module();
  3134. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  3135. << source << std::endl;
  3136. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  3137. SinglePassRunAndCheck<LoopFissionPass>(source, source, true);
  3138. }
  3139. /*
  3140. #version 430
  3141. void main(void) {
  3142. float A[10];
  3143. float B[10];
  3144. for (int i = 0; i < 10; ++i) {
  3145. switch (i) {
  3146. case 1:
  3147. B[i] = A[i];
  3148. break;
  3149. default:
  3150. A[i] = B[i];
  3151. }
  3152. }
  3153. }
  3154. This should be split into:
  3155. for (int i = 0; i < 10; ++i) {
  3156. switch (i) {
  3157. case 1:
  3158. break;
  3159. default:
  3160. A[i] = B[i];
  3161. }
  3162. }
  3163. for (int i = 0; i < 10; ++i) {
  3164. switch (i) {
  3165. case 1:
  3166. B[i] = A[i];
  3167. break;
  3168. default:
  3169. break;
  3170. }
  3171. }
  3172. */
  3173. TEST_F(FissionClassTest, FissionSwitchStatement) {
  3174. // clang-format off
  3175. // With LocalMultiStoreElimPass
  3176. const std::string source = R"(OpCapability Shader
  3177. %1 = OpExtInstImport "GLSL.std.450"
  3178. OpMemoryModel Logical GLSL450
  3179. OpEntryPoint Fragment %2 "main"
  3180. OpExecutionMode %2 OriginUpperLeft
  3181. OpSource GLSL 430
  3182. OpName %2 "main"
  3183. OpName %3 "i"
  3184. OpName %4 "B"
  3185. OpName %5 "A"
  3186. %6 = OpTypeVoid
  3187. %7 = OpTypeFunction %6
  3188. %8 = OpTypeInt 32 1
  3189. %9 = OpTypePointer Function %8
  3190. %10 = OpConstant %8 0
  3191. %11 = OpConstant %8 10
  3192. %12 = OpTypeBool
  3193. %13 = OpTypeFloat 32
  3194. %14 = OpTypeInt 32 0
  3195. %15 = OpConstant %14 10
  3196. %16 = OpTypeArray %13 %15
  3197. %17 = OpTypePointer Function %16
  3198. %18 = OpTypePointer Function %13
  3199. %19 = OpConstant %8 1
  3200. %2 = OpFunction %6 None %7
  3201. %20 = OpLabel
  3202. %3 = OpVariable %9 Function
  3203. %4 = OpVariable %17 Function
  3204. %5 = OpVariable %17 Function
  3205. OpStore %3 %10
  3206. OpBranch %21
  3207. %21 = OpLabel
  3208. %22 = OpPhi %8 %10 %20 %23 %24
  3209. OpLoopMerge %25 %24 None
  3210. OpBranch %26
  3211. %26 = OpLabel
  3212. %27 = OpSLessThan %12 %22 %11
  3213. OpBranchConditional %27 %28 %25
  3214. %28 = OpLabel
  3215. OpSelectionMerge %29 None
  3216. OpSwitch %22 %30 1 %31
  3217. %30 = OpLabel
  3218. %32 = OpAccessChain %18 %4 %22
  3219. %33 = OpLoad %13 %32
  3220. %34 = OpAccessChain %18 %5 %22
  3221. OpStore %34 %33
  3222. OpBranch %29
  3223. %31 = OpLabel
  3224. %35 = OpAccessChain %18 %5 %22
  3225. %36 = OpLoad %13 %35
  3226. %37 = OpAccessChain %18 %4 %22
  3227. OpStore %37 %36
  3228. OpBranch %29
  3229. %29 = OpLabel
  3230. OpBranch %24
  3231. %24 = OpLabel
  3232. %23 = OpIAdd %8 %22 %19
  3233. OpStore %3 %23
  3234. OpBranch %21
  3235. %25 = OpLabel
  3236. OpReturn
  3237. OpFunctionEnd
  3238. )";
  3239. const std::string expected = R"(OpCapability Shader
  3240. %1 = OpExtInstImport "GLSL.std.450"
  3241. OpMemoryModel Logical GLSL450
  3242. OpEntryPoint Fragment %2 "main"
  3243. OpExecutionMode %2 OriginUpperLeft
  3244. OpSource GLSL 430
  3245. OpName %2 "main"
  3246. OpName %3 "i"
  3247. OpName %4 "B"
  3248. OpName %5 "A"
  3249. %6 = OpTypeVoid
  3250. %7 = OpTypeFunction %6
  3251. %8 = OpTypeInt 32 1
  3252. %9 = OpTypePointer Function %8
  3253. %10 = OpConstant %8 0
  3254. %11 = OpConstant %8 10
  3255. %12 = OpTypeBool
  3256. %13 = OpTypeFloat 32
  3257. %14 = OpTypeInt 32 0
  3258. %15 = OpConstant %14 10
  3259. %16 = OpTypeArray %13 %15
  3260. %17 = OpTypePointer Function %16
  3261. %18 = OpTypePointer Function %13
  3262. %19 = OpConstant %8 1
  3263. %2 = OpFunction %6 None %7
  3264. %20 = OpLabel
  3265. %3 = OpVariable %9 Function
  3266. %4 = OpVariable %17 Function
  3267. %5 = OpVariable %17 Function
  3268. OpStore %3 %10
  3269. OpBranch %38
  3270. %38 = OpLabel
  3271. %39 = OpPhi %8 %10 %20 %53 %52
  3272. OpLoopMerge %54 %52 None
  3273. OpBranch %40
  3274. %40 = OpLabel
  3275. %41 = OpSLessThan %12 %39 %11
  3276. OpBranchConditional %41 %42 %54
  3277. %42 = OpLabel
  3278. OpSelectionMerge %51 None
  3279. OpSwitch %39 %47 1 %43
  3280. %43 = OpLabel
  3281. OpBranch %51
  3282. %47 = OpLabel
  3283. %48 = OpAccessChain %18 %4 %39
  3284. %49 = OpLoad %13 %48
  3285. %50 = OpAccessChain %18 %5 %39
  3286. OpStore %50 %49
  3287. OpBranch %51
  3288. %51 = OpLabel
  3289. OpBranch %52
  3290. %52 = OpLabel
  3291. %53 = OpIAdd %8 %39 %19
  3292. OpStore %3 %53
  3293. OpBranch %38
  3294. %54 = OpLabel
  3295. OpBranch %21
  3296. %21 = OpLabel
  3297. %22 = OpPhi %8 %10 %54 %23 %24
  3298. OpLoopMerge %25 %24 None
  3299. OpBranch %26
  3300. %26 = OpLabel
  3301. %27 = OpSLessThan %12 %22 %11
  3302. OpBranchConditional %27 %28 %25
  3303. %28 = OpLabel
  3304. OpSelectionMerge %29 None
  3305. OpSwitch %22 %30 1 %31
  3306. %30 = OpLabel
  3307. OpBranch %29
  3308. %31 = OpLabel
  3309. %35 = OpAccessChain %18 %5 %22
  3310. %36 = OpLoad %13 %35
  3311. %37 = OpAccessChain %18 %4 %22
  3312. OpStore %37 %36
  3313. OpBranch %29
  3314. %29 = OpLabel
  3315. OpBranch %24
  3316. %24 = OpLabel
  3317. %23 = OpIAdd %8 %22 %19
  3318. OpStore %3 %23
  3319. OpBranch %21
  3320. %25 = OpLabel
  3321. OpReturn
  3322. OpFunctionEnd
  3323. )";
  3324. // clang-format on
  3325. std::unique_ptr<IRContext> context =
  3326. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  3327. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  3328. Module* module = context->module();
  3329. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  3330. << source << std::endl;
  3331. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  3332. SinglePassRunAndCheck<LoopFissionPass>(source, expected, true);
  3333. }
  3334. } // namespace
  3335. } // namespace opt
  3336. } // namespace spvtools