structured_loop_to_selection_test.cpp 117 KB

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