dependence_analysis_helpers.cpp 101 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011
  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 <vector>
  16. #include "source/opt/loop_dependence.h"
  17. #include "source/opt/loop_descriptor.h"
  18. #include "source/opt/scalar_analysis.h"
  19. #include "test/opt/assembly_builder.h"
  20. #include "test/opt/function_utils.h"
  21. #include "test/opt/pass_fixture.h"
  22. #include "test/opt/pass_utils.h"
  23. namespace spvtools {
  24. namespace opt {
  25. namespace {
  26. using DependencyAnalysisHelpers = ::testing::Test;
  27. /*
  28. Generated from the following GLSL fragment shader
  29. with --eliminate-local-multi-store
  30. #version 440 core
  31. void a() {
  32. int[10][10] arr;
  33. int i = 0;
  34. int j = 0;
  35. for (; i < 10 && j < 10; i++, j++) {
  36. arr[i][j] = arr[i][j];
  37. }
  38. }
  39. void b() {
  40. int[10] arr;
  41. for (int i = 0; i < 10; i+=2) {
  42. arr[i] = arr[i];
  43. }
  44. }
  45. void main(){
  46. a();
  47. b();
  48. }
  49. */
  50. TEST(DependencyAnalysisHelpers, UnsupportedLoops) {
  51. const std::string text = R"( OpCapability Shader
  52. %1 = OpExtInstImport "GLSL.std.450"
  53. OpMemoryModel Logical GLSL450
  54. OpEntryPoint Fragment %4 "main"
  55. OpExecutionMode %4 OriginUpperLeft
  56. OpSource GLSL 440
  57. OpName %4 "main"
  58. OpName %6 "a("
  59. OpName %8 "b("
  60. OpName %12 "i"
  61. OpName %14 "j"
  62. OpName %32 "arr"
  63. OpName %45 "i"
  64. OpName %54 "arr"
  65. %2 = OpTypeVoid
  66. %3 = OpTypeFunction %2
  67. %10 = OpTypeInt 32 1
  68. %11 = OpTypePointer Function %10
  69. %13 = OpConstant %10 0
  70. %21 = OpConstant %10 10
  71. %22 = OpTypeBool
  72. %27 = OpTypeInt 32 0
  73. %28 = OpConstant %27 10
  74. %29 = OpTypeArray %10 %28
  75. %30 = OpTypeArray %29 %28
  76. %31 = OpTypePointer Function %30
  77. %41 = OpConstant %10 1
  78. %53 = OpTypePointer Function %29
  79. %60 = OpConstant %10 2
  80. %4 = OpFunction %2 None %3
  81. %5 = OpLabel
  82. %63 = OpFunctionCall %2 %6
  83. %64 = OpFunctionCall %2 %8
  84. OpReturn
  85. OpFunctionEnd
  86. %6 = OpFunction %2 None %3
  87. %7 = OpLabel
  88. %12 = OpVariable %11 Function
  89. %14 = OpVariable %11 Function
  90. %32 = OpVariable %31 Function
  91. OpStore %12 %13
  92. OpStore %14 %13
  93. OpBranch %15
  94. %15 = OpLabel
  95. %65 = OpPhi %10 %13 %7 %42 %18
  96. %66 = OpPhi %10 %13 %7 %44 %18
  97. OpLoopMerge %17 %18 None
  98. OpBranch %19
  99. %19 = OpLabel
  100. %23 = OpSLessThan %22 %65 %21
  101. %25 = OpSLessThan %22 %66 %21
  102. %26 = OpLogicalAnd %22 %23 %25
  103. OpBranchConditional %26 %16 %17
  104. %16 = OpLabel
  105. %37 = OpAccessChain %11 %32 %65 %66
  106. %38 = OpLoad %10 %37
  107. %39 = OpAccessChain %11 %32 %65 %66
  108. OpStore %39 %38
  109. OpBranch %18
  110. %18 = OpLabel
  111. %42 = OpIAdd %10 %65 %41
  112. OpStore %12 %42
  113. %44 = OpIAdd %10 %66 %41
  114. OpStore %14 %44
  115. OpBranch %15
  116. %17 = OpLabel
  117. OpReturn
  118. OpFunctionEnd
  119. %8 = OpFunction %2 None %3
  120. %9 = OpLabel
  121. %45 = OpVariable %11 Function
  122. %54 = OpVariable %53 Function
  123. OpStore %45 %13
  124. OpBranch %46
  125. %46 = OpLabel
  126. %67 = OpPhi %10 %13 %9 %62 %49
  127. OpLoopMerge %48 %49 None
  128. OpBranch %50
  129. %50 = OpLabel
  130. %52 = OpSLessThan %22 %67 %21
  131. OpBranchConditional %52 %47 %48
  132. %47 = OpLabel
  133. %57 = OpAccessChain %11 %54 %67
  134. %58 = OpLoad %10 %57
  135. %59 = OpAccessChain %11 %54 %67
  136. OpStore %59 %58
  137. OpBranch %49
  138. %49 = OpLabel
  139. %62 = OpIAdd %10 %67 %60
  140. OpStore %45 %62
  141. OpBranch %46
  142. %48 = OpLabel
  143. OpReturn
  144. OpFunctionEnd
  145. )";
  146. std::unique_ptr<IRContext> context =
  147. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  148. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  149. Module* module = context->module();
  150. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  151. << text << std::endl;
  152. {
  153. // Function a
  154. const Function* f = spvtest::GetFunction(module, 6);
  155. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  156. Loop* loop = &ld.GetLoopByIndex(0);
  157. std::vector<const Loop*> loops{loop};
  158. LoopDependenceAnalysis analysis{context.get(), loops};
  159. const Instruction* store[1] = {nullptr};
  160. int stores_found = 0;
  161. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 16)) {
  162. if (inst.opcode() == spv::Op::OpStore) {
  163. store[stores_found] = &inst;
  164. ++stores_found;
  165. }
  166. }
  167. // 38 -> 39
  168. DistanceVector distance_vector{loops.size()};
  169. EXPECT_FALSE(analysis.IsSupportedLoop(loops[0]));
  170. EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(38),
  171. store[0], &distance_vector));
  172. EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information,
  173. DistanceEntry::DependenceInformation::UNKNOWN);
  174. EXPECT_EQ(distance_vector.GetEntries()[0].direction,
  175. DistanceEntry::Directions::ALL);
  176. }
  177. {
  178. // Function b
  179. const Function* f = spvtest::GetFunction(module, 8);
  180. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  181. Loop* loop = &ld.GetLoopByIndex(0);
  182. std::vector<const Loop*> loops{loop};
  183. LoopDependenceAnalysis analysis{context.get(), loops};
  184. const Instruction* store[1] = {nullptr};
  185. int stores_found = 0;
  186. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 47)) {
  187. if (inst.opcode() == spv::Op::OpStore) {
  188. store[stores_found] = &inst;
  189. ++stores_found;
  190. }
  191. }
  192. // 58 -> 59
  193. DistanceVector distance_vector{loops.size()};
  194. EXPECT_FALSE(analysis.IsSupportedLoop(loops[0]));
  195. EXPECT_FALSE(analysis.GetDependence(context->get_def_use_mgr()->GetDef(58),
  196. store[0], &distance_vector));
  197. EXPECT_EQ(distance_vector.GetEntries()[0].dependence_information,
  198. DistanceEntry::DependenceInformation::UNKNOWN);
  199. EXPECT_EQ(distance_vector.GetEntries()[0].direction,
  200. DistanceEntry::Directions::ALL);
  201. }
  202. }
  203. /*
  204. Generated from the following GLSL fragment shader
  205. with --eliminate-local-multi-store
  206. #version 440 core
  207. void a() {
  208. for (int i = -10; i < 0; i++) {
  209. }
  210. }
  211. void b() {
  212. for (int i = -5; i < 5; i++) {
  213. }
  214. }
  215. void c() {
  216. for (int i = 0; i < 10; i++) {
  217. }
  218. }
  219. void d() {
  220. for (int i = 5; i < 15; i++) {
  221. }
  222. }
  223. void e() {
  224. for (int i = -10; i <= 0; i++) {
  225. }
  226. }
  227. void f() {
  228. for (int i = -5; i <= 5; i++) {
  229. }
  230. }
  231. void g() {
  232. for (int i = 0; i <= 10; i++) {
  233. }
  234. }
  235. void h() {
  236. for (int i = 5; i <= 15; i++) {
  237. }
  238. }
  239. void i() {
  240. for (int i = 0; i > -10; i--) {
  241. }
  242. }
  243. void j() {
  244. for (int i = 5; i > -5; i--) {
  245. }
  246. }
  247. void k() {
  248. for (int i = 10; i > 0; i--) {
  249. }
  250. }
  251. void l() {
  252. for (int i = 15; i > 5; i--) {
  253. }
  254. }
  255. void m() {
  256. for (int i = 0; i >= -10; i--) {
  257. }
  258. }
  259. void n() {
  260. for (int i = 5; i >= -5; i--) {
  261. }
  262. }
  263. void o() {
  264. for (int i = 10; i >= 0; i--) {
  265. }
  266. }
  267. void p() {
  268. for (int i = 15; i >= 5; i--) {
  269. }
  270. }
  271. void main(){
  272. a();
  273. b();
  274. c();
  275. d();
  276. e();
  277. f();
  278. g();
  279. h();
  280. i();
  281. j();
  282. k();
  283. l();
  284. m();
  285. n();
  286. o();
  287. p();
  288. }
  289. */
  290. TEST(DependencyAnalysisHelpers, loop_information) {
  291. const std::string text = R"( OpCapability Shader
  292. %1 = OpExtInstImport "GLSL.std.450"
  293. OpMemoryModel Logical GLSL450
  294. OpEntryPoint Fragment %4 "main"
  295. OpExecutionMode %4 OriginUpperLeft
  296. OpSource GLSL 440
  297. OpName %4 "main"
  298. OpName %6 "a("
  299. OpName %8 "b("
  300. OpName %10 "c("
  301. OpName %12 "d("
  302. OpName %14 "e("
  303. OpName %16 "f("
  304. OpName %18 "g("
  305. OpName %20 "h("
  306. OpName %22 "i("
  307. OpName %24 "j("
  308. OpName %26 "k("
  309. OpName %28 "l("
  310. OpName %30 "m("
  311. OpName %32 "n("
  312. OpName %34 "o("
  313. OpName %36 "p("
  314. OpName %40 "i"
  315. OpName %54 "i"
  316. OpName %66 "i"
  317. OpName %77 "i"
  318. OpName %88 "i"
  319. OpName %98 "i"
  320. OpName %108 "i"
  321. OpName %118 "i"
  322. OpName %128 "i"
  323. OpName %138 "i"
  324. OpName %148 "i"
  325. OpName %158 "i"
  326. OpName %168 "i"
  327. OpName %178 "i"
  328. OpName %188 "i"
  329. OpName %198 "i"
  330. %2 = OpTypeVoid
  331. %3 = OpTypeFunction %2
  332. %38 = OpTypeInt 32 1
  333. %39 = OpTypePointer Function %38
  334. %41 = OpConstant %38 -10
  335. %48 = OpConstant %38 0
  336. %49 = OpTypeBool
  337. %52 = OpConstant %38 1
  338. %55 = OpConstant %38 -5
  339. %62 = OpConstant %38 5
  340. %73 = OpConstant %38 10
  341. %84 = OpConstant %38 15
  342. %4 = OpFunction %2 None %3
  343. %5 = OpLabel
  344. %208 = OpFunctionCall %2 %6
  345. %209 = OpFunctionCall %2 %8
  346. %210 = OpFunctionCall %2 %10
  347. %211 = OpFunctionCall %2 %12
  348. %212 = OpFunctionCall %2 %14
  349. %213 = OpFunctionCall %2 %16
  350. %214 = OpFunctionCall %2 %18
  351. %215 = OpFunctionCall %2 %20
  352. %216 = OpFunctionCall %2 %22
  353. %217 = OpFunctionCall %2 %24
  354. %218 = OpFunctionCall %2 %26
  355. %219 = OpFunctionCall %2 %28
  356. %220 = OpFunctionCall %2 %30
  357. %221 = OpFunctionCall %2 %32
  358. %222 = OpFunctionCall %2 %34
  359. %223 = OpFunctionCall %2 %36
  360. OpReturn
  361. OpFunctionEnd
  362. %6 = OpFunction %2 None %3
  363. %7 = OpLabel
  364. %40 = OpVariable %39 Function
  365. OpStore %40 %41
  366. OpBranch %42
  367. %42 = OpLabel
  368. %224 = OpPhi %38 %41 %7 %53 %45
  369. OpLoopMerge %44 %45 None
  370. OpBranch %46
  371. %46 = OpLabel
  372. %50 = OpSLessThan %49 %224 %48
  373. OpBranchConditional %50 %43 %44
  374. %43 = OpLabel
  375. OpBranch %45
  376. %45 = OpLabel
  377. %53 = OpIAdd %38 %224 %52
  378. OpStore %40 %53
  379. OpBranch %42
  380. %44 = OpLabel
  381. OpReturn
  382. OpFunctionEnd
  383. %8 = OpFunction %2 None %3
  384. %9 = OpLabel
  385. %54 = OpVariable %39 Function
  386. OpStore %54 %55
  387. OpBranch %56
  388. %56 = OpLabel
  389. %225 = OpPhi %38 %55 %9 %65 %59
  390. OpLoopMerge %58 %59 None
  391. OpBranch %60
  392. %60 = OpLabel
  393. %63 = OpSLessThan %49 %225 %62
  394. OpBranchConditional %63 %57 %58
  395. %57 = OpLabel
  396. OpBranch %59
  397. %59 = OpLabel
  398. %65 = OpIAdd %38 %225 %52
  399. OpStore %54 %65
  400. OpBranch %56
  401. %58 = OpLabel
  402. OpReturn
  403. OpFunctionEnd
  404. %10 = OpFunction %2 None %3
  405. %11 = OpLabel
  406. %66 = OpVariable %39 Function
  407. OpStore %66 %48
  408. OpBranch %67
  409. %67 = OpLabel
  410. %226 = OpPhi %38 %48 %11 %76 %70
  411. OpLoopMerge %69 %70 None
  412. OpBranch %71
  413. %71 = OpLabel
  414. %74 = OpSLessThan %49 %226 %73
  415. OpBranchConditional %74 %68 %69
  416. %68 = OpLabel
  417. OpBranch %70
  418. %70 = OpLabel
  419. %76 = OpIAdd %38 %226 %52
  420. OpStore %66 %76
  421. OpBranch %67
  422. %69 = OpLabel
  423. OpReturn
  424. OpFunctionEnd
  425. %12 = OpFunction %2 None %3
  426. %13 = OpLabel
  427. %77 = OpVariable %39 Function
  428. OpStore %77 %62
  429. OpBranch %78
  430. %78 = OpLabel
  431. %227 = OpPhi %38 %62 %13 %87 %81
  432. OpLoopMerge %80 %81 None
  433. OpBranch %82
  434. %82 = OpLabel
  435. %85 = OpSLessThan %49 %227 %84
  436. OpBranchConditional %85 %79 %80
  437. %79 = OpLabel
  438. OpBranch %81
  439. %81 = OpLabel
  440. %87 = OpIAdd %38 %227 %52
  441. OpStore %77 %87
  442. OpBranch %78
  443. %80 = OpLabel
  444. OpReturn
  445. OpFunctionEnd
  446. %14 = OpFunction %2 None %3
  447. %15 = OpLabel
  448. %88 = OpVariable %39 Function
  449. OpStore %88 %41
  450. OpBranch %89
  451. %89 = OpLabel
  452. %228 = OpPhi %38 %41 %15 %97 %92
  453. OpLoopMerge %91 %92 None
  454. OpBranch %93
  455. %93 = OpLabel
  456. %95 = OpSLessThanEqual %49 %228 %48
  457. OpBranchConditional %95 %90 %91
  458. %90 = OpLabel
  459. OpBranch %92
  460. %92 = OpLabel
  461. %97 = OpIAdd %38 %228 %52
  462. OpStore %88 %97
  463. OpBranch %89
  464. %91 = OpLabel
  465. OpReturn
  466. OpFunctionEnd
  467. %16 = OpFunction %2 None %3
  468. %17 = OpLabel
  469. %98 = OpVariable %39 Function
  470. OpStore %98 %55
  471. OpBranch %99
  472. %99 = OpLabel
  473. %229 = OpPhi %38 %55 %17 %107 %102
  474. OpLoopMerge %101 %102 None
  475. OpBranch %103
  476. %103 = OpLabel
  477. %105 = OpSLessThanEqual %49 %229 %62
  478. OpBranchConditional %105 %100 %101
  479. %100 = OpLabel
  480. OpBranch %102
  481. %102 = OpLabel
  482. %107 = OpIAdd %38 %229 %52
  483. OpStore %98 %107
  484. OpBranch %99
  485. %101 = OpLabel
  486. OpReturn
  487. OpFunctionEnd
  488. %18 = OpFunction %2 None %3
  489. %19 = OpLabel
  490. %108 = OpVariable %39 Function
  491. OpStore %108 %48
  492. OpBranch %109
  493. %109 = OpLabel
  494. %230 = OpPhi %38 %48 %19 %117 %112
  495. OpLoopMerge %111 %112 None
  496. OpBranch %113
  497. %113 = OpLabel
  498. %115 = OpSLessThanEqual %49 %230 %73
  499. OpBranchConditional %115 %110 %111
  500. %110 = OpLabel
  501. OpBranch %112
  502. %112 = OpLabel
  503. %117 = OpIAdd %38 %230 %52
  504. OpStore %108 %117
  505. OpBranch %109
  506. %111 = OpLabel
  507. OpReturn
  508. OpFunctionEnd
  509. %20 = OpFunction %2 None %3
  510. %21 = OpLabel
  511. %118 = OpVariable %39 Function
  512. OpStore %118 %62
  513. OpBranch %119
  514. %119 = OpLabel
  515. %231 = OpPhi %38 %62 %21 %127 %122
  516. OpLoopMerge %121 %122 None
  517. OpBranch %123
  518. %123 = OpLabel
  519. %125 = OpSLessThanEqual %49 %231 %84
  520. OpBranchConditional %125 %120 %121
  521. %120 = OpLabel
  522. OpBranch %122
  523. %122 = OpLabel
  524. %127 = OpIAdd %38 %231 %52
  525. OpStore %118 %127
  526. OpBranch %119
  527. %121 = OpLabel
  528. OpReturn
  529. OpFunctionEnd
  530. %22 = OpFunction %2 None %3
  531. %23 = OpLabel
  532. %128 = OpVariable %39 Function
  533. OpStore %128 %48
  534. OpBranch %129
  535. %129 = OpLabel
  536. %232 = OpPhi %38 %48 %23 %137 %132
  537. OpLoopMerge %131 %132 None
  538. OpBranch %133
  539. %133 = OpLabel
  540. %135 = OpSGreaterThan %49 %232 %41
  541. OpBranchConditional %135 %130 %131
  542. %130 = OpLabel
  543. OpBranch %132
  544. %132 = OpLabel
  545. %137 = OpISub %38 %232 %52
  546. OpStore %128 %137
  547. OpBranch %129
  548. %131 = OpLabel
  549. OpReturn
  550. OpFunctionEnd
  551. %24 = OpFunction %2 None %3
  552. %25 = OpLabel
  553. %138 = OpVariable %39 Function
  554. OpStore %138 %62
  555. OpBranch %139
  556. %139 = OpLabel
  557. %233 = OpPhi %38 %62 %25 %147 %142
  558. OpLoopMerge %141 %142 None
  559. OpBranch %143
  560. %143 = OpLabel
  561. %145 = OpSGreaterThan %49 %233 %55
  562. OpBranchConditional %145 %140 %141
  563. %140 = OpLabel
  564. OpBranch %142
  565. %142 = OpLabel
  566. %147 = OpISub %38 %233 %52
  567. OpStore %138 %147
  568. OpBranch %139
  569. %141 = OpLabel
  570. OpReturn
  571. OpFunctionEnd
  572. %26 = OpFunction %2 None %3
  573. %27 = OpLabel
  574. %148 = OpVariable %39 Function
  575. OpStore %148 %73
  576. OpBranch %149
  577. %149 = OpLabel
  578. %234 = OpPhi %38 %73 %27 %157 %152
  579. OpLoopMerge %151 %152 None
  580. OpBranch %153
  581. %153 = OpLabel
  582. %155 = OpSGreaterThan %49 %234 %48
  583. OpBranchConditional %155 %150 %151
  584. %150 = OpLabel
  585. OpBranch %152
  586. %152 = OpLabel
  587. %157 = OpISub %38 %234 %52
  588. OpStore %148 %157
  589. OpBranch %149
  590. %151 = OpLabel
  591. OpReturn
  592. OpFunctionEnd
  593. %28 = OpFunction %2 None %3
  594. %29 = OpLabel
  595. %158 = OpVariable %39 Function
  596. OpStore %158 %84
  597. OpBranch %159
  598. %159 = OpLabel
  599. %235 = OpPhi %38 %84 %29 %167 %162
  600. OpLoopMerge %161 %162 None
  601. OpBranch %163
  602. %163 = OpLabel
  603. %165 = OpSGreaterThan %49 %235 %62
  604. OpBranchConditional %165 %160 %161
  605. %160 = OpLabel
  606. OpBranch %162
  607. %162 = OpLabel
  608. %167 = OpISub %38 %235 %52
  609. OpStore %158 %167
  610. OpBranch %159
  611. %161 = OpLabel
  612. OpReturn
  613. OpFunctionEnd
  614. %30 = OpFunction %2 None %3
  615. %31 = OpLabel
  616. %168 = OpVariable %39 Function
  617. OpStore %168 %48
  618. OpBranch %169
  619. %169 = OpLabel
  620. %236 = OpPhi %38 %48 %31 %177 %172
  621. OpLoopMerge %171 %172 None
  622. OpBranch %173
  623. %173 = OpLabel
  624. %175 = OpSGreaterThanEqual %49 %236 %41
  625. OpBranchConditional %175 %170 %171
  626. %170 = OpLabel
  627. OpBranch %172
  628. %172 = OpLabel
  629. %177 = OpISub %38 %236 %52
  630. OpStore %168 %177
  631. OpBranch %169
  632. %171 = OpLabel
  633. OpReturn
  634. OpFunctionEnd
  635. %32 = OpFunction %2 None %3
  636. %33 = OpLabel
  637. %178 = OpVariable %39 Function
  638. OpStore %178 %62
  639. OpBranch %179
  640. %179 = OpLabel
  641. %237 = OpPhi %38 %62 %33 %187 %182
  642. OpLoopMerge %181 %182 None
  643. OpBranch %183
  644. %183 = OpLabel
  645. %185 = OpSGreaterThanEqual %49 %237 %55
  646. OpBranchConditional %185 %180 %181
  647. %180 = OpLabel
  648. OpBranch %182
  649. %182 = OpLabel
  650. %187 = OpISub %38 %237 %52
  651. OpStore %178 %187
  652. OpBranch %179
  653. %181 = OpLabel
  654. OpReturn
  655. OpFunctionEnd
  656. %34 = OpFunction %2 None %3
  657. %35 = OpLabel
  658. %188 = OpVariable %39 Function
  659. OpStore %188 %73
  660. OpBranch %189
  661. %189 = OpLabel
  662. %238 = OpPhi %38 %73 %35 %197 %192
  663. OpLoopMerge %191 %192 None
  664. OpBranch %193
  665. %193 = OpLabel
  666. %195 = OpSGreaterThanEqual %49 %238 %48
  667. OpBranchConditional %195 %190 %191
  668. %190 = OpLabel
  669. OpBranch %192
  670. %192 = OpLabel
  671. %197 = OpISub %38 %238 %52
  672. OpStore %188 %197
  673. OpBranch %189
  674. %191 = OpLabel
  675. OpReturn
  676. OpFunctionEnd
  677. %36 = OpFunction %2 None %3
  678. %37 = OpLabel
  679. %198 = OpVariable %39 Function
  680. OpStore %198 %84
  681. OpBranch %199
  682. %199 = OpLabel
  683. %239 = OpPhi %38 %84 %37 %207 %202
  684. OpLoopMerge %201 %202 None
  685. OpBranch %203
  686. %203 = OpLabel
  687. %205 = OpSGreaterThanEqual %49 %239 %62
  688. OpBranchConditional %205 %200 %201
  689. %200 = OpLabel
  690. OpBranch %202
  691. %202 = OpLabel
  692. %207 = OpISub %38 %239 %52
  693. OpStore %198 %207
  694. OpBranch %199
  695. %201 = OpLabel
  696. OpReturn
  697. OpFunctionEnd
  698. )";
  699. std::unique_ptr<IRContext> context =
  700. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  701. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  702. Module* module = context->module();
  703. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  704. << text << std::endl;
  705. {
  706. // Function a
  707. const Function* f = spvtest::GetFunction(module, 6);
  708. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  709. Loop* loop = &ld.GetLoopByIndex(0);
  710. std::vector<const Loop*> loops{loop};
  711. LoopDependenceAnalysis analysis{context.get(), loops};
  712. EXPECT_EQ(
  713. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  714. -10);
  715. EXPECT_EQ(
  716. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  717. -1);
  718. EXPECT_EQ(
  719. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  720. 10);
  721. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  722. analysis.GetScalarEvolution()->CreateConstant(-10));
  723. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  724. loop, analysis.GetScalarEvolution()->CreateConstant(1)),
  725. analysis.GetScalarEvolution()->CreateConstant(-1));
  726. }
  727. {
  728. // Function b
  729. const Function* f = spvtest::GetFunction(module, 8);
  730. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  731. Loop* loop = &ld.GetLoopByIndex(0);
  732. std::vector<const Loop*> loops{loop};
  733. LoopDependenceAnalysis analysis{context.get(), loops};
  734. EXPECT_EQ(
  735. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  736. -5);
  737. EXPECT_EQ(
  738. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  739. 4);
  740. EXPECT_EQ(
  741. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  742. 10);
  743. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  744. analysis.GetScalarEvolution()->CreateConstant(-5));
  745. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  746. loop, analysis.GetScalarEvolution()->CreateConstant(1)),
  747. analysis.GetScalarEvolution()->CreateConstant(4));
  748. }
  749. {
  750. // Function c
  751. const Function* f = spvtest::GetFunction(module, 10);
  752. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  753. Loop* loop = &ld.GetLoopByIndex(0);
  754. std::vector<const Loop*> loops{loop};
  755. LoopDependenceAnalysis analysis{context.get(), loops};
  756. EXPECT_EQ(
  757. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  758. 0);
  759. EXPECT_EQ(
  760. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  761. 9);
  762. EXPECT_EQ(
  763. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  764. 10);
  765. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  766. analysis.GetScalarEvolution()->CreateConstant(0));
  767. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  768. loop, analysis.GetScalarEvolution()->CreateConstant(1)),
  769. analysis.GetScalarEvolution()->CreateConstant(9));
  770. }
  771. {
  772. // Function d
  773. const Function* f = spvtest::GetFunction(module, 12);
  774. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  775. Loop* loop = &ld.GetLoopByIndex(0);
  776. std::vector<const Loop*> loops{loop};
  777. LoopDependenceAnalysis analysis{context.get(), loops};
  778. EXPECT_EQ(
  779. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  780. 5);
  781. EXPECT_EQ(
  782. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  783. 14);
  784. EXPECT_EQ(
  785. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  786. 10);
  787. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  788. analysis.GetScalarEvolution()->CreateConstant(5));
  789. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  790. loop, analysis.GetScalarEvolution()->CreateConstant(1)),
  791. analysis.GetScalarEvolution()->CreateConstant(14));
  792. }
  793. {
  794. // Function e
  795. const Function* f = spvtest::GetFunction(module, 14);
  796. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  797. Loop* loop = &ld.GetLoopByIndex(0);
  798. std::vector<const Loop*> loops{loop};
  799. LoopDependenceAnalysis analysis{context.get(), loops};
  800. EXPECT_EQ(
  801. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  802. -10);
  803. EXPECT_EQ(
  804. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  805. 0);
  806. EXPECT_EQ(
  807. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  808. 11);
  809. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  810. analysis.GetScalarEvolution()->CreateConstant(-10));
  811. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  812. loop, analysis.GetScalarEvolution()->CreateConstant(1)),
  813. analysis.GetScalarEvolution()->CreateConstant(0));
  814. }
  815. {
  816. // Function f
  817. const Function* f = spvtest::GetFunction(module, 16);
  818. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  819. Loop* loop = &ld.GetLoopByIndex(0);
  820. std::vector<const Loop*> loops{loop};
  821. LoopDependenceAnalysis analysis{context.get(), loops};
  822. EXPECT_EQ(
  823. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  824. -5);
  825. EXPECT_EQ(
  826. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  827. 5);
  828. EXPECT_EQ(
  829. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  830. 11);
  831. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  832. analysis.GetScalarEvolution()->CreateConstant(-5));
  833. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  834. loop, analysis.GetScalarEvolution()->CreateConstant(1)),
  835. analysis.GetScalarEvolution()->CreateConstant(5));
  836. }
  837. {
  838. // Function g
  839. const Function* f = spvtest::GetFunction(module, 18);
  840. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  841. Loop* loop = &ld.GetLoopByIndex(0);
  842. std::vector<const Loop*> loops{loop};
  843. LoopDependenceAnalysis analysis{context.get(), loops};
  844. EXPECT_EQ(
  845. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  846. 0);
  847. EXPECT_EQ(
  848. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  849. 10);
  850. EXPECT_EQ(
  851. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  852. 11);
  853. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  854. analysis.GetScalarEvolution()->CreateConstant(0));
  855. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  856. loop, analysis.GetScalarEvolution()->CreateConstant(1)),
  857. analysis.GetScalarEvolution()->CreateConstant(10));
  858. }
  859. {
  860. // Function h
  861. const Function* f = spvtest::GetFunction(module, 20);
  862. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  863. Loop* loop = &ld.GetLoopByIndex(0);
  864. std::vector<const Loop*> loops{loop};
  865. LoopDependenceAnalysis analysis{context.get(), loops};
  866. EXPECT_EQ(
  867. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  868. 5);
  869. EXPECT_EQ(
  870. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  871. 15);
  872. EXPECT_EQ(
  873. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  874. 11);
  875. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  876. analysis.GetScalarEvolution()->CreateConstant(5));
  877. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  878. loop, analysis.GetScalarEvolution()->CreateConstant(1)),
  879. analysis.GetScalarEvolution()->CreateConstant(15));
  880. }
  881. {
  882. // Function i
  883. const Function* f = spvtest::GetFunction(module, 22);
  884. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  885. Loop* loop = &ld.GetLoopByIndex(0);
  886. std::vector<const Loop*> loops{loop};
  887. LoopDependenceAnalysis analysis{context.get(), loops};
  888. EXPECT_EQ(
  889. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  890. 0);
  891. EXPECT_EQ(
  892. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  893. -9);
  894. EXPECT_EQ(
  895. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  896. 10);
  897. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  898. analysis.GetScalarEvolution()->CreateConstant(0));
  899. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  900. loop, analysis.GetScalarEvolution()->CreateConstant(-1)),
  901. analysis.GetScalarEvolution()->CreateConstant(-9));
  902. }
  903. {
  904. // Function j
  905. const Function* f = spvtest::GetFunction(module, 24);
  906. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  907. Loop* loop = &ld.GetLoopByIndex(0);
  908. std::vector<const Loop*> loops{loop};
  909. LoopDependenceAnalysis analysis{context.get(), loops};
  910. EXPECT_EQ(
  911. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  912. 5);
  913. EXPECT_EQ(
  914. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  915. -4);
  916. EXPECT_EQ(
  917. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  918. 10);
  919. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  920. analysis.GetScalarEvolution()->CreateConstant(5));
  921. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  922. loop, analysis.GetScalarEvolution()->CreateConstant(-1)),
  923. analysis.GetScalarEvolution()->CreateConstant(-4));
  924. }
  925. {
  926. // Function k
  927. const Function* f = spvtest::GetFunction(module, 26);
  928. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  929. Loop* loop = &ld.GetLoopByIndex(0);
  930. std::vector<const Loop*> loops{loop};
  931. LoopDependenceAnalysis analysis{context.get(), loops};
  932. EXPECT_EQ(
  933. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  934. 10);
  935. EXPECT_EQ(
  936. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  937. 1);
  938. EXPECT_EQ(
  939. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  940. 10);
  941. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  942. analysis.GetScalarEvolution()->CreateConstant(10));
  943. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  944. loop, analysis.GetScalarEvolution()->CreateConstant(-1)),
  945. analysis.GetScalarEvolution()->CreateConstant(1));
  946. }
  947. {
  948. // Function l
  949. const Function* f = spvtest::GetFunction(module, 28);
  950. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  951. Loop* loop = &ld.GetLoopByIndex(0);
  952. std::vector<const Loop*> loops{loop};
  953. LoopDependenceAnalysis analysis{context.get(), loops};
  954. EXPECT_EQ(
  955. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  956. 15);
  957. EXPECT_EQ(
  958. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  959. 6);
  960. EXPECT_EQ(
  961. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  962. 10);
  963. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  964. analysis.GetScalarEvolution()->CreateConstant(15));
  965. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  966. loop, analysis.GetScalarEvolution()->CreateConstant(-1)),
  967. analysis.GetScalarEvolution()->CreateConstant(6));
  968. }
  969. {
  970. // Function m
  971. const Function* f = spvtest::GetFunction(module, 30);
  972. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  973. Loop* loop = &ld.GetLoopByIndex(0);
  974. std::vector<const Loop*> loops{loop};
  975. LoopDependenceAnalysis analysis{context.get(), loops};
  976. EXPECT_EQ(
  977. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  978. 0);
  979. EXPECT_EQ(
  980. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  981. -10);
  982. EXPECT_EQ(
  983. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  984. 11);
  985. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  986. analysis.GetScalarEvolution()->CreateConstant(0));
  987. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  988. loop, analysis.GetScalarEvolution()->CreateConstant(-1)),
  989. analysis.GetScalarEvolution()->CreateConstant(-10));
  990. }
  991. {
  992. // Function n
  993. const Function* f = spvtest::GetFunction(module, 32);
  994. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  995. Loop* loop = &ld.GetLoopByIndex(0);
  996. std::vector<const Loop*> loops{loop};
  997. LoopDependenceAnalysis analysis{context.get(), loops};
  998. EXPECT_EQ(
  999. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  1000. 5);
  1001. EXPECT_EQ(
  1002. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  1003. -5);
  1004. EXPECT_EQ(
  1005. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  1006. 11);
  1007. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  1008. analysis.GetScalarEvolution()->CreateConstant(5));
  1009. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  1010. loop, analysis.GetScalarEvolution()->CreateConstant(-1)),
  1011. analysis.GetScalarEvolution()->CreateConstant(-5));
  1012. }
  1013. {
  1014. // Function o
  1015. const Function* f = spvtest::GetFunction(module, 34);
  1016. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  1017. Loop* loop = &ld.GetLoopByIndex(0);
  1018. std::vector<const Loop*> loops{loop};
  1019. LoopDependenceAnalysis analysis{context.get(), loops};
  1020. EXPECT_EQ(
  1021. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  1022. 10);
  1023. EXPECT_EQ(
  1024. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  1025. 0);
  1026. EXPECT_EQ(
  1027. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  1028. 11);
  1029. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  1030. analysis.GetScalarEvolution()->CreateConstant(10));
  1031. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  1032. loop, analysis.GetScalarEvolution()->CreateConstant(-1)),
  1033. analysis.GetScalarEvolution()->CreateConstant(0));
  1034. }
  1035. {
  1036. // Function p
  1037. const Function* f = spvtest::GetFunction(module, 36);
  1038. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  1039. Loop* loop = &ld.GetLoopByIndex(0);
  1040. std::vector<const Loop*> loops{loop};
  1041. LoopDependenceAnalysis analysis{context.get(), loops};
  1042. EXPECT_EQ(
  1043. analysis.GetLowerBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  1044. 15);
  1045. EXPECT_EQ(
  1046. analysis.GetUpperBound(loop)->AsSEConstantNode()->FoldToSingleValue(),
  1047. 5);
  1048. EXPECT_EQ(
  1049. analysis.GetTripCount(loop)->AsSEConstantNode()->FoldToSingleValue(),
  1050. 11);
  1051. EXPECT_EQ(analysis.GetFirstTripInductionNode(loop),
  1052. analysis.GetScalarEvolution()->CreateConstant(15));
  1053. EXPECT_EQ(analysis.GetFinalTripInductionNode(
  1054. loop, analysis.GetScalarEvolution()->CreateConstant(-1)),
  1055. analysis.GetScalarEvolution()->CreateConstant(5));
  1056. }
  1057. }
  1058. /*
  1059. Generated from the following GLSL fragment shader
  1060. with --eliminate-local-multi-store
  1061. #version 440 core
  1062. void main(){
  1063. for (int i = 0; i < 10; i++) {
  1064. }
  1065. }
  1066. */
  1067. TEST(DependencyAnalysisHelpers, bounds_checks) {
  1068. const std::string text = R"( OpCapability Shader
  1069. %1 = OpExtInstImport "GLSL.std.450"
  1070. OpMemoryModel Logical GLSL450
  1071. OpEntryPoint Fragment %4 "main"
  1072. OpExecutionMode %4 OriginUpperLeft
  1073. OpSource GLSL 440
  1074. OpName %4 "main"
  1075. OpName %8 "i"
  1076. %2 = OpTypeVoid
  1077. %3 = OpTypeFunction %2
  1078. %6 = OpTypeInt 32 1
  1079. %7 = OpTypePointer Function %6
  1080. %9 = OpConstant %6 0
  1081. %16 = OpConstant %6 10
  1082. %17 = OpTypeBool
  1083. %20 = OpConstant %6 1
  1084. %4 = OpFunction %2 None %3
  1085. %5 = OpLabel
  1086. %8 = OpVariable %7 Function
  1087. OpStore %8 %9
  1088. OpBranch %10
  1089. %10 = OpLabel
  1090. %22 = OpPhi %6 %9 %5 %21 %13
  1091. OpLoopMerge %12 %13 None
  1092. OpBranch %14
  1093. %14 = OpLabel
  1094. %18 = OpSLessThan %17 %22 %16
  1095. OpBranchConditional %18 %11 %12
  1096. %11 = OpLabel
  1097. OpBranch %13
  1098. %13 = OpLabel
  1099. %21 = OpIAdd %6 %22 %20
  1100. OpStore %8 %21
  1101. OpBranch %10
  1102. %12 = OpLabel
  1103. OpReturn
  1104. OpFunctionEnd
  1105. )";
  1106. std::unique_ptr<IRContext> context =
  1107. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  1108. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1109. Module* module = context->module();
  1110. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1111. << text << std::endl;
  1112. // We need a shader that includes a loop for this test so we can build a
  1113. // LoopDependenceAnalaysis
  1114. const Function* f = spvtest::GetFunction(module, 4);
  1115. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  1116. Loop* loop = &ld.GetLoopByIndex(0);
  1117. std::vector<const Loop*> loops{loop};
  1118. LoopDependenceAnalysis analysis{context.get(), loops};
  1119. EXPECT_TRUE(analysis.IsWithinBounds(0, 0, 0));
  1120. EXPECT_TRUE(analysis.IsWithinBounds(0, -1, 0));
  1121. EXPECT_TRUE(analysis.IsWithinBounds(0, 0, 1));
  1122. EXPECT_TRUE(analysis.IsWithinBounds(0, -1, 1));
  1123. EXPECT_TRUE(analysis.IsWithinBounds(-2, -2, -2));
  1124. EXPECT_TRUE(analysis.IsWithinBounds(-2, -3, 0));
  1125. EXPECT_TRUE(analysis.IsWithinBounds(-2, 0, -3));
  1126. EXPECT_TRUE(analysis.IsWithinBounds(2, 2, 2));
  1127. EXPECT_TRUE(analysis.IsWithinBounds(2, 3, 0));
  1128. EXPECT_FALSE(analysis.IsWithinBounds(2, 3, 3));
  1129. EXPECT_FALSE(analysis.IsWithinBounds(0, 1, 5));
  1130. EXPECT_FALSE(analysis.IsWithinBounds(0, -1, -4));
  1131. EXPECT_FALSE(analysis.IsWithinBounds(-2, -4, -3));
  1132. }
  1133. /*
  1134. Generated from the following GLSL fragment shader
  1135. with --eliminate-local-multi-store
  1136. #version 440 core
  1137. layout(location = 0) in vec4 in_vec;
  1138. // Loop iterates from constant to symbolic
  1139. void a() {
  1140. int N = int(in_vec.x);
  1141. int arr[10];
  1142. for (int i = 0; i < N; i++) { // Bounds are N - 0 - 1
  1143. arr[i] = arr[i+N]; // |distance| = N
  1144. arr[i+N] = arr[i]; // |distance| = N
  1145. }
  1146. }
  1147. void b() {
  1148. int N = int(in_vec.x);
  1149. int arr[10];
  1150. for (int i = 0; i <= N; i++) { // Bounds are N - 0
  1151. arr[i] = arr[i+N]; // |distance| = N
  1152. arr[i+N] = arr[i]; // |distance| = N
  1153. }
  1154. }
  1155. void c() {
  1156. int N = int(in_vec.x);
  1157. int arr[10];
  1158. for (int i = 9; i > N; i--) { // Bounds are 9 - N - 1
  1159. arr[i] = arr[i+N]; // |distance| = N
  1160. arr[i+N] = arr[i]; // |distance| = N
  1161. }
  1162. }
  1163. void d() {
  1164. int N = int(in_vec.x);
  1165. int arr[10];
  1166. for (int i = 9; i >= N; i--) { // Bounds are 9 - N
  1167. arr[i] = arr[i+N]; // |distance| = N
  1168. arr[i+N] = arr[i]; // |distance| = N
  1169. }
  1170. }
  1171. void main(){
  1172. a();
  1173. b();
  1174. c();
  1175. d();
  1176. }
  1177. */
  1178. TEST(DependencyAnalysisHelpers, const_to_symbolic) {
  1179. const std::string text = R"( OpCapability Shader
  1180. %1 = OpExtInstImport "GLSL.std.450"
  1181. OpMemoryModel Logical GLSL450
  1182. OpEntryPoint Fragment %4 "main" %20
  1183. OpExecutionMode %4 OriginUpperLeft
  1184. OpSource GLSL 440
  1185. OpName %4 "main"
  1186. OpName %6 "a("
  1187. OpName %8 "b("
  1188. OpName %10 "c("
  1189. OpName %12 "d("
  1190. OpName %16 "N"
  1191. OpName %20 "in_vec"
  1192. OpName %27 "i"
  1193. OpName %41 "arr"
  1194. OpName %59 "N"
  1195. OpName %63 "i"
  1196. OpName %72 "arr"
  1197. OpName %89 "N"
  1198. OpName %93 "i"
  1199. OpName %103 "arr"
  1200. OpName %120 "N"
  1201. OpName %124 "i"
  1202. OpName %133 "arr"
  1203. OpDecorate %20 Location 0
  1204. %2 = OpTypeVoid
  1205. %3 = OpTypeFunction %2
  1206. %14 = OpTypeInt 32 1
  1207. %15 = OpTypePointer Function %14
  1208. %17 = OpTypeFloat 32
  1209. %18 = OpTypeVector %17 4
  1210. %19 = OpTypePointer Input %18
  1211. %20 = OpVariable %19 Input
  1212. %21 = OpTypeInt 32 0
  1213. %22 = OpConstant %21 0
  1214. %23 = OpTypePointer Input %17
  1215. %28 = OpConstant %14 0
  1216. %36 = OpTypeBool
  1217. %38 = OpConstant %21 10
  1218. %39 = OpTypeArray %14 %38
  1219. %40 = OpTypePointer Function %39
  1220. %57 = OpConstant %14 1
  1221. %94 = OpConstant %14 9
  1222. %4 = OpFunction %2 None %3
  1223. %5 = OpLabel
  1224. %150 = OpFunctionCall %2 %6
  1225. %151 = OpFunctionCall %2 %8
  1226. %152 = OpFunctionCall %2 %10
  1227. %153 = OpFunctionCall %2 %12
  1228. OpReturn
  1229. OpFunctionEnd
  1230. %6 = OpFunction %2 None %3
  1231. %7 = OpLabel
  1232. %16 = OpVariable %15 Function
  1233. %27 = OpVariable %15 Function
  1234. %41 = OpVariable %40 Function
  1235. %24 = OpAccessChain %23 %20 %22
  1236. %25 = OpLoad %17 %24
  1237. %26 = OpConvertFToS %14 %25
  1238. OpStore %16 %26
  1239. OpStore %27 %28
  1240. OpBranch %29
  1241. %29 = OpLabel
  1242. %154 = OpPhi %14 %28 %7 %58 %32
  1243. OpLoopMerge %31 %32 None
  1244. OpBranch %33
  1245. %33 = OpLabel
  1246. %37 = OpSLessThan %36 %154 %26
  1247. OpBranchConditional %37 %30 %31
  1248. %30 = OpLabel
  1249. %45 = OpIAdd %14 %154 %26
  1250. %46 = OpAccessChain %15 %41 %45
  1251. %47 = OpLoad %14 %46
  1252. %48 = OpAccessChain %15 %41 %154
  1253. OpStore %48 %47
  1254. %51 = OpIAdd %14 %154 %26
  1255. %53 = OpAccessChain %15 %41 %154
  1256. %54 = OpLoad %14 %53
  1257. %55 = OpAccessChain %15 %41 %51
  1258. OpStore %55 %54
  1259. OpBranch %32
  1260. %32 = OpLabel
  1261. %58 = OpIAdd %14 %154 %57
  1262. OpStore %27 %58
  1263. OpBranch %29
  1264. %31 = OpLabel
  1265. OpReturn
  1266. OpFunctionEnd
  1267. %8 = OpFunction %2 None %3
  1268. %9 = OpLabel
  1269. %59 = OpVariable %15 Function
  1270. %63 = OpVariable %15 Function
  1271. %72 = OpVariable %40 Function
  1272. %60 = OpAccessChain %23 %20 %22
  1273. %61 = OpLoad %17 %60
  1274. %62 = OpConvertFToS %14 %61
  1275. OpStore %59 %62
  1276. OpStore %63 %28
  1277. OpBranch %64
  1278. %64 = OpLabel
  1279. %155 = OpPhi %14 %28 %9 %88 %67
  1280. OpLoopMerge %66 %67 None
  1281. OpBranch %68
  1282. %68 = OpLabel
  1283. %71 = OpSLessThanEqual %36 %155 %62
  1284. OpBranchConditional %71 %65 %66
  1285. %65 = OpLabel
  1286. %76 = OpIAdd %14 %155 %62
  1287. %77 = OpAccessChain %15 %72 %76
  1288. %78 = OpLoad %14 %77
  1289. %79 = OpAccessChain %15 %72 %155
  1290. OpStore %79 %78
  1291. %82 = OpIAdd %14 %155 %62
  1292. %84 = OpAccessChain %15 %72 %155
  1293. %85 = OpLoad %14 %84
  1294. %86 = OpAccessChain %15 %72 %82
  1295. OpStore %86 %85
  1296. OpBranch %67
  1297. %67 = OpLabel
  1298. %88 = OpIAdd %14 %155 %57
  1299. OpStore %63 %88
  1300. OpBranch %64
  1301. %66 = OpLabel
  1302. OpReturn
  1303. OpFunctionEnd
  1304. %10 = OpFunction %2 None %3
  1305. %11 = OpLabel
  1306. %89 = OpVariable %15 Function
  1307. %93 = OpVariable %15 Function
  1308. %103 = OpVariable %40 Function
  1309. %90 = OpAccessChain %23 %20 %22
  1310. %91 = OpLoad %17 %90
  1311. %92 = OpConvertFToS %14 %91
  1312. OpStore %89 %92
  1313. OpStore %93 %94
  1314. OpBranch %95
  1315. %95 = OpLabel
  1316. %156 = OpPhi %14 %94 %11 %119 %98
  1317. OpLoopMerge %97 %98 None
  1318. OpBranch %99
  1319. %99 = OpLabel
  1320. %102 = OpSGreaterThan %36 %156 %92
  1321. OpBranchConditional %102 %96 %97
  1322. %96 = OpLabel
  1323. %107 = OpIAdd %14 %156 %92
  1324. %108 = OpAccessChain %15 %103 %107
  1325. %109 = OpLoad %14 %108
  1326. %110 = OpAccessChain %15 %103 %156
  1327. OpStore %110 %109
  1328. %113 = OpIAdd %14 %156 %92
  1329. %115 = OpAccessChain %15 %103 %156
  1330. %116 = OpLoad %14 %115
  1331. %117 = OpAccessChain %15 %103 %113
  1332. OpStore %117 %116
  1333. OpBranch %98
  1334. %98 = OpLabel
  1335. %119 = OpISub %14 %156 %57
  1336. OpStore %93 %119
  1337. OpBranch %95
  1338. %97 = OpLabel
  1339. OpReturn
  1340. OpFunctionEnd
  1341. %12 = OpFunction %2 None %3
  1342. %13 = OpLabel
  1343. %120 = OpVariable %15 Function
  1344. %124 = OpVariable %15 Function
  1345. %133 = OpVariable %40 Function
  1346. %121 = OpAccessChain %23 %20 %22
  1347. %122 = OpLoad %17 %121
  1348. %123 = OpConvertFToS %14 %122
  1349. OpStore %120 %123
  1350. OpStore %124 %94
  1351. OpBranch %125
  1352. %125 = OpLabel
  1353. %157 = OpPhi %14 %94 %13 %149 %128
  1354. OpLoopMerge %127 %128 None
  1355. OpBranch %129
  1356. %129 = OpLabel
  1357. %132 = OpSGreaterThanEqual %36 %157 %123
  1358. OpBranchConditional %132 %126 %127
  1359. %126 = OpLabel
  1360. %137 = OpIAdd %14 %157 %123
  1361. %138 = OpAccessChain %15 %133 %137
  1362. %139 = OpLoad %14 %138
  1363. %140 = OpAccessChain %15 %133 %157
  1364. OpStore %140 %139
  1365. %143 = OpIAdd %14 %157 %123
  1366. %145 = OpAccessChain %15 %133 %157
  1367. %146 = OpLoad %14 %145
  1368. %147 = OpAccessChain %15 %133 %143
  1369. OpStore %147 %146
  1370. OpBranch %128
  1371. %128 = OpLabel
  1372. %149 = OpISub %14 %157 %57
  1373. OpStore %124 %149
  1374. OpBranch %125
  1375. %127 = OpLabel
  1376. OpReturn
  1377. OpFunctionEnd
  1378. )";
  1379. std::unique_ptr<IRContext> context =
  1380. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  1381. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1382. Module* module = context->module();
  1383. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1384. << text << std::endl;
  1385. {
  1386. // Function a
  1387. const Function* f = spvtest::GetFunction(module, 6);
  1388. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  1389. Loop* loop = &ld.GetLoopByIndex(0);
  1390. std::vector<const Loop*> loops{loop};
  1391. LoopDependenceAnalysis analysis{context.get(), loops};
  1392. const Instruction* stores[2];
  1393. int stores_found = 0;
  1394. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) {
  1395. if (inst.opcode() == spv::Op::OpStore) {
  1396. stores[stores_found] = &inst;
  1397. ++stores_found;
  1398. }
  1399. }
  1400. for (int i = 0; i < 2; ++i) {
  1401. EXPECT_TRUE(stores[i]);
  1402. }
  1403. // 47 -> 48
  1404. {
  1405. // Analyse and simplify the instruction behind the access chain of this
  1406. // load.
  1407. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  1408. context->get_def_use_mgr()
  1409. ->GetDef(context->get_def_use_mgr()
  1410. ->GetDef(47)
  1411. ->GetSingleWordInOperand(0))
  1412. ->GetSingleWordInOperand(1));
  1413. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  1414. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  1415. // Analyse and simplify the instruction behind the access chain of this
  1416. // store.
  1417. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  1418. context->get_def_use_mgr()
  1419. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  1420. ->GetSingleWordInOperand(1));
  1421. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  1422. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  1423. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  1424. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  1425. // Independent and supported.
  1426. EXPECT_TRUE(analysis.IsProvablyOutsideOfLoopBounds(
  1427. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  1428. }
  1429. // 54 -> 55
  1430. {
  1431. // Analyse and simplify the instruction behind the access chain of this
  1432. // load.
  1433. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  1434. context->get_def_use_mgr()
  1435. ->GetDef(context->get_def_use_mgr()
  1436. ->GetDef(54)
  1437. ->GetSingleWordInOperand(0))
  1438. ->GetSingleWordInOperand(1));
  1439. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  1440. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  1441. // Analyse and simplify the instruction behind the access chain of this
  1442. // store.
  1443. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  1444. context->get_def_use_mgr()
  1445. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  1446. ->GetSingleWordInOperand(1));
  1447. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  1448. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  1449. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  1450. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  1451. // Independent but not supported.
  1452. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  1453. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  1454. }
  1455. }
  1456. {
  1457. // Function b
  1458. const Function* f = spvtest::GetFunction(module, 8);
  1459. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  1460. Loop* loop = &ld.GetLoopByIndex(0);
  1461. std::vector<const Loop*> loops{loop};
  1462. LoopDependenceAnalysis analysis{context.get(), loops};
  1463. const Instruction* stores[2];
  1464. int stores_found = 0;
  1465. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 65)) {
  1466. if (inst.opcode() == spv::Op::OpStore) {
  1467. stores[stores_found] = &inst;
  1468. ++stores_found;
  1469. }
  1470. }
  1471. for (int i = 0; i < 2; ++i) {
  1472. EXPECT_TRUE(stores[i]);
  1473. }
  1474. // 78 -> 79
  1475. {
  1476. // Analyse and simplify the instruction behind the access chain of this
  1477. // load.
  1478. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  1479. context->get_def_use_mgr()
  1480. ->GetDef(context->get_def_use_mgr()
  1481. ->GetDef(78)
  1482. ->GetSingleWordInOperand(0))
  1483. ->GetSingleWordInOperand(1));
  1484. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  1485. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  1486. // Analyse and simplify the instruction behind the access chain of this
  1487. // store.
  1488. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  1489. context->get_def_use_mgr()
  1490. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  1491. ->GetSingleWordInOperand(1));
  1492. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  1493. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  1494. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  1495. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  1496. // Dependent.
  1497. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  1498. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  1499. }
  1500. // 85 -> 86
  1501. {
  1502. // Analyse and simplify the instruction behind the access chain of this
  1503. // load.
  1504. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  1505. context->get_def_use_mgr()
  1506. ->GetDef(context->get_def_use_mgr()
  1507. ->GetDef(85)
  1508. ->GetSingleWordInOperand(0))
  1509. ->GetSingleWordInOperand(1));
  1510. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  1511. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  1512. // Analyse and simplify the instruction behind the access chain of this
  1513. // store.
  1514. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  1515. context->get_def_use_mgr()
  1516. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  1517. ->GetSingleWordInOperand(1));
  1518. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  1519. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  1520. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  1521. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  1522. // Dependent.
  1523. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  1524. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  1525. }
  1526. }
  1527. {
  1528. // Function c
  1529. const Function* f = spvtest::GetFunction(module, 10);
  1530. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  1531. Loop* loop = &ld.GetLoopByIndex(0);
  1532. std::vector<const Loop*> loops{loop};
  1533. LoopDependenceAnalysis analysis{context.get(), loops};
  1534. const Instruction* stores[2];
  1535. int stores_found = 0;
  1536. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 96)) {
  1537. if (inst.opcode() == spv::Op::OpStore) {
  1538. stores[stores_found] = &inst;
  1539. ++stores_found;
  1540. }
  1541. }
  1542. for (int i = 0; i < 2; ++i) {
  1543. EXPECT_TRUE(stores[i]);
  1544. }
  1545. // 109 -> 110
  1546. {
  1547. // Analyse and simplify the instruction behind the access chain of this
  1548. // load.
  1549. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  1550. context->get_def_use_mgr()
  1551. ->GetDef(context->get_def_use_mgr()
  1552. ->GetDef(109)
  1553. ->GetSingleWordInOperand(0))
  1554. ->GetSingleWordInOperand(1));
  1555. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  1556. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  1557. // Analyse and simplify the instruction behind the access chain of this
  1558. // store.
  1559. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  1560. context->get_def_use_mgr()
  1561. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  1562. ->GetSingleWordInOperand(1));
  1563. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  1564. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  1565. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  1566. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  1567. // Independent but not supported.
  1568. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  1569. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  1570. }
  1571. // 116 -> 117
  1572. {
  1573. // Analyse and simplify the instruction behind the access chain of this
  1574. // load.
  1575. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  1576. context->get_def_use_mgr()
  1577. ->GetDef(context->get_def_use_mgr()
  1578. ->GetDef(116)
  1579. ->GetSingleWordInOperand(0))
  1580. ->GetSingleWordInOperand(1));
  1581. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  1582. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  1583. // Analyse and simplify the instruction behind the access chain of this
  1584. // store.
  1585. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  1586. context->get_def_use_mgr()
  1587. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  1588. ->GetSingleWordInOperand(1));
  1589. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  1590. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  1591. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  1592. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  1593. // Independent but not supported.
  1594. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  1595. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  1596. }
  1597. }
  1598. {
  1599. // Function d
  1600. const Function* f = spvtest::GetFunction(module, 12);
  1601. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  1602. Loop* loop = &ld.GetLoopByIndex(0);
  1603. std::vector<const Loop*> loops{loop};
  1604. LoopDependenceAnalysis analysis{context.get(), loops};
  1605. const Instruction* stores[2];
  1606. int stores_found = 0;
  1607. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 126)) {
  1608. if (inst.opcode() == spv::Op::OpStore) {
  1609. stores[stores_found] = &inst;
  1610. ++stores_found;
  1611. }
  1612. }
  1613. for (int i = 0; i < 2; ++i) {
  1614. EXPECT_TRUE(stores[i]);
  1615. }
  1616. // 139 -> 140
  1617. {
  1618. // Analyse and simplify the instruction behind the access chain of this
  1619. // load.
  1620. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  1621. context->get_def_use_mgr()
  1622. ->GetDef(context->get_def_use_mgr()
  1623. ->GetDef(139)
  1624. ->GetSingleWordInOperand(0))
  1625. ->GetSingleWordInOperand(1));
  1626. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  1627. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  1628. // Analyse and simplify the instruction behind the access chain of this
  1629. // store.
  1630. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  1631. context->get_def_use_mgr()
  1632. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  1633. ->GetSingleWordInOperand(1));
  1634. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  1635. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  1636. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  1637. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  1638. // Dependent.
  1639. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  1640. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  1641. }
  1642. // 146 -> 147
  1643. {
  1644. // Analyse and simplify the instruction behind the access chain of this
  1645. // load.
  1646. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  1647. context->get_def_use_mgr()
  1648. ->GetDef(context->get_def_use_mgr()
  1649. ->GetDef(146)
  1650. ->GetSingleWordInOperand(0))
  1651. ->GetSingleWordInOperand(1));
  1652. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  1653. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  1654. // Analyse and simplify the instruction behind the access chain of this
  1655. // store.
  1656. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  1657. context->get_def_use_mgr()
  1658. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  1659. ->GetSingleWordInOperand(1));
  1660. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  1661. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  1662. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  1663. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  1664. // Dependent.
  1665. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  1666. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  1667. }
  1668. }
  1669. }
  1670. /*
  1671. Generated from the following GLSL fragment shader
  1672. with --eliminate-local-multi-store
  1673. #version 440 core
  1674. layout(location = 0) in vec4 in_vec;
  1675. // Loop iterates from symbolic to constant
  1676. void a() {
  1677. int N = int(in_vec.x);
  1678. int arr[10];
  1679. for (int i = N; i < 9; i++) { // Bounds are 9 - N - 1
  1680. arr[i] = arr[i+N]; // |distance| = N
  1681. arr[i+N] = arr[i]; // |distance| = N
  1682. }
  1683. }
  1684. void b() {
  1685. int N = int(in_vec.x);
  1686. int arr[10];
  1687. for (int i = N; i <= 9; i++) { // Bounds are 9 - N
  1688. arr[i] = arr[i+N]; // |distance| = N
  1689. arr[i+N] = arr[i]; // |distance| = N
  1690. }
  1691. }
  1692. void c() {
  1693. int N = int(in_vec.x);
  1694. int arr[10];
  1695. for (int i = N; i > 0; i--) { // Bounds are N - 0 - 1
  1696. arr[i] = arr[i+N]; // |distance| = N
  1697. arr[i+N] = arr[i]; // |distance| = N
  1698. }
  1699. }
  1700. void d() {
  1701. int N = int(in_vec.x);
  1702. int arr[10];
  1703. for (int i = N; i >= 0; i--) { // Bounds are N - 0
  1704. arr[i] = arr[i+N]; // |distance| = N
  1705. arr[i+N] = arr[i]; // |distance| = N
  1706. }
  1707. }
  1708. void main(){
  1709. a();
  1710. b();
  1711. c();
  1712. d();
  1713. }
  1714. */
  1715. TEST(DependencyAnalysisHelpers, symbolic_to_const) {
  1716. const std::string text = R"( OpCapability Shader
  1717. %1 = OpExtInstImport "GLSL.std.450"
  1718. OpMemoryModel Logical GLSL450
  1719. OpEntryPoint Fragment %4 "main" %20
  1720. OpExecutionMode %4 OriginUpperLeft
  1721. OpSource GLSL 440
  1722. OpName %4 "main"
  1723. OpName %6 "a("
  1724. OpName %8 "b("
  1725. OpName %10 "c("
  1726. OpName %12 "d("
  1727. OpName %16 "N"
  1728. OpName %20 "in_vec"
  1729. OpName %27 "i"
  1730. OpName %41 "arr"
  1731. OpName %59 "N"
  1732. OpName %63 "i"
  1733. OpName %72 "arr"
  1734. OpName %89 "N"
  1735. OpName %93 "i"
  1736. OpName %103 "arr"
  1737. OpName %120 "N"
  1738. OpName %124 "i"
  1739. OpName %133 "arr"
  1740. OpDecorate %20 Location 0
  1741. %2 = OpTypeVoid
  1742. %3 = OpTypeFunction %2
  1743. %14 = OpTypeInt 32 1
  1744. %15 = OpTypePointer Function %14
  1745. %17 = OpTypeFloat 32
  1746. %18 = OpTypeVector %17 4
  1747. %19 = OpTypePointer Input %18
  1748. %20 = OpVariable %19 Input
  1749. %21 = OpTypeInt 32 0
  1750. %22 = OpConstant %21 0
  1751. %23 = OpTypePointer Input %17
  1752. %35 = OpConstant %14 9
  1753. %36 = OpTypeBool
  1754. %38 = OpConstant %21 10
  1755. %39 = OpTypeArray %14 %38
  1756. %40 = OpTypePointer Function %39
  1757. %57 = OpConstant %14 1
  1758. %101 = OpConstant %14 0
  1759. %4 = OpFunction %2 None %3
  1760. %5 = OpLabel
  1761. %150 = OpFunctionCall %2 %6
  1762. %151 = OpFunctionCall %2 %8
  1763. %152 = OpFunctionCall %2 %10
  1764. %153 = OpFunctionCall %2 %12
  1765. OpReturn
  1766. OpFunctionEnd
  1767. %6 = OpFunction %2 None %3
  1768. %7 = OpLabel
  1769. %16 = OpVariable %15 Function
  1770. %27 = OpVariable %15 Function
  1771. %41 = OpVariable %40 Function
  1772. %24 = OpAccessChain %23 %20 %22
  1773. %25 = OpLoad %17 %24
  1774. %26 = OpConvertFToS %14 %25
  1775. OpStore %16 %26
  1776. OpStore %27 %26
  1777. OpBranch %29
  1778. %29 = OpLabel
  1779. %154 = OpPhi %14 %26 %7 %58 %32
  1780. OpLoopMerge %31 %32 None
  1781. OpBranch %33
  1782. %33 = OpLabel
  1783. %37 = OpSLessThan %36 %154 %35
  1784. OpBranchConditional %37 %30 %31
  1785. %30 = OpLabel
  1786. %45 = OpIAdd %14 %154 %26
  1787. %46 = OpAccessChain %15 %41 %45
  1788. %47 = OpLoad %14 %46
  1789. %48 = OpAccessChain %15 %41 %154
  1790. OpStore %48 %47
  1791. %51 = OpIAdd %14 %154 %26
  1792. %53 = OpAccessChain %15 %41 %154
  1793. %54 = OpLoad %14 %53
  1794. %55 = OpAccessChain %15 %41 %51
  1795. OpStore %55 %54
  1796. OpBranch %32
  1797. %32 = OpLabel
  1798. %58 = OpIAdd %14 %154 %57
  1799. OpStore %27 %58
  1800. OpBranch %29
  1801. %31 = OpLabel
  1802. OpReturn
  1803. OpFunctionEnd
  1804. %8 = OpFunction %2 None %3
  1805. %9 = OpLabel
  1806. %59 = OpVariable %15 Function
  1807. %63 = OpVariable %15 Function
  1808. %72 = OpVariable %40 Function
  1809. %60 = OpAccessChain %23 %20 %22
  1810. %61 = OpLoad %17 %60
  1811. %62 = OpConvertFToS %14 %61
  1812. OpStore %59 %62
  1813. OpStore %63 %62
  1814. OpBranch %65
  1815. %65 = OpLabel
  1816. %155 = OpPhi %14 %62 %9 %88 %68
  1817. OpLoopMerge %67 %68 None
  1818. OpBranch %69
  1819. %69 = OpLabel
  1820. %71 = OpSLessThanEqual %36 %155 %35
  1821. OpBranchConditional %71 %66 %67
  1822. %66 = OpLabel
  1823. %76 = OpIAdd %14 %155 %62
  1824. %77 = OpAccessChain %15 %72 %76
  1825. %78 = OpLoad %14 %77
  1826. %79 = OpAccessChain %15 %72 %155
  1827. OpStore %79 %78
  1828. %82 = OpIAdd %14 %155 %62
  1829. %84 = OpAccessChain %15 %72 %155
  1830. %85 = OpLoad %14 %84
  1831. %86 = OpAccessChain %15 %72 %82
  1832. OpStore %86 %85
  1833. OpBranch %68
  1834. %68 = OpLabel
  1835. %88 = OpIAdd %14 %155 %57
  1836. OpStore %63 %88
  1837. OpBranch %65
  1838. %67 = OpLabel
  1839. OpReturn
  1840. OpFunctionEnd
  1841. %10 = OpFunction %2 None %3
  1842. %11 = OpLabel
  1843. %89 = OpVariable %15 Function
  1844. %93 = OpVariable %15 Function
  1845. %103 = OpVariable %40 Function
  1846. %90 = OpAccessChain %23 %20 %22
  1847. %91 = OpLoad %17 %90
  1848. %92 = OpConvertFToS %14 %91
  1849. OpStore %89 %92
  1850. OpStore %93 %92
  1851. OpBranch %95
  1852. %95 = OpLabel
  1853. %156 = OpPhi %14 %92 %11 %119 %98
  1854. OpLoopMerge %97 %98 None
  1855. OpBranch %99
  1856. %99 = OpLabel
  1857. %102 = OpSGreaterThan %36 %156 %101
  1858. OpBranchConditional %102 %96 %97
  1859. %96 = OpLabel
  1860. %107 = OpIAdd %14 %156 %92
  1861. %108 = OpAccessChain %15 %103 %107
  1862. %109 = OpLoad %14 %108
  1863. %110 = OpAccessChain %15 %103 %156
  1864. OpStore %110 %109
  1865. %113 = OpIAdd %14 %156 %92
  1866. %115 = OpAccessChain %15 %103 %156
  1867. %116 = OpLoad %14 %115
  1868. %117 = OpAccessChain %15 %103 %113
  1869. OpStore %117 %116
  1870. OpBranch %98
  1871. %98 = OpLabel
  1872. %119 = OpISub %14 %156 %57
  1873. OpStore %93 %119
  1874. OpBranch %95
  1875. %97 = OpLabel
  1876. OpReturn
  1877. OpFunctionEnd
  1878. %12 = OpFunction %2 None %3
  1879. %13 = OpLabel
  1880. %120 = OpVariable %15 Function
  1881. %124 = OpVariable %15 Function
  1882. %133 = OpVariable %40 Function
  1883. %121 = OpAccessChain %23 %20 %22
  1884. %122 = OpLoad %17 %121
  1885. %123 = OpConvertFToS %14 %122
  1886. OpStore %120 %123
  1887. OpStore %124 %123
  1888. OpBranch %126
  1889. %126 = OpLabel
  1890. %157 = OpPhi %14 %123 %13 %149 %129
  1891. OpLoopMerge %128 %129 None
  1892. OpBranch %130
  1893. %130 = OpLabel
  1894. %132 = OpSGreaterThanEqual %36 %157 %101
  1895. OpBranchConditional %132 %127 %128
  1896. %127 = OpLabel
  1897. %137 = OpIAdd %14 %157 %123
  1898. %138 = OpAccessChain %15 %133 %137
  1899. %139 = OpLoad %14 %138
  1900. %140 = OpAccessChain %15 %133 %157
  1901. OpStore %140 %139
  1902. %143 = OpIAdd %14 %157 %123
  1903. %145 = OpAccessChain %15 %133 %157
  1904. %146 = OpLoad %14 %145
  1905. %147 = OpAccessChain %15 %133 %143
  1906. OpStore %147 %146
  1907. OpBranch %129
  1908. %129 = OpLabel
  1909. %149 = OpISub %14 %157 %57
  1910. OpStore %124 %149
  1911. OpBranch %126
  1912. %128 = OpLabel
  1913. OpReturn
  1914. OpFunctionEnd
  1915. )";
  1916. std::unique_ptr<IRContext> context =
  1917. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  1918. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1919. Module* module = context->module();
  1920. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1921. << text << std::endl;
  1922. {
  1923. // Function a
  1924. const Function* f = spvtest::GetFunction(module, 6);
  1925. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  1926. Loop* loop = &ld.GetLoopByIndex(0);
  1927. std::vector<const Loop*> loops{loop};
  1928. LoopDependenceAnalysis analysis{context.get(), loops};
  1929. const Instruction* stores[2];
  1930. int stores_found = 0;
  1931. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) {
  1932. if (inst.opcode() == spv::Op::OpStore) {
  1933. stores[stores_found] = &inst;
  1934. ++stores_found;
  1935. }
  1936. }
  1937. for (int i = 0; i < 2; ++i) {
  1938. EXPECT_TRUE(stores[i]);
  1939. }
  1940. // 47 -> 48
  1941. {
  1942. // Analyse and simplify the instruction behind the access chain of this
  1943. // load.
  1944. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  1945. context->get_def_use_mgr()
  1946. ->GetDef(context->get_def_use_mgr()
  1947. ->GetDef(47)
  1948. ->GetSingleWordInOperand(0))
  1949. ->GetSingleWordInOperand(1));
  1950. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  1951. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  1952. // Analyse and simplify the instruction behind the access chain of this
  1953. // store.
  1954. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  1955. context->get_def_use_mgr()
  1956. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  1957. ->GetSingleWordInOperand(1));
  1958. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  1959. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  1960. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  1961. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  1962. // Independent but not supported.
  1963. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  1964. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  1965. }
  1966. // 54 -> 55
  1967. {
  1968. // Analyse and simplify the instruction behind the access chain of this
  1969. // load.
  1970. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  1971. context->get_def_use_mgr()
  1972. ->GetDef(context->get_def_use_mgr()
  1973. ->GetDef(54)
  1974. ->GetSingleWordInOperand(0))
  1975. ->GetSingleWordInOperand(1));
  1976. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  1977. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  1978. // Analyse and simplify the instruction behind the access chain of this
  1979. // store.
  1980. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  1981. context->get_def_use_mgr()
  1982. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  1983. ->GetSingleWordInOperand(1));
  1984. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  1985. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  1986. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  1987. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  1988. // Independent but not supported.
  1989. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  1990. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  1991. }
  1992. }
  1993. {
  1994. // Function b
  1995. const Function* f = spvtest::GetFunction(module, 8);
  1996. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  1997. Loop* loop = &ld.GetLoopByIndex(0);
  1998. std::vector<const Loop*> loops{loop};
  1999. LoopDependenceAnalysis analysis{context.get(), loops};
  2000. const Instruction* stores[2];
  2001. int stores_found = 0;
  2002. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 66)) {
  2003. if (inst.opcode() == spv::Op::OpStore) {
  2004. stores[stores_found] = &inst;
  2005. ++stores_found;
  2006. }
  2007. }
  2008. for (int i = 0; i < 2; ++i) {
  2009. EXPECT_TRUE(stores[i]);
  2010. }
  2011. // 78 -> 79
  2012. {
  2013. // Analyse and simplify the instruction behind the access chain of this
  2014. // load.
  2015. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2016. context->get_def_use_mgr()
  2017. ->GetDef(context->get_def_use_mgr()
  2018. ->GetDef(78)
  2019. ->GetSingleWordInOperand(0))
  2020. ->GetSingleWordInOperand(1));
  2021. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2022. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2023. // Analyse and simplify the instruction behind the access chain of this
  2024. // store.
  2025. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2026. context->get_def_use_mgr()
  2027. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  2028. ->GetSingleWordInOperand(1));
  2029. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2030. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2031. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2032. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2033. // Dependent.
  2034. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2035. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2036. }
  2037. // 85 -> 86
  2038. {
  2039. // Analyse and simplify the instruction behind the access chain of this
  2040. // load.
  2041. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2042. context->get_def_use_mgr()
  2043. ->GetDef(context->get_def_use_mgr()
  2044. ->GetDef(85)
  2045. ->GetSingleWordInOperand(0))
  2046. ->GetSingleWordInOperand(1));
  2047. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2048. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2049. // Analyse and simplify the instruction behind the access chain of this
  2050. // store.
  2051. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2052. context->get_def_use_mgr()
  2053. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  2054. ->GetSingleWordInOperand(1));
  2055. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2056. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2057. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2058. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2059. // Dependent.
  2060. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2061. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2062. }
  2063. }
  2064. {
  2065. // Function c
  2066. const Function* f = spvtest::GetFunction(module, 10);
  2067. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  2068. Loop* loop = &ld.GetLoopByIndex(0);
  2069. std::vector<const Loop*> loops{loop};
  2070. LoopDependenceAnalysis analysis{context.get(), loops};
  2071. const Instruction* stores[2];
  2072. int stores_found = 0;
  2073. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 96)) {
  2074. if (inst.opcode() == spv::Op::OpStore) {
  2075. stores[stores_found] = &inst;
  2076. ++stores_found;
  2077. }
  2078. }
  2079. for (int i = 0; i < 2; ++i) {
  2080. EXPECT_TRUE(stores[i]);
  2081. }
  2082. // 109 -> 110
  2083. {
  2084. // Analyse and simplify the instruction behind the access chain of this
  2085. // load.
  2086. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2087. context->get_def_use_mgr()
  2088. ->GetDef(context->get_def_use_mgr()
  2089. ->GetDef(109)
  2090. ->GetSingleWordInOperand(0))
  2091. ->GetSingleWordInOperand(1));
  2092. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2093. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2094. // Analyse and simplify the instruction behind the access chain of this
  2095. // store.
  2096. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2097. context->get_def_use_mgr()
  2098. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  2099. ->GetSingleWordInOperand(1));
  2100. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2101. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2102. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2103. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2104. // Independent and supported.
  2105. EXPECT_TRUE(analysis.IsProvablyOutsideOfLoopBounds(
  2106. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2107. }
  2108. // 116 -> 117
  2109. {
  2110. // Analyse and simplify the instruction behind the access chain of this
  2111. // load.
  2112. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2113. context->get_def_use_mgr()
  2114. ->GetDef(context->get_def_use_mgr()
  2115. ->GetDef(116)
  2116. ->GetSingleWordInOperand(0))
  2117. ->GetSingleWordInOperand(1));
  2118. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2119. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2120. // Analyse and simplify the instruction behind the access chain of this
  2121. // store.
  2122. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2123. context->get_def_use_mgr()
  2124. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  2125. ->GetSingleWordInOperand(1));
  2126. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2127. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2128. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2129. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2130. // Independent but not supported.
  2131. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2132. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2133. }
  2134. }
  2135. {
  2136. // Function d
  2137. const Function* f = spvtest::GetFunction(module, 12);
  2138. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  2139. Loop* loop = &ld.GetLoopByIndex(0);
  2140. std::vector<const Loop*> loops{loop};
  2141. LoopDependenceAnalysis analysis{context.get(), loops};
  2142. const Instruction* stores[2];
  2143. int stores_found = 0;
  2144. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 127)) {
  2145. if (inst.opcode() == spv::Op::OpStore) {
  2146. stores[stores_found] = &inst;
  2147. ++stores_found;
  2148. }
  2149. }
  2150. for (int i = 0; i < 2; ++i) {
  2151. EXPECT_TRUE(stores[i]);
  2152. }
  2153. // 139 -> 140
  2154. {
  2155. // Analyse and simplify the instruction behind the access chain of this
  2156. // load.
  2157. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2158. context->get_def_use_mgr()
  2159. ->GetDef(context->get_def_use_mgr()
  2160. ->GetDef(139)
  2161. ->GetSingleWordInOperand(0))
  2162. ->GetSingleWordInOperand(1));
  2163. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2164. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2165. // Analyse and simplify the instruction behind the access chain of this
  2166. // store.
  2167. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2168. context->get_def_use_mgr()
  2169. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  2170. ->GetSingleWordInOperand(1));
  2171. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2172. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2173. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2174. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2175. // Dependent
  2176. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2177. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2178. }
  2179. // 146 -> 147
  2180. {
  2181. // Analyse and simplify the instruction behind the access chain of this
  2182. // load.
  2183. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2184. context->get_def_use_mgr()
  2185. ->GetDef(context->get_def_use_mgr()
  2186. ->GetDef(146)
  2187. ->GetSingleWordInOperand(0))
  2188. ->GetSingleWordInOperand(1));
  2189. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2190. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2191. // Analyse and simplify the instruction behind the access chain of this
  2192. // store.
  2193. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2194. context->get_def_use_mgr()
  2195. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  2196. ->GetSingleWordInOperand(1));
  2197. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2198. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2199. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2200. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2201. // Dependent
  2202. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2203. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2204. }
  2205. }
  2206. }
  2207. /*
  2208. Generated from the following GLSL fragment shader
  2209. with --eliminate-local-multi-store
  2210. #version 440 core
  2211. layout(location = 0) in vec4 in_vec;
  2212. // Loop iterates from symbolic to symbolic
  2213. void a() {
  2214. int M = int(in_vec.x);
  2215. int N = int(in_vec.y);
  2216. int arr[10];
  2217. for (int i = M; i < N; i++) { // Bounds are N - M - 1
  2218. arr[i+M+N] = arr[i+M+2*N]; // |distance| = N
  2219. arr[i+M+2*N] = arr[i+M+N]; // |distance| = N
  2220. }
  2221. }
  2222. void b() {
  2223. int M = int(in_vec.x);
  2224. int N = int(in_vec.y);
  2225. int arr[10];
  2226. for (int i = M; i <= N; i++) { // Bounds are N - M
  2227. arr[i+M+N] = arr[i+M+2*N]; // |distance| = N
  2228. arr[i+M+2*N] = arr[i+M+N]; // |distance| = N
  2229. }
  2230. }
  2231. void c() {
  2232. int M = int(in_vec.x);
  2233. int N = int(in_vec.y);
  2234. int arr[10];
  2235. for (int i = M; i > N; i--) { // Bounds are M - N - 1
  2236. arr[i+M+N] = arr[i+M+2*N]; // |distance| = N
  2237. arr[i+M+2*N] = arr[i+M+N]; // |distance| = N
  2238. }
  2239. }
  2240. void d() {
  2241. int M = int(in_vec.x);
  2242. int N = int(in_vec.y);
  2243. int arr[10];
  2244. for (int i = M; i >= N; i--) { // Bounds are M - N
  2245. arr[i+M+N] = arr[i+M+2*N]; // |distance| = N
  2246. arr[i+M+2*N] = arr[i+M+N]; // |distance| = N
  2247. }
  2248. }
  2249. void main(){
  2250. a();
  2251. b();
  2252. c();
  2253. d();
  2254. }
  2255. */
  2256. TEST(DependencyAnalysisHelpers, symbolic_to_symbolic) {
  2257. const std::string text = R"( OpCapability Shader
  2258. %1 = OpExtInstImport "GLSL.std.450"
  2259. OpMemoryModel Logical GLSL450
  2260. OpEntryPoint Fragment %4 "main" %20
  2261. OpExecutionMode %4 OriginUpperLeft
  2262. OpSource GLSL 440
  2263. OpName %4 "main"
  2264. OpName %6 "a("
  2265. OpName %8 "b("
  2266. OpName %10 "c("
  2267. OpName %12 "d("
  2268. OpName %16 "M"
  2269. OpName %20 "in_vec"
  2270. OpName %27 "N"
  2271. OpName %32 "i"
  2272. OpName %46 "arr"
  2273. OpName %79 "M"
  2274. OpName %83 "N"
  2275. OpName %87 "i"
  2276. OpName %97 "arr"
  2277. OpName %128 "M"
  2278. OpName %132 "N"
  2279. OpName %136 "i"
  2280. OpName %146 "arr"
  2281. OpName %177 "M"
  2282. OpName %181 "N"
  2283. OpName %185 "i"
  2284. OpName %195 "arr"
  2285. OpDecorate %20 Location 0
  2286. %2 = OpTypeVoid
  2287. %3 = OpTypeFunction %2
  2288. %14 = OpTypeInt 32 1
  2289. %15 = OpTypePointer Function %14
  2290. %17 = OpTypeFloat 32
  2291. %18 = OpTypeVector %17 4
  2292. %19 = OpTypePointer Input %18
  2293. %20 = OpVariable %19 Input
  2294. %21 = OpTypeInt 32 0
  2295. %22 = OpConstant %21 0
  2296. %23 = OpTypePointer Input %17
  2297. %28 = OpConstant %21 1
  2298. %41 = OpTypeBool
  2299. %43 = OpConstant %21 10
  2300. %44 = OpTypeArray %14 %43
  2301. %45 = OpTypePointer Function %44
  2302. %55 = OpConstant %14 2
  2303. %77 = OpConstant %14 1
  2304. %4 = OpFunction %2 None %3
  2305. %5 = OpLabel
  2306. %226 = OpFunctionCall %2 %6
  2307. %227 = OpFunctionCall %2 %8
  2308. %228 = OpFunctionCall %2 %10
  2309. %229 = OpFunctionCall %2 %12
  2310. OpReturn
  2311. OpFunctionEnd
  2312. %6 = OpFunction %2 None %3
  2313. %7 = OpLabel
  2314. %16 = OpVariable %15 Function
  2315. %27 = OpVariable %15 Function
  2316. %32 = OpVariable %15 Function
  2317. %46 = OpVariable %45 Function
  2318. %24 = OpAccessChain %23 %20 %22
  2319. %25 = OpLoad %17 %24
  2320. %26 = OpConvertFToS %14 %25
  2321. OpStore %16 %26
  2322. %29 = OpAccessChain %23 %20 %28
  2323. %30 = OpLoad %17 %29
  2324. %31 = OpConvertFToS %14 %30
  2325. OpStore %27 %31
  2326. OpStore %32 %26
  2327. OpBranch %34
  2328. %34 = OpLabel
  2329. %230 = OpPhi %14 %26 %7 %78 %37
  2330. OpLoopMerge %36 %37 None
  2331. OpBranch %38
  2332. %38 = OpLabel
  2333. %42 = OpSLessThan %41 %230 %31
  2334. OpBranchConditional %42 %35 %36
  2335. %35 = OpLabel
  2336. %49 = OpIAdd %14 %230 %26
  2337. %51 = OpIAdd %14 %49 %31
  2338. %54 = OpIAdd %14 %230 %26
  2339. %57 = OpIMul %14 %55 %31
  2340. %58 = OpIAdd %14 %54 %57
  2341. %59 = OpAccessChain %15 %46 %58
  2342. %60 = OpLoad %14 %59
  2343. %61 = OpAccessChain %15 %46 %51
  2344. OpStore %61 %60
  2345. %64 = OpIAdd %14 %230 %26
  2346. %66 = OpIMul %14 %55 %31
  2347. %67 = OpIAdd %14 %64 %66
  2348. %70 = OpIAdd %14 %230 %26
  2349. %72 = OpIAdd %14 %70 %31
  2350. %73 = OpAccessChain %15 %46 %72
  2351. %74 = OpLoad %14 %73
  2352. %75 = OpAccessChain %15 %46 %67
  2353. OpStore %75 %74
  2354. OpBranch %37
  2355. %37 = OpLabel
  2356. %78 = OpIAdd %14 %230 %77
  2357. OpStore %32 %78
  2358. OpBranch %34
  2359. %36 = OpLabel
  2360. OpReturn
  2361. OpFunctionEnd
  2362. %8 = OpFunction %2 None %3
  2363. %9 = OpLabel
  2364. %79 = OpVariable %15 Function
  2365. %83 = OpVariable %15 Function
  2366. %87 = OpVariable %15 Function
  2367. %97 = OpVariable %45 Function
  2368. %80 = OpAccessChain %23 %20 %22
  2369. %81 = OpLoad %17 %80
  2370. %82 = OpConvertFToS %14 %81
  2371. OpStore %79 %82
  2372. %84 = OpAccessChain %23 %20 %28
  2373. %85 = OpLoad %17 %84
  2374. %86 = OpConvertFToS %14 %85
  2375. OpStore %83 %86
  2376. OpStore %87 %82
  2377. OpBranch %89
  2378. %89 = OpLabel
  2379. %231 = OpPhi %14 %82 %9 %127 %92
  2380. OpLoopMerge %91 %92 None
  2381. OpBranch %93
  2382. %93 = OpLabel
  2383. %96 = OpSLessThanEqual %41 %231 %86
  2384. OpBranchConditional %96 %90 %91
  2385. %90 = OpLabel
  2386. %100 = OpIAdd %14 %231 %82
  2387. %102 = OpIAdd %14 %100 %86
  2388. %105 = OpIAdd %14 %231 %82
  2389. %107 = OpIMul %14 %55 %86
  2390. %108 = OpIAdd %14 %105 %107
  2391. %109 = OpAccessChain %15 %97 %108
  2392. %110 = OpLoad %14 %109
  2393. %111 = OpAccessChain %15 %97 %102
  2394. OpStore %111 %110
  2395. %114 = OpIAdd %14 %231 %82
  2396. %116 = OpIMul %14 %55 %86
  2397. %117 = OpIAdd %14 %114 %116
  2398. %120 = OpIAdd %14 %231 %82
  2399. %122 = OpIAdd %14 %120 %86
  2400. %123 = OpAccessChain %15 %97 %122
  2401. %124 = OpLoad %14 %123
  2402. %125 = OpAccessChain %15 %97 %117
  2403. OpStore %125 %124
  2404. OpBranch %92
  2405. %92 = OpLabel
  2406. %127 = OpIAdd %14 %231 %77
  2407. OpStore %87 %127
  2408. OpBranch %89
  2409. %91 = OpLabel
  2410. OpReturn
  2411. OpFunctionEnd
  2412. %10 = OpFunction %2 None %3
  2413. %11 = OpLabel
  2414. %128 = OpVariable %15 Function
  2415. %132 = OpVariable %15 Function
  2416. %136 = OpVariable %15 Function
  2417. %146 = OpVariable %45 Function
  2418. %129 = OpAccessChain %23 %20 %22
  2419. %130 = OpLoad %17 %129
  2420. %131 = OpConvertFToS %14 %130
  2421. OpStore %128 %131
  2422. %133 = OpAccessChain %23 %20 %28
  2423. %134 = OpLoad %17 %133
  2424. %135 = OpConvertFToS %14 %134
  2425. OpStore %132 %135
  2426. OpStore %136 %131
  2427. OpBranch %138
  2428. %138 = OpLabel
  2429. %232 = OpPhi %14 %131 %11 %176 %141
  2430. OpLoopMerge %140 %141 None
  2431. OpBranch %142
  2432. %142 = OpLabel
  2433. %145 = OpSGreaterThan %41 %232 %135
  2434. OpBranchConditional %145 %139 %140
  2435. %139 = OpLabel
  2436. %149 = OpIAdd %14 %232 %131
  2437. %151 = OpIAdd %14 %149 %135
  2438. %154 = OpIAdd %14 %232 %131
  2439. %156 = OpIMul %14 %55 %135
  2440. %157 = OpIAdd %14 %154 %156
  2441. %158 = OpAccessChain %15 %146 %157
  2442. %159 = OpLoad %14 %158
  2443. %160 = OpAccessChain %15 %146 %151
  2444. OpStore %160 %159
  2445. %163 = OpIAdd %14 %232 %131
  2446. %165 = OpIMul %14 %55 %135
  2447. %166 = OpIAdd %14 %163 %165
  2448. %169 = OpIAdd %14 %232 %131
  2449. %171 = OpIAdd %14 %169 %135
  2450. %172 = OpAccessChain %15 %146 %171
  2451. %173 = OpLoad %14 %172
  2452. %174 = OpAccessChain %15 %146 %166
  2453. OpStore %174 %173
  2454. OpBranch %141
  2455. %141 = OpLabel
  2456. %176 = OpISub %14 %232 %77
  2457. OpStore %136 %176
  2458. OpBranch %138
  2459. %140 = OpLabel
  2460. OpReturn
  2461. OpFunctionEnd
  2462. %12 = OpFunction %2 None %3
  2463. %13 = OpLabel
  2464. %177 = OpVariable %15 Function
  2465. %181 = OpVariable %15 Function
  2466. %185 = OpVariable %15 Function
  2467. %195 = OpVariable %45 Function
  2468. %178 = OpAccessChain %23 %20 %22
  2469. %179 = OpLoad %17 %178
  2470. %180 = OpConvertFToS %14 %179
  2471. OpStore %177 %180
  2472. %182 = OpAccessChain %23 %20 %28
  2473. %183 = OpLoad %17 %182
  2474. %184 = OpConvertFToS %14 %183
  2475. OpStore %181 %184
  2476. OpStore %185 %180
  2477. OpBranch %187
  2478. %187 = OpLabel
  2479. %233 = OpPhi %14 %180 %13 %225 %190
  2480. OpLoopMerge %189 %190 None
  2481. OpBranch %191
  2482. %191 = OpLabel
  2483. %194 = OpSGreaterThanEqual %41 %233 %184
  2484. OpBranchConditional %194 %188 %189
  2485. %188 = OpLabel
  2486. %198 = OpIAdd %14 %233 %180
  2487. %200 = OpIAdd %14 %198 %184
  2488. %203 = OpIAdd %14 %233 %180
  2489. %205 = OpIMul %14 %55 %184
  2490. %206 = OpIAdd %14 %203 %205
  2491. %207 = OpAccessChain %15 %195 %206
  2492. %208 = OpLoad %14 %207
  2493. %209 = OpAccessChain %15 %195 %200
  2494. OpStore %209 %208
  2495. %212 = OpIAdd %14 %233 %180
  2496. %214 = OpIMul %14 %55 %184
  2497. %215 = OpIAdd %14 %212 %214
  2498. %218 = OpIAdd %14 %233 %180
  2499. %220 = OpIAdd %14 %218 %184
  2500. %221 = OpAccessChain %15 %195 %220
  2501. %222 = OpLoad %14 %221
  2502. %223 = OpAccessChain %15 %195 %215
  2503. OpStore %223 %222
  2504. OpBranch %190
  2505. %190 = OpLabel
  2506. %225 = OpISub %14 %233 %77
  2507. OpStore %185 %225
  2508. OpBranch %187
  2509. %189 = OpLabel
  2510. OpReturn
  2511. OpFunctionEnd
  2512. )";
  2513. std::unique_ptr<IRContext> context =
  2514. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  2515. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  2516. Module* module = context->module();
  2517. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  2518. << text << std::endl;
  2519. {
  2520. // Function a
  2521. const Function* f = spvtest::GetFunction(module, 6);
  2522. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  2523. Loop* loop = &ld.GetLoopByIndex(0);
  2524. std::vector<const Loop*> loops{loop};
  2525. LoopDependenceAnalysis analysis{context.get(), loops};
  2526. const Instruction* stores[2];
  2527. int stores_found = 0;
  2528. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 35)) {
  2529. if (inst.opcode() == spv::Op::OpStore) {
  2530. stores[stores_found] = &inst;
  2531. ++stores_found;
  2532. }
  2533. }
  2534. for (int i = 0; i < 2; ++i) {
  2535. EXPECT_TRUE(stores[i]);
  2536. }
  2537. // 60 -> 61
  2538. {
  2539. // Analyse and simplify the instruction behind the access chain of this
  2540. // load.
  2541. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2542. context->get_def_use_mgr()
  2543. ->GetDef(context->get_def_use_mgr()
  2544. ->GetDef(60)
  2545. ->GetSingleWordInOperand(0))
  2546. ->GetSingleWordInOperand(1));
  2547. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2548. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2549. // Analyse and simplify the instruction behind the access chain of this
  2550. // store.
  2551. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2552. context->get_def_use_mgr()
  2553. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  2554. ->GetSingleWordInOperand(1));
  2555. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2556. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2557. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2558. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2559. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2560. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2561. }
  2562. // 74 -> 75
  2563. {
  2564. // Analyse and simplify the instruction behind the access chain of this
  2565. // load.
  2566. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2567. context->get_def_use_mgr()
  2568. ->GetDef(context->get_def_use_mgr()
  2569. ->GetDef(74)
  2570. ->GetSingleWordInOperand(0))
  2571. ->GetSingleWordInOperand(1));
  2572. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2573. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2574. // Analyse and simplify the instruction behind the access chain of this
  2575. // store.
  2576. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2577. context->get_def_use_mgr()
  2578. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  2579. ->GetSingleWordInOperand(1));
  2580. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2581. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2582. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2583. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2584. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2585. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2586. }
  2587. }
  2588. {
  2589. // Function b
  2590. const Function* f = spvtest::GetFunction(module, 8);
  2591. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  2592. Loop* loop = &ld.GetLoopByIndex(0);
  2593. std::vector<const Loop*> loops{loop};
  2594. LoopDependenceAnalysis analysis{context.get(), loops};
  2595. const Instruction* stores[2];
  2596. int stores_found = 0;
  2597. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 90)) {
  2598. if (inst.opcode() == spv::Op::OpStore) {
  2599. stores[stores_found] = &inst;
  2600. ++stores_found;
  2601. }
  2602. }
  2603. for (int i = 0; i < 2; ++i) {
  2604. EXPECT_TRUE(stores[i]);
  2605. }
  2606. // 110 -> 111
  2607. {
  2608. // Analyse and simplify the instruction behind the access chain of this
  2609. // load.
  2610. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2611. context->get_def_use_mgr()
  2612. ->GetDef(context->get_def_use_mgr()
  2613. ->GetDef(110)
  2614. ->GetSingleWordInOperand(0))
  2615. ->GetSingleWordInOperand(1));
  2616. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2617. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2618. // Analyse and simplify the instruction behind the access chain of this
  2619. // store.
  2620. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2621. context->get_def_use_mgr()
  2622. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  2623. ->GetSingleWordInOperand(1));
  2624. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2625. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2626. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2627. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2628. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2629. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2630. }
  2631. // 124 -> 125
  2632. {
  2633. // Analyse and simplify the instruction behind the access chain of this
  2634. // load.
  2635. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2636. context->get_def_use_mgr()
  2637. ->GetDef(context->get_def_use_mgr()
  2638. ->GetDef(124)
  2639. ->GetSingleWordInOperand(0))
  2640. ->GetSingleWordInOperand(1));
  2641. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2642. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2643. // Analyse and simplify the instruction behind the access chain of this
  2644. // store.
  2645. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2646. context->get_def_use_mgr()
  2647. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  2648. ->GetSingleWordInOperand(1));
  2649. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2650. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2651. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2652. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2653. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2654. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2655. }
  2656. }
  2657. {
  2658. // Function c
  2659. const Function* f = spvtest::GetFunction(module, 10);
  2660. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  2661. Loop* loop = &ld.GetLoopByIndex(0);
  2662. std::vector<const Loop*> loops{loop};
  2663. LoopDependenceAnalysis analysis{context.get(), loops};
  2664. const Instruction* stores[2];
  2665. int stores_found = 0;
  2666. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 139)) {
  2667. if (inst.opcode() == spv::Op::OpStore) {
  2668. stores[stores_found] = &inst;
  2669. ++stores_found;
  2670. }
  2671. }
  2672. for (int i = 0; i < 2; ++i) {
  2673. EXPECT_TRUE(stores[i]);
  2674. }
  2675. // 159 -> 160
  2676. {
  2677. // Analyse and simplify the instruction behind the access chain of this
  2678. // load.
  2679. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2680. context->get_def_use_mgr()
  2681. ->GetDef(context->get_def_use_mgr()
  2682. ->GetDef(159)
  2683. ->GetSingleWordInOperand(0))
  2684. ->GetSingleWordInOperand(1));
  2685. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2686. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2687. // Analyse and simplify the instruction behind the access chain of this
  2688. // store.
  2689. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2690. context->get_def_use_mgr()
  2691. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  2692. ->GetSingleWordInOperand(1));
  2693. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2694. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2695. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2696. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2697. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2698. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2699. }
  2700. // 173 -> 174
  2701. {
  2702. // Analyse and simplify the instruction behind the access chain of this
  2703. // load.
  2704. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2705. context->get_def_use_mgr()
  2706. ->GetDef(context->get_def_use_mgr()
  2707. ->GetDef(173)
  2708. ->GetSingleWordInOperand(0))
  2709. ->GetSingleWordInOperand(1));
  2710. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2711. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2712. // Analyse and simplify the instruction behind the access chain of this
  2713. // store.
  2714. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2715. context->get_def_use_mgr()
  2716. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  2717. ->GetSingleWordInOperand(1));
  2718. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2719. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2720. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2721. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2722. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2723. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2724. }
  2725. }
  2726. {
  2727. // Function d
  2728. const Function* f = spvtest::GetFunction(module, 12);
  2729. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  2730. Loop* loop = &ld.GetLoopByIndex(0);
  2731. std::vector<const Loop*> loops{loop};
  2732. LoopDependenceAnalysis analysis{context.get(), loops};
  2733. const Instruction* stores[2];
  2734. int stores_found = 0;
  2735. for (const Instruction& inst : *spvtest::GetBasicBlock(f, 188)) {
  2736. if (inst.opcode() == spv::Op::OpStore) {
  2737. stores[stores_found] = &inst;
  2738. ++stores_found;
  2739. }
  2740. }
  2741. for (int i = 0; i < 2; ++i) {
  2742. EXPECT_TRUE(stores[i]);
  2743. }
  2744. // 208 -> 209
  2745. {
  2746. // Analyse and simplify the instruction behind the access chain of this
  2747. // load.
  2748. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2749. context->get_def_use_mgr()
  2750. ->GetDef(context->get_def_use_mgr()
  2751. ->GetDef(208)
  2752. ->GetSingleWordInOperand(0))
  2753. ->GetSingleWordInOperand(1));
  2754. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2755. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2756. // Analyse and simplify the instruction behind the access chain of this
  2757. // store.
  2758. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2759. context->get_def_use_mgr()
  2760. ->GetDef(stores[0]->GetSingleWordInOperand(0))
  2761. ->GetSingleWordInOperand(1));
  2762. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2763. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2764. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2765. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2766. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2767. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2768. }
  2769. // 222 -> 223
  2770. {
  2771. // Analyse and simplify the instruction behind the access chain of this
  2772. // load.
  2773. Instruction* load_var = context->get_def_use_mgr()->GetDef(
  2774. context->get_def_use_mgr()
  2775. ->GetDef(context->get_def_use_mgr()
  2776. ->GetDef(222)
  2777. ->GetSingleWordInOperand(0))
  2778. ->GetSingleWordInOperand(1));
  2779. SENode* load = analysis.GetScalarEvolution()->SimplifyExpression(
  2780. analysis.GetScalarEvolution()->AnalyzeInstruction(load_var));
  2781. // Analyse and simplify the instruction behind the access chain of this
  2782. // store.
  2783. Instruction* store_var = context->get_def_use_mgr()->GetDef(
  2784. context->get_def_use_mgr()
  2785. ->GetDef(stores[1]->GetSingleWordInOperand(0))
  2786. ->GetSingleWordInOperand(1));
  2787. SENode* store = analysis.GetScalarEvolution()->SimplifyExpression(
  2788. analysis.GetScalarEvolution()->AnalyzeInstruction(store_var));
  2789. SENode* delta = analysis.GetScalarEvolution()->SimplifyExpression(
  2790. analysis.GetScalarEvolution()->CreateSubtraction(load, store));
  2791. EXPECT_FALSE(analysis.IsProvablyOutsideOfLoopBounds(
  2792. loop, delta, store->AsSERecurrentNode()->GetCoefficient()));
  2793. }
  2794. }
  2795. }
  2796. } // namespace
  2797. } // namespace opt
  2798. } // namespace spvtools