unroll_simple.cpp 103 KB

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