structured_loop_to_selection_test.cpp 117 KB

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