dependence_analysis.cpp 139 KB

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