loop_fission.cpp 85 KB

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