register_liveness.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283
  1. // Copyright (c) 2018 Google LLC.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <memory>
  15. #include <string>
  16. #include <unordered_set>
  17. #include <vector>
  18. #include "gmock/gmock.h"
  19. #include "source/opt/register_pressure.h"
  20. #include "test/opt/assembly_builder.h"
  21. #include "test/opt/function_utils.h"
  22. #include "test/opt/pass_fixture.h"
  23. #include "test/opt/pass_utils.h"
  24. namespace spvtools {
  25. namespace opt {
  26. namespace {
  27. using ::testing::UnorderedElementsAre;
  28. using PassClassTest = PassTest<::testing::Test>;
  29. void CompareSets(const std::unordered_set<Instruction*>& computed,
  30. const std::unordered_set<uint32_t>& expected) {
  31. for (Instruction* insn : computed) {
  32. EXPECT_TRUE(expected.count(insn->result_id()))
  33. << "Unexpected instruction in live set: " << *insn;
  34. }
  35. EXPECT_EQ(computed.size(), expected.size());
  36. }
  37. /*
  38. Generated from the following GLSL
  39. #version 330
  40. in vec4 BaseColor;
  41. flat in int Count;
  42. void main()
  43. {
  44. vec4 color = BaseColor;
  45. vec4 acc;
  46. if (Count == 0) {
  47. acc = color;
  48. }
  49. else {
  50. acc = color + vec4(0,1,2,0);
  51. }
  52. gl_FragColor = acc + color;
  53. }
  54. */
  55. TEST_F(PassClassTest, LivenessWithIf) {
  56. const std::string text = R"(
  57. OpCapability Shader
  58. %1 = OpExtInstImport "GLSL.std.450"
  59. OpMemoryModel Logical GLSL450
  60. OpEntryPoint Fragment %4 "main" %11 %15 %32
  61. OpExecutionMode %4 OriginLowerLeft
  62. OpSource GLSL 330
  63. OpName %4 "main"
  64. OpName %11 "BaseColor"
  65. OpName %15 "Count"
  66. OpName %32 "gl_FragColor"
  67. OpDecorate %11 Location 0
  68. OpDecorate %15 Flat
  69. OpDecorate %15 Location 0
  70. OpDecorate %32 Location 0
  71. %2 = OpTypeVoid
  72. %3 = OpTypeFunction %2
  73. %6 = OpTypeFloat 32
  74. %7 = OpTypeVector %6 4
  75. %10 = OpTypePointer Input %7
  76. %11 = OpVariable %10 Input
  77. %13 = OpTypeInt 32 1
  78. %14 = OpTypePointer Input %13
  79. %15 = OpVariable %14 Input
  80. %17 = OpConstant %13 0
  81. %18 = OpTypeBool
  82. %26 = OpConstant %6 0
  83. %27 = OpConstant %6 1
  84. %28 = OpConstant %6 2
  85. %29 = OpConstantComposite %7 %26 %27 %28 %26
  86. %31 = OpTypePointer Output %7
  87. %32 = OpVariable %31 Output
  88. %4 = OpFunction %2 None %3
  89. %5 = OpLabel
  90. %12 = OpLoad %7 %11
  91. %16 = OpLoad %13 %15
  92. %19 = OpIEqual %18 %16 %17
  93. OpSelectionMerge %21 None
  94. OpBranchConditional %19 %20 %24
  95. %20 = OpLabel
  96. OpBranch %21
  97. %24 = OpLabel
  98. %30 = OpFAdd %7 %12 %29
  99. OpBranch %21
  100. %21 = OpLabel
  101. %36 = OpPhi %7 %12 %20 %30 %24
  102. %35 = OpFAdd %7 %36 %12
  103. OpStore %32 %35
  104. OpReturn
  105. OpFunctionEnd
  106. )";
  107. std::unique_ptr<IRContext> context =
  108. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  109. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  110. Module* module = context->module();
  111. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  112. << text << std::endl;
  113. Function* f = &*module->begin();
  114. LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis();
  115. const RegisterLiveness* register_liveness = liveness_analysis->Get(f);
  116. {
  117. SCOPED_TRACE("Block 5");
  118. auto live_sets = register_liveness->Get(5);
  119. std::unordered_set<uint32_t> live_in{
  120. 11, // %11 = OpVariable %10 Input
  121. 15, // %15 = OpVariable %14 Input
  122. 32, // %32 = OpVariable %31 Output
  123. };
  124. CompareSets(live_sets->live_in_, live_in);
  125. std::unordered_set<uint32_t> live_out{
  126. 12, // %12 = OpLoad %7 %11
  127. 32, // %32 = OpVariable %31 Output
  128. };
  129. CompareSets(live_sets->live_out_, live_out);
  130. }
  131. {
  132. SCOPED_TRACE("Block 20");
  133. auto live_sets = register_liveness->Get(20);
  134. std::unordered_set<uint32_t> live_inout{
  135. 12, // %12 = OpLoad %7 %11
  136. 32, // %32 = OpVariable %31 Output
  137. };
  138. CompareSets(live_sets->live_in_, live_inout);
  139. CompareSets(live_sets->live_out_, live_inout);
  140. }
  141. {
  142. SCOPED_TRACE("Block 24");
  143. auto live_sets = register_liveness->Get(24);
  144. std::unordered_set<uint32_t> live_in{
  145. 12, // %12 = OpLoad %7 %11
  146. 32, // %32 = OpVariable %31 Output
  147. };
  148. CompareSets(live_sets->live_in_, live_in);
  149. std::unordered_set<uint32_t> live_out{
  150. 12, // %12 = OpLoad %7 %11
  151. 30, // %30 = OpFAdd %7 %12 %29
  152. 32, // %32 = OpVariable %31 Output
  153. };
  154. CompareSets(live_sets->live_out_, live_out);
  155. }
  156. {
  157. SCOPED_TRACE("Block 21");
  158. auto live_sets = register_liveness->Get(21);
  159. std::unordered_set<uint32_t> live_in{
  160. 12, // %12 = OpLoad %7 %11
  161. 32, // %32 = OpVariable %31 Output
  162. 36, // %36 = OpPhi %7 %12 %20 %30 %24
  163. };
  164. CompareSets(live_sets->live_in_, live_in);
  165. std::unordered_set<uint32_t> live_out{};
  166. CompareSets(live_sets->live_out_, live_out);
  167. }
  168. }
  169. /*
  170. Generated from the following GLSL
  171. #version 330
  172. in vec4 bigColor;
  173. in vec4 BaseColor;
  174. in float f;
  175. flat in int Count;
  176. flat in uvec4 v4;
  177. void main()
  178. {
  179. vec4 color = BaseColor;
  180. for (int i = 0; i < Count; ++i)
  181. color += bigColor;
  182. float sum = 0.0;
  183. for (int i = 0; i < 4; ++i) {
  184. float acc = 0.0;
  185. if (sum == 0.0) {
  186. acc = v4[i];
  187. }
  188. else {
  189. acc = BaseColor[i];
  190. }
  191. sum += acc + v4[i];
  192. }
  193. vec4 tv4;
  194. for (int i = 0; i < 4; ++i)
  195. tv4[i] = v4[i] * 4u;
  196. color += vec4(sum) + tv4;
  197. vec4 r;
  198. r.xyz = BaseColor.xyz;
  199. for (int i = 0; i < Count; ++i)
  200. r.w = f;
  201. color.xyz += r.xyz;
  202. for (int i = 0; i < 16; i += 4)
  203. for (int j = 0; j < 4; j++)
  204. color *= f;
  205. gl_FragColor = color + tv4;
  206. }
  207. */
  208. TEST_F(PassClassTest, RegisterLiveness) {
  209. const std::string text = R"(
  210. OpCapability Shader
  211. %1 = OpExtInstImport "GLSL.std.450"
  212. OpMemoryModel Logical GLSL450
  213. OpEntryPoint Fragment %4 "main" %11 %24 %28 %55 %124 %176
  214. OpExecutionMode %4 OriginLowerLeft
  215. OpSource GLSL 330
  216. OpName %4 "main"
  217. OpName %11 "BaseColor"
  218. OpName %24 "Count"
  219. OpName %28 "bigColor"
  220. OpName %55 "v4"
  221. OpName %84 "tv4"
  222. OpName %124 "f"
  223. OpName %176 "gl_FragColor"
  224. OpDecorate %11 Location 0
  225. OpDecorate %24 Flat
  226. OpDecorate %24 Location 0
  227. OpDecorate %28 Location 0
  228. OpDecorate %55 Flat
  229. OpDecorate %55 Location 0
  230. OpDecorate %124 Location 0
  231. OpDecorate %176 Location 0
  232. %2 = OpTypeVoid
  233. %3 = OpTypeFunction %2
  234. %6 = OpTypeFloat 32
  235. %7 = OpTypeVector %6 4
  236. %8 = OpTypePointer Function %7
  237. %10 = OpTypePointer Input %7
  238. %11 = OpVariable %10 Input
  239. %13 = OpTypeInt 32 1
  240. %16 = OpConstant %13 0
  241. %23 = OpTypePointer Input %13
  242. %24 = OpVariable %23 Input
  243. %26 = OpTypeBool
  244. %28 = OpVariable %10 Input
  245. %33 = OpConstant %13 1
  246. %35 = OpTypePointer Function %6
  247. %37 = OpConstant %6 0
  248. %45 = OpConstant %13 4
  249. %52 = OpTypeInt 32 0
  250. %53 = OpTypeVector %52 4
  251. %54 = OpTypePointer Input %53
  252. %55 = OpVariable %54 Input
  253. %57 = OpTypePointer Input %52
  254. %63 = OpTypePointer Input %6
  255. %89 = OpConstant %52 4
  256. %102 = OpTypeVector %6 3
  257. %124 = OpVariable %63 Input
  258. %158 = OpConstant %13 16
  259. %175 = OpTypePointer Output %7
  260. %176 = OpVariable %175 Output
  261. %195 = OpUndef %7
  262. %4 = OpFunction %2 None %3
  263. %5 = OpLabel
  264. %84 = OpVariable %8 Function
  265. %12 = OpLoad %7 %11
  266. OpBranch %17
  267. %17 = OpLabel
  268. %191 = OpPhi %7 %12 %5 %31 %18
  269. %184 = OpPhi %13 %16 %5 %34 %18
  270. %25 = OpLoad %13 %24
  271. %27 = OpSLessThan %26 %184 %25
  272. OpLoopMerge %19 %18 None
  273. OpBranchConditional %27 %18 %19
  274. %18 = OpLabel
  275. %29 = OpLoad %7 %28
  276. %31 = OpFAdd %7 %191 %29
  277. %34 = OpIAdd %13 %184 %33
  278. OpBranch %17
  279. %19 = OpLabel
  280. OpBranch %39
  281. %39 = OpLabel
  282. %188 = OpPhi %6 %37 %19 %73 %51
  283. %185 = OpPhi %13 %16 %19 %75 %51
  284. %46 = OpSLessThan %26 %185 %45
  285. OpLoopMerge %41 %51 None
  286. OpBranchConditional %46 %40 %41
  287. %40 = OpLabel
  288. %49 = OpFOrdEqual %26 %188 %37
  289. OpSelectionMerge %51 None
  290. OpBranchConditional %49 %50 %61
  291. %50 = OpLabel
  292. %58 = OpAccessChain %57 %55 %185
  293. %59 = OpLoad %52 %58
  294. %60 = OpConvertUToF %6 %59
  295. OpBranch %51
  296. %61 = OpLabel
  297. %64 = OpAccessChain %63 %11 %185
  298. %65 = OpLoad %6 %64
  299. OpBranch %51
  300. %51 = OpLabel
  301. %210 = OpPhi %6 %60 %50 %65 %61
  302. %68 = OpAccessChain %57 %55 %185
  303. %69 = OpLoad %52 %68
  304. %70 = OpConvertUToF %6 %69
  305. %71 = OpFAdd %6 %210 %70
  306. %73 = OpFAdd %6 %188 %71
  307. %75 = OpIAdd %13 %185 %33
  308. OpBranch %39
  309. %41 = OpLabel
  310. OpBranch %77
  311. %77 = OpLabel
  312. %186 = OpPhi %13 %16 %41 %94 %78
  313. %83 = OpSLessThan %26 %186 %45
  314. OpLoopMerge %79 %78 None
  315. OpBranchConditional %83 %78 %79
  316. %78 = OpLabel
  317. %87 = OpAccessChain %57 %55 %186
  318. %88 = OpLoad %52 %87
  319. %90 = OpIMul %52 %88 %89
  320. %91 = OpConvertUToF %6 %90
  321. %92 = OpAccessChain %35 %84 %186
  322. OpStore %92 %91
  323. %94 = OpIAdd %13 %186 %33
  324. OpBranch %77
  325. %79 = OpLabel
  326. %96 = OpCompositeConstruct %7 %188 %188 %188 %188
  327. %97 = OpLoad %7 %84
  328. %98 = OpFAdd %7 %96 %97
  329. %100 = OpFAdd %7 %191 %98
  330. %104 = OpVectorShuffle %102 %12 %12 0 1 2
  331. %106 = OpVectorShuffle %7 %195 %104 4 5 6 3
  332. OpBranch %108
  333. %108 = OpLabel
  334. %197 = OpPhi %7 %106 %79 %208 %133
  335. %196 = OpPhi %13 %16 %79 %143 %133
  336. %115 = OpSLessThan %26 %196 %25
  337. OpLoopMerge %110 %133 None
  338. OpBranchConditional %115 %109 %110
  339. %109 = OpLabel
  340. OpBranch %117
  341. %117 = OpLabel
  342. %209 = OpPhi %7 %197 %109 %181 %118
  343. %204 = OpPhi %13 %16 %109 %129 %118
  344. %123 = OpSLessThan %26 %204 %45
  345. OpLoopMerge %119 %118 None
  346. OpBranchConditional %123 %118 %119
  347. %118 = OpLabel
  348. %125 = OpLoad %6 %124
  349. %181 = OpCompositeInsert %7 %125 %209 3
  350. %129 = OpIAdd %13 %204 %33
  351. OpBranch %117
  352. %119 = OpLabel
  353. OpBranch %131
  354. %131 = OpLabel
  355. %208 = OpPhi %7 %209 %119 %183 %132
  356. %205 = OpPhi %13 %16 %119 %141 %132
  357. %137 = OpSLessThan %26 %205 %45
  358. OpLoopMerge %133 %132 None
  359. OpBranchConditional %137 %132 %133
  360. %132 = OpLabel
  361. %138 = OpLoad %6 %124
  362. %183 = OpCompositeInsert %7 %138 %208 3
  363. %141 = OpIAdd %13 %205 %33
  364. OpBranch %131
  365. %133 = OpLabel
  366. %143 = OpIAdd %13 %196 %33
  367. OpBranch %108
  368. %110 = OpLabel
  369. %145 = OpVectorShuffle %102 %197 %197 0 1 2
  370. %147 = OpVectorShuffle %102 %100 %100 0 1 2
  371. %148 = OpFAdd %102 %147 %145
  372. %150 = OpVectorShuffle %7 %100 %148 4 5 6 3
  373. OpBranch %152
  374. %152 = OpLabel
  375. %200 = OpPhi %7 %150 %110 %203 %163
  376. %199 = OpPhi %13 %16 %110 %174 %163
  377. %159 = OpSLessThan %26 %199 %158
  378. OpLoopMerge %154 %163 None
  379. OpBranchConditional %159 %153 %154
  380. %153 = OpLabel
  381. OpBranch %161
  382. %161 = OpLabel
  383. %203 = OpPhi %7 %200 %153 %170 %162
  384. %201 = OpPhi %13 %16 %153 %172 %162
  385. %167 = OpSLessThan %26 %201 %45
  386. OpLoopMerge %163 %162 None
  387. OpBranchConditional %167 %162 %163
  388. %162 = OpLabel
  389. %168 = OpLoad %6 %124
  390. %170 = OpVectorTimesScalar %7 %203 %168
  391. %172 = OpIAdd %13 %201 %33
  392. OpBranch %161
  393. %163 = OpLabel
  394. %174 = OpIAdd %13 %199 %45
  395. OpBranch %152
  396. %154 = OpLabel
  397. %178 = OpLoad %7 %84
  398. %179 = OpFAdd %7 %200 %178
  399. OpStore %176 %179
  400. OpReturn
  401. OpFunctionEnd
  402. )";
  403. std::unique_ptr<IRContext> context =
  404. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  405. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  406. Module* module = context->module();
  407. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  408. << text << std::endl;
  409. Function* f = &*module->begin();
  410. LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis();
  411. const RegisterLiveness* register_liveness = liveness_analysis->Get(f);
  412. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  413. {
  414. SCOPED_TRACE("Block 5");
  415. auto live_sets = register_liveness->Get(5);
  416. std::unordered_set<uint32_t> live_in{
  417. 11, // %11 = OpVariable %10 Input
  418. 24, // %24 = OpVariable %23 Input
  419. 28, // %28 = OpVariable %10 Input
  420. 55, // %55 = OpVariable %54 Input
  421. 124, // %124 = OpVariable %63 Input
  422. 176, // %176 = OpVariable %175 Output
  423. };
  424. CompareSets(live_sets->live_in_, live_in);
  425. std::unordered_set<uint32_t> live_out{
  426. 11, // %11 = OpVariable %10 Input
  427. 12, // %12 = OpLoad %7 %11
  428. 24, // %24 = OpVariable %23 Input
  429. 28, // %28 = OpVariable %10 Input
  430. 55, // %55 = OpVariable %54 Input
  431. 84, // %84 = OpVariable %8 Function
  432. 124, // %124 = OpVariable %63 Input
  433. 176, // %176 = OpVariable %175 Output
  434. };
  435. CompareSets(live_sets->live_out_, live_out);
  436. EXPECT_EQ(live_sets->used_registers_, 8u);
  437. }
  438. {
  439. SCOPED_TRACE("Block 17");
  440. auto live_sets = register_liveness->Get(17);
  441. std::unordered_set<uint32_t> live_in{
  442. 11, // %11 = OpVariable %10 Input
  443. 12, // %12 = OpLoad %7 %11
  444. 24, // %24 = OpVariable %23 Input
  445. 28, // %28 = OpVariable %10 Input
  446. 55, // %55 = OpVariable %54 Input
  447. 84, // %84 = OpVariable %8 Function
  448. 124, // %124 = OpVariable %63 Input
  449. 176, // %176 = OpVariable %175 Output
  450. 184, // %184 = OpPhi %13 %16 %5 %34 %18
  451. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  452. };
  453. CompareSets(live_sets->live_in_, live_in);
  454. std::unordered_set<uint32_t> live_out{
  455. 11, // %11 = OpVariable %10 Input
  456. 12, // %12 = OpLoad %7 %11
  457. 25, // %25 = OpLoad %13 %24
  458. 28, // %28 = OpVariable %10 Input
  459. 55, // %55 = OpVariable %54 Input
  460. 84, // %84 = OpVariable %8 Function
  461. 124, // %124 = OpVariable %63 Input
  462. 176, // %176 = OpVariable %175 Output
  463. 184, // %184 = OpPhi %13 %16 %5 %34 %18
  464. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  465. };
  466. CompareSets(live_sets->live_out_, live_out);
  467. EXPECT_EQ(live_sets->used_registers_, 11u);
  468. }
  469. {
  470. SCOPED_TRACE("Block 18");
  471. auto live_sets = register_liveness->Get(18);
  472. std::unordered_set<uint32_t> live_in{
  473. 11, // %11 = OpVariable %10 Input
  474. 12, // %12 = OpLoad %7 %11
  475. 24, // %24 = OpVariable %23 Input
  476. 28, // %28 = OpVariable %10 Input
  477. 55, // %55 = OpVariable %54 Input
  478. 84, // %84 = OpVariable %8 Function
  479. 124, // %124 = OpVariable %63 Input
  480. 176, // %176 = OpVariable %175 Output
  481. 184, // %184 = OpPhi %13 %16 %5 %34 %18
  482. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  483. };
  484. CompareSets(live_sets->live_in_, live_in);
  485. std::unordered_set<uint32_t> live_out{
  486. 11, // %11 = OpVariable %10 Input
  487. 12, // %12 = OpLoad %7 %11
  488. 24, // %24 = OpVariable %23 Input
  489. 28, // %28 = OpVariable %10 Input
  490. 31, // %31 = OpFAdd %7 %191 %29
  491. 34, // %34 = OpIAdd %13 %184 %33
  492. 55, // %55 = OpVariable %54 Input
  493. 84, // %84 = OpVariable %8 Function
  494. 124, // %124 = OpVariable %63 Input
  495. 176, // %176 = OpVariable %175 Output
  496. };
  497. CompareSets(live_sets->live_out_, live_out);
  498. EXPECT_EQ(live_sets->used_registers_, 12u);
  499. }
  500. {
  501. SCOPED_TRACE("Block 19");
  502. auto live_sets = register_liveness->Get(19);
  503. std::unordered_set<uint32_t> live_inout{
  504. 11, // %11 = OpVariable %10 Input
  505. 12, // %12 = OpLoad %7 %11
  506. 25, // %25 = OpLoad %13 %24
  507. 55, // %55 = OpVariable %54 Input
  508. 84, // %84 = OpVariable %8 Function
  509. 124, // %124 = OpVariable %63 Input
  510. 176, // %176 = OpVariable %175 Output
  511. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  512. };
  513. CompareSets(live_sets->live_in_, live_inout);
  514. CompareSets(live_sets->live_out_, live_inout);
  515. EXPECT_EQ(live_sets->used_registers_, 8u);
  516. }
  517. {
  518. SCOPED_TRACE("Block 39");
  519. auto live_sets = register_liveness->Get(39);
  520. std::unordered_set<uint32_t> live_inout{
  521. 11, // %11 = OpVariable %10 Input
  522. 12, // %12 = OpLoad %7 %11
  523. 25, // %25 = OpLoad %13 %24
  524. 55, // %55 = OpVariable %54 Input
  525. 84, // %84 = OpVariable %8 Function
  526. 124, // %124 = OpVariable %63 Input
  527. 176, // %176 = OpVariable %175 Output
  528. 185, // %185 = OpPhi %13 %16 %19 %75 %51
  529. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  530. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  531. };
  532. CompareSets(live_sets->live_in_, live_inout);
  533. CompareSets(live_sets->live_out_, live_inout);
  534. EXPECT_EQ(live_sets->used_registers_, 11u);
  535. }
  536. {
  537. SCOPED_TRACE("Block 40");
  538. auto live_sets = register_liveness->Get(40);
  539. std::unordered_set<uint32_t> live_inout{
  540. 11, // %11 = OpVariable %10 Input
  541. 12, // %12 = OpLoad %7 %11
  542. 25, // %25 = OpLoad %13 %24
  543. 55, // %55 = OpVariable %54 Input
  544. 84, // %84 = OpVariable %8 Function
  545. 124, // %124 = OpVariable %63 Input
  546. 176, // %176 = OpVariable %175 Output
  547. 185, // %185 = OpPhi %13 %16 %19 %75 %51
  548. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  549. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  550. };
  551. CompareSets(live_sets->live_in_, live_inout);
  552. CompareSets(live_sets->live_out_, live_inout);
  553. EXPECT_EQ(live_sets->used_registers_, 11u);
  554. }
  555. {
  556. SCOPED_TRACE("Block 50");
  557. auto live_sets = register_liveness->Get(50);
  558. std::unordered_set<uint32_t> live_in{
  559. 11, // %11 = OpVariable %10 Input
  560. 12, // %12 = OpLoad %7 %11
  561. 25, // %25 = OpLoad %13 %24
  562. 55, // %55 = OpVariable %54 Input
  563. 84, // %84 = OpVariable %8 Function
  564. 124, // %124 = OpVariable %63 Input
  565. 176, // %176 = OpVariable %175 Output
  566. 185, // %185 = OpPhi %13 %16 %19 %75 %51
  567. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  568. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  569. };
  570. CompareSets(live_sets->live_in_, live_in);
  571. std::unordered_set<uint32_t> live_out{
  572. 11, // %11 = OpVariable %10 Input
  573. 12, // %12 = OpLoad %7 %11
  574. 25, // %25 = OpLoad %13 %24
  575. 55, // %55 = OpVariable %54 Input
  576. 60, // %60 = OpConvertUToF %6 %59
  577. 84, // %84 = OpVariable %8 Function
  578. 124, // %124 = OpVariable %63 Input
  579. 176, // %176 = OpVariable %175 Output
  580. 185, // %185 = OpPhi %13 %16 %19 %75 %51
  581. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  582. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  583. };
  584. CompareSets(live_sets->live_out_, live_out);
  585. EXPECT_EQ(live_sets->used_registers_, 12u);
  586. }
  587. {
  588. SCOPED_TRACE("Block 61");
  589. auto live_sets = register_liveness->Get(61);
  590. std::unordered_set<uint32_t> live_in{
  591. 11, // %11 = OpVariable %10 Input
  592. 12, // %12 = OpLoad %7 %11
  593. 25, // %25 = OpLoad %13 %24
  594. 55, // %55 = OpVariable %54 Input
  595. 84, // %84 = OpVariable %8 Function
  596. 124, // %124 = OpVariable %63 Input
  597. 176, // %176 = OpVariable %175 Output
  598. 185, // %185 = OpPhi %13 %16 %19 %75 %51
  599. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  600. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  601. };
  602. CompareSets(live_sets->live_in_, live_in);
  603. std::unordered_set<uint32_t> live_out{
  604. 11, // %11 = OpVariable %10 Input
  605. 12, // %12 = OpLoad %7 %11
  606. 25, // %25 = OpLoad %13 %24
  607. 55, // %55 = OpVariable %54 Input
  608. 65, // %65 = OpLoad %6 %64
  609. 84, // %84 = OpVariable %8 Function
  610. 124, // %124 = OpVariable %63 Input
  611. 176, // %176 = OpVariable %175 Output
  612. 185, // %185 = OpPhi %13 %16 %19 %75 %51
  613. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  614. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  615. };
  616. CompareSets(live_sets->live_out_, live_out);
  617. EXPECT_EQ(live_sets->used_registers_, 12u);
  618. }
  619. {
  620. SCOPED_TRACE("Block 51");
  621. auto live_sets = register_liveness->Get(51);
  622. std::unordered_set<uint32_t> live_in{
  623. 11, // %11 = OpVariable %10 Input
  624. 12, // %12 = OpLoad %7 %11
  625. 25, // %25 = OpLoad %13 %24
  626. 55, // %55 = OpVariable %54 Input
  627. 84, // %84 = OpVariable %8 Function
  628. 124, // %124 = OpVariable %63 Input
  629. 176, // %176 = OpVariable %175 Output
  630. 185, // %185 = OpPhi %13 %16 %19 %75 %51
  631. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  632. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  633. 210, // %210 = OpPhi %6 %60 %50 %65 %61
  634. };
  635. CompareSets(live_sets->live_in_, live_in);
  636. std::unordered_set<uint32_t> live_out{
  637. 11, // %11 = OpVariable %10 Input
  638. 12, // %12 = OpLoad %7 %11
  639. 25, // %25 = OpLoad %13 %24
  640. 55, // %55 = OpVariable %54 Input
  641. 73, // %73 = OpFAdd %6 %188 %71
  642. 75, // %75 = OpIAdd %13 %185 %33
  643. 84, // %84 = OpVariable %8 Function
  644. 124, // %124 = OpVariable %63 Input
  645. 176, // %176 = OpVariable %175 Output
  646. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  647. };
  648. CompareSets(live_sets->live_out_, live_out);
  649. EXPECT_EQ(live_sets->used_registers_, 13u);
  650. }
  651. {
  652. SCOPED_TRACE("Block 41");
  653. auto live_sets = register_liveness->Get(41);
  654. std::unordered_set<uint32_t> live_inout{
  655. 12, // %12 = OpLoad %7 %11
  656. 25, // %25 = OpLoad %13 %24
  657. 55, // %55 = OpVariable %54 Input
  658. 84, // %84 = OpVariable %8 Function
  659. 124, // %124 = OpVariable %63 Input
  660. 176, // %176 = OpVariable %175 Output
  661. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  662. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  663. };
  664. CompareSets(live_sets->live_in_, live_inout);
  665. CompareSets(live_sets->live_out_, live_inout);
  666. EXPECT_EQ(live_sets->used_registers_, 8u);
  667. }
  668. {
  669. SCOPED_TRACE("Block 77");
  670. auto live_sets = register_liveness->Get(77);
  671. std::unordered_set<uint32_t> live_inout{
  672. 12, // %12 = OpLoad %7 %11
  673. 25, // %25 = OpLoad %13 %24
  674. 55, // %55 = OpVariable %54 Input
  675. 84, // %84 = OpVariable %8 Function
  676. 124, // %124 = OpVariable %63 Input
  677. 176, // %176 = OpVariable %175 Output
  678. 186, // %186 = OpPhi %13 %16 %41 %94 %78
  679. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  680. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  681. };
  682. CompareSets(live_sets->live_in_, live_inout);
  683. CompareSets(live_sets->live_out_, live_inout);
  684. EXPECT_EQ(live_sets->used_registers_, 10u);
  685. }
  686. {
  687. SCOPED_TRACE("Block 78");
  688. auto live_sets = register_liveness->Get(78);
  689. std::unordered_set<uint32_t> live_in{
  690. 12, // %12 = OpLoad %7 %11
  691. 25, // %25 = OpLoad %13 %24
  692. 55, // %55 = OpVariable %54 Input
  693. 84, // %84 = OpVariable %8 Function
  694. 124, // %124 = OpVariable %63 Input
  695. 176, // %176 = OpVariable %175 Output
  696. 186, // %186 = OpPhi %13 %16 %41 %94 %78
  697. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  698. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  699. };
  700. CompareSets(live_sets->live_in_, live_in);
  701. std::unordered_set<uint32_t> live_out{
  702. 12, // %12 = OpLoad %7 %11
  703. 25, // %25 = OpLoad %13 %24
  704. 55, // %55 = OpVariable %54 Input
  705. 84, // %84 = OpVariable %8 Function
  706. 94, // %94 = OpIAdd %13 %186 %33
  707. 124, // %124 = OpVariable %63 Input
  708. 176, // %176 = OpVariable %175 Output
  709. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  710. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  711. };
  712. CompareSets(live_sets->live_out_, live_out);
  713. EXPECT_EQ(live_sets->used_registers_, 11u);
  714. }
  715. {
  716. SCOPED_TRACE("Block 79");
  717. auto live_sets = register_liveness->Get(79);
  718. std::unordered_set<uint32_t> live_in{
  719. 12, // %12 = OpLoad %7 %11
  720. 25, // %25 = OpLoad %13 %24
  721. 84, // %84 = OpVariable %8 Function
  722. 124, // %124 = OpVariable %63 Input
  723. 176, // %176 = OpVariable %175 Output
  724. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  725. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  726. };
  727. CompareSets(live_sets->live_in_, live_in);
  728. std::unordered_set<uint32_t> live_out{
  729. 25, // %25 = OpLoad %13 %24
  730. 84, // %84 = OpVariable %8 Function
  731. 100, // %100 = OpFAdd %7 %191 %98
  732. 106, // %106 = OpVectorShuffle %7 %195 %104 4 5 6 3
  733. 124, // %124 = OpVariable %63 Input
  734. 176, // %176 = OpVariable %175 Output
  735. };
  736. CompareSets(live_sets->live_out_, live_out);
  737. EXPECT_EQ(live_sets->used_registers_, 9u);
  738. }
  739. {
  740. SCOPED_TRACE("Block 108");
  741. auto live_sets = register_liveness->Get(108);
  742. std::unordered_set<uint32_t> live_in{
  743. 25, // %25 = OpLoad %13 %24
  744. 84, // %84 = OpVariable %8 Function
  745. 100, // %100 = OpFAdd %7 %191 %98
  746. 124, // %124 = OpVariable %63 Input
  747. 176, // %176 = OpVariable %175 Output
  748. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  749. 197, // %197 = OpPhi %7 %106 %79 %208 %133
  750. };
  751. CompareSets(live_sets->live_in_, live_in);
  752. std::unordered_set<uint32_t> live_out{
  753. 84, // %84 = OpVariable %8 Function
  754. 100, // %100 = OpFAdd %7 %191 %98
  755. 124, // %124 = OpVariable %63 Input
  756. 176, // %176 = OpVariable %175 Output
  757. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  758. 197, // %197 = OpPhi %7 %106 %79 %208 %133
  759. };
  760. CompareSets(live_sets->live_out_, live_out);
  761. EXPECT_EQ(live_sets->used_registers_, 8u);
  762. }
  763. {
  764. SCOPED_TRACE("Block 109");
  765. auto live_sets = register_liveness->Get(109);
  766. std::unordered_set<uint32_t> live_inout{
  767. 25, // %25 = OpLoad %13 %24
  768. 84, // %84 = OpVariable %8 Function
  769. 100, // %100 = OpFAdd %7 %191 %98
  770. 124, // %124 = OpVariable %63 Input
  771. 176, // %176 = OpVariable %175 Output
  772. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  773. 197, // %197 = OpPhi %7 %106 %79 %208 %133
  774. };
  775. CompareSets(live_sets->live_in_, live_inout);
  776. CompareSets(live_sets->live_out_, live_inout);
  777. EXPECT_EQ(live_sets->used_registers_, 7u);
  778. }
  779. {
  780. SCOPED_TRACE("Block 117");
  781. auto live_sets = register_liveness->Get(117);
  782. std::unordered_set<uint32_t> live_inout{
  783. 25, // %25 = OpLoad %13 %24
  784. 84, // %84 = OpVariable %8 Function
  785. 100, // %100 = OpFAdd %7 %191 %98
  786. 124, // %124 = OpVariable %63 Input
  787. 176, // %176 = OpVariable %175 Output
  788. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  789. 204, // %204 = OpPhi %13 %16 %109 %129 %118
  790. 209, // %209 = OpPhi %7 %197 %109 %181 %118
  791. };
  792. CompareSets(live_sets->live_in_, live_inout);
  793. CompareSets(live_sets->live_out_, live_inout);
  794. EXPECT_EQ(live_sets->used_registers_, 9u);
  795. }
  796. {
  797. SCOPED_TRACE("Block 118");
  798. auto live_sets = register_liveness->Get(118);
  799. std::unordered_set<uint32_t> live_in{
  800. 25, // %25 = OpLoad %13 %24
  801. 84, // %84 = OpVariable %8 Function
  802. 100, // %100 = OpFAdd %7 %191 %98
  803. 124, // %124 = OpVariable %63 Input
  804. 176, // %176 = OpVariable %175 Output
  805. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  806. 204, // %204 = OpPhi %13 %16 %109 %129 %118
  807. 209, // %209 = OpPhi %7 %197 %109 %181 %118
  808. };
  809. CompareSets(live_sets->live_in_, live_in);
  810. std::unordered_set<uint32_t> live_out{
  811. 25, // %25 = OpLoad %13 %24
  812. 84, // %84 = OpVariable %8 Function
  813. 100, // %100 = OpFAdd %7 %191 %98
  814. 124, // %124 = OpVariable %63 Input
  815. 129, // %129 = OpIAdd %13 %204 %33
  816. 176, // %176 = OpVariable %175 Output
  817. 181, // %181 = OpCompositeInsert %7 %125 %209 3
  818. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  819. };
  820. CompareSets(live_sets->live_out_, live_out);
  821. EXPECT_EQ(live_sets->used_registers_, 10u);
  822. }
  823. {
  824. SCOPED_TRACE("Block 119");
  825. auto live_sets = register_liveness->Get(119);
  826. std::unordered_set<uint32_t> live_inout{
  827. 25, // %25 = OpLoad %13 %24
  828. 84, // %84 = OpVariable %8 Function
  829. 100, // %100 = OpFAdd %7 %191 %98
  830. 124, // %124 = OpVariable %63 Input
  831. 176, // %176 = OpVariable %175 Output
  832. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  833. 209, // %209 = OpPhi %7 %197 %109 %181 %118
  834. };
  835. CompareSets(live_sets->live_in_, live_inout);
  836. CompareSets(live_sets->live_out_, live_inout);
  837. EXPECT_EQ(live_sets->used_registers_, 7u);
  838. }
  839. {
  840. SCOPED_TRACE("Block 131");
  841. auto live_sets = register_liveness->Get(131);
  842. std::unordered_set<uint32_t> live_inout{
  843. 25, // %25 = OpLoad %13 %24
  844. 84, // %84 = OpVariable %8 Function
  845. 100, // %100 = OpFAdd %7 %191 %98
  846. 124, // %124 = OpVariable %63 Input
  847. 176, // %176 = OpVariable %175 Output
  848. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  849. 205, // %205 = OpPhi %13 %16 %119 %141 %132
  850. 208, // %208 = OpPhi %7 %209 %119 %183 %132
  851. };
  852. CompareSets(live_sets->live_in_, live_inout);
  853. CompareSets(live_sets->live_out_, live_inout);
  854. EXPECT_EQ(live_sets->used_registers_, 9u);
  855. }
  856. {
  857. SCOPED_TRACE("Block 132");
  858. auto live_sets = register_liveness->Get(132);
  859. std::unordered_set<uint32_t> live_in{
  860. 25, // %25 = OpLoad %13 %24
  861. 84, // %84 = OpVariable %8 Function
  862. 100, // %100 = OpFAdd %7 %191 %98
  863. 124, // %124 = OpVariable %63 Input
  864. 176, // %176 = OpVariable %175 Output
  865. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  866. 205, // %205 = OpPhi %13 %16 %119 %141 %132
  867. 208, // %208 = OpPhi %7 %209 %119 %183 %132
  868. };
  869. CompareSets(live_sets->live_in_, live_in);
  870. std::unordered_set<uint32_t> live_out{
  871. 25, // %25 = OpLoad %13 %24
  872. 84, // %84 = OpVariable %8 Function
  873. 100, // %100 = OpFAdd %7 %191 %98
  874. 124, // %124 = OpVariable %63 Input
  875. 141, // %141 = OpIAdd %13 %205 %33
  876. 176, // %176 = OpVariable %175 Output
  877. 183, // %183 = OpCompositeInsert %7 %138 %208 3
  878. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  879. };
  880. CompareSets(live_sets->live_out_, live_out);
  881. EXPECT_EQ(live_sets->used_registers_, 10u);
  882. }
  883. {
  884. SCOPED_TRACE("Block 133");
  885. auto live_sets = register_liveness->Get(133);
  886. std::unordered_set<uint32_t> live_in{
  887. 25, // %25 = OpLoad %13 %24
  888. 84, // %84 = OpVariable %8 Function
  889. 100, // %100 = OpFAdd %7 %191 %98
  890. 124, // %124 = OpVariable %63 Input
  891. 176, // %176 = OpVariable %175 Output
  892. 196, // %196 = OpPhi %13 %16 %79 %143 %133
  893. 208, // %208 = OpPhi %7 %209 %119 %183 %132
  894. };
  895. CompareSets(live_sets->live_in_, live_in);
  896. std::unordered_set<uint32_t> live_out{
  897. 25, // %25 = OpLoad %13 %24
  898. 84, // %84 = OpVariable %8 Function
  899. 100, // %100 = OpFAdd %7 %191 %98
  900. 124, // %124 = OpVariable %63 Input
  901. 143, // %143 = OpIAdd %13 %196 %33
  902. 176, // %176 = OpVariable %175 Output
  903. 208, // %208 = OpPhi %7 %209 %119 %183 %132
  904. };
  905. CompareSets(live_sets->live_out_, live_out);
  906. EXPECT_EQ(live_sets->used_registers_, 8u);
  907. }
  908. {
  909. SCOPED_TRACE("Block 110");
  910. auto live_sets = register_liveness->Get(110);
  911. std::unordered_set<uint32_t> live_in{
  912. 84, // %84 = OpVariable %8 Function
  913. 100, // %100 = OpFAdd %7 %191 %98
  914. 124, // %124 = OpVariable %63 Input
  915. 176, // %176 = OpVariable %175 Output
  916. 197, // %197 = OpPhi %7 %106 %79 %208 %133
  917. };
  918. CompareSets(live_sets->live_in_, live_in);
  919. std::unordered_set<uint32_t> live_out{
  920. 84, // %84 = OpVariable %8 Function
  921. 124, // %124 = OpVariable %63 Input
  922. 150, // %150 = OpVectorShuffle %7 %100 %148 4 5 6 3
  923. 176, // %176 = OpVariable %175 Output
  924. };
  925. CompareSets(live_sets->live_out_, live_out);
  926. EXPECT_EQ(live_sets->used_registers_, 7u);
  927. }
  928. {
  929. SCOPED_TRACE("Block 152");
  930. auto live_sets = register_liveness->Get(152);
  931. std::unordered_set<uint32_t> live_inout{
  932. 84, // %84 = OpVariable %8 Function
  933. 124, // %124 = OpVariable %63 Input
  934. 176, // %176 = OpVariable %175 Output
  935. 199, // %199 = OpPhi %13 %16 %110 %174 %163
  936. 200, // %200 = OpPhi %7 %150 %110 %203 %163
  937. };
  938. CompareSets(live_sets->live_in_, live_inout);
  939. CompareSets(live_sets->live_out_, live_inout);
  940. EXPECT_EQ(live_sets->used_registers_, 6u);
  941. }
  942. {
  943. SCOPED_TRACE("Block 153");
  944. auto live_sets = register_liveness->Get(153);
  945. std::unordered_set<uint32_t> live_inout{
  946. 84, // %84 = OpVariable %8 Function
  947. 124, // %124 = OpVariable %63 Input
  948. 176, // %176 = OpVariable %175 Output
  949. 199, // %199 = OpPhi %13 %16 %110 %174 %163
  950. 200, // %200 = OpPhi %7 %150 %110 %203 %163
  951. };
  952. CompareSets(live_sets->live_in_, live_inout);
  953. CompareSets(live_sets->live_out_, live_inout);
  954. EXPECT_EQ(live_sets->used_registers_, 5u);
  955. }
  956. {
  957. SCOPED_TRACE("Block 161");
  958. auto live_sets = register_liveness->Get(161);
  959. std::unordered_set<uint32_t> live_inout{
  960. 84, // %84 = OpVariable %8 Function
  961. 124, // %124 = OpVariable %63 Input
  962. 176, // %176 = OpVariable %175 Output
  963. 199, // %199 = OpPhi %13 %16 %110 %174 %163
  964. 201, // %201 = OpPhi %13 %16 %153 %172 %162
  965. 203, // %203 = OpPhi %7 %200 %153 %170 %162
  966. };
  967. CompareSets(live_sets->live_in_, live_inout);
  968. CompareSets(live_sets->live_out_, live_inout);
  969. EXPECT_EQ(live_sets->used_registers_, 7u);
  970. }
  971. {
  972. SCOPED_TRACE("Block 162");
  973. auto live_sets = register_liveness->Get(162);
  974. std::unordered_set<uint32_t> live_in{
  975. 84, // %84 = OpVariable %8 Function
  976. 124, // %124 = OpVariable %63 Input
  977. 176, // %176 = OpVariable %175 Output
  978. 199, // %199 = OpPhi %13 %16 %110 %174 %163
  979. 201, // %201 = OpPhi %13 %16 %153 %172 %162
  980. 203, // %203 = OpPhi %7 %200 %153 %170 %162
  981. };
  982. CompareSets(live_sets->live_in_, live_in);
  983. std::unordered_set<uint32_t> live_out{
  984. 84, // %84 = OpVariable %8 Function
  985. 124, // %124 = OpVariable %63 Input
  986. 170, // %170 = OpVectorTimesScalar %7 %203 %168
  987. 172, // %172 = OpIAdd %13 %201 %33
  988. 176, // %176 = OpVariable %175 Output
  989. 199, // %199 = OpPhi %13 %16 %110 %174 %163
  990. };
  991. CompareSets(live_sets->live_out_, live_out);
  992. EXPECT_EQ(live_sets->used_registers_, 8u);
  993. }
  994. {
  995. SCOPED_TRACE("Block 163");
  996. auto live_sets = register_liveness->Get(163);
  997. std::unordered_set<uint32_t> live_in{
  998. 84, // %84 = OpVariable %8 Function
  999. 124, // %124 = OpVariable %63 Input
  1000. 176, // %176 = OpVariable %175 Output
  1001. 199, // %199 = OpPhi %13 %16 %110 %174 %163
  1002. 203, // %203 = OpPhi %7 %200 %153 %170 %162
  1003. };
  1004. CompareSets(live_sets->live_in_, live_in);
  1005. std::unordered_set<uint32_t> live_out{
  1006. 84, // %84 = OpVariable %8 Function
  1007. 124, // %124 = OpVariable %63 Input
  1008. 174, // %174 = OpIAdd %13 %199 %45
  1009. 176, // %176 = OpVariable %175 Output
  1010. 203, // %203 = OpPhi %7 %200 %153 %170 %162
  1011. };
  1012. CompareSets(live_sets->live_out_, live_out);
  1013. EXPECT_EQ(live_sets->used_registers_, 6u);
  1014. }
  1015. {
  1016. SCOPED_TRACE("Block 154");
  1017. auto live_sets = register_liveness->Get(154);
  1018. std::unordered_set<uint32_t> live_in{
  1019. 84, // %84 = OpVariable %8 Function
  1020. 176, // %176 = OpVariable %175 Output
  1021. 200, // %200 = OpPhi %7 %150 %110 %203 %163
  1022. };
  1023. CompareSets(live_sets->live_in_, live_in);
  1024. std::unordered_set<uint32_t> live_out{};
  1025. CompareSets(live_sets->live_out_, live_out);
  1026. EXPECT_EQ(live_sets->used_registers_, 4u);
  1027. }
  1028. {
  1029. SCOPED_TRACE("Compute loop pressure");
  1030. RegisterLiveness::RegionRegisterLiveness loop_reg_pressure;
  1031. register_liveness->ComputeLoopRegisterPressure(*ld[39], &loop_reg_pressure);
  1032. // Generate(*context->cfg()->block(39), &loop_reg_pressure);
  1033. std::unordered_set<uint32_t> live_in{
  1034. 11, // %11 = OpVariable %10 Input
  1035. 12, // %12 = OpLoad %7 %11
  1036. 25, // %25 = OpLoad %13 %24
  1037. 55, // %55 = OpVariable %54 Input
  1038. 84, // %84 = OpVariable %8 Function
  1039. 124, // %124 = OpVariable %63 Input
  1040. 176, // %176 = OpVariable %175 Output
  1041. 185, // %185 = OpPhi %13 %16 %19 %75 %51
  1042. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  1043. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  1044. };
  1045. CompareSets(loop_reg_pressure.live_in_, live_in);
  1046. std::unordered_set<uint32_t> live_out{
  1047. 12, // %12 = OpLoad %7 %11
  1048. 25, // %25 = OpLoad %13 %24
  1049. 55, // %55 = OpVariable %54 Input
  1050. 84, // %84 = OpVariable %8 Function
  1051. 124, // %124 = OpVariable %63 Input
  1052. 176, // %176 = OpVariable %175 Output
  1053. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  1054. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  1055. };
  1056. CompareSets(loop_reg_pressure.live_out_, live_out);
  1057. EXPECT_EQ(loop_reg_pressure.used_registers_, 13u);
  1058. }
  1059. {
  1060. SCOPED_TRACE("Loop Fusion simulation");
  1061. RegisterLiveness::RegionRegisterLiveness simulation_resut;
  1062. register_liveness->SimulateFusion(*ld[17], *ld[39], &simulation_resut);
  1063. std::unordered_set<uint32_t> live_in{
  1064. 11, // %11 = OpVariable %10 Input
  1065. 12, // %12 = OpLoad %7 %11
  1066. 24, // %24 = OpVariable %23 Input
  1067. 25, // %25 = OpLoad %13 %24
  1068. 28, // %28 = OpVariable %10 Input
  1069. 55, // %55 = OpVariable %54 Input
  1070. 84, // %84 = OpVariable %8 Function
  1071. 124, // %124 = OpVariable %63 Input
  1072. 176, // %176 = OpVariable %175 Output
  1073. 184, // %184 = OpPhi %13 %16 %5 %34 %18
  1074. 185, // %185 = OpPhi %13 %16 %19 %75 %51
  1075. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  1076. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  1077. };
  1078. CompareSets(simulation_resut.live_in_, live_in);
  1079. std::unordered_set<uint32_t> live_out{
  1080. 12, // %12 = OpLoad %7 %11
  1081. 25, // %25 = OpLoad %13 %24
  1082. 55, // %55 = OpVariable %54 Input
  1083. 84, // %84 = OpVariable %8 Function
  1084. 124, // %124 = OpVariable %63 Input
  1085. 176, // %176 = OpVariable %175 Output
  1086. 188, // %188 = OpPhi %6 %37 %19 %73 %51
  1087. 191, // %191 = OpPhi %7 %12 %5 %31 %18
  1088. };
  1089. CompareSets(simulation_resut.live_out_, live_out);
  1090. EXPECT_EQ(simulation_resut.used_registers_, 17u);
  1091. }
  1092. }
  1093. TEST_F(PassClassTest, FissionSimulation) {
  1094. const std::string source = R"(
  1095. OpCapability Shader
  1096. %1 = OpExtInstImport "GLSL.std.450"
  1097. OpMemoryModel Logical GLSL450
  1098. OpEntryPoint Fragment %2 "main"
  1099. OpExecutionMode %2 OriginUpperLeft
  1100. OpSource GLSL 430
  1101. OpName %2 "main"
  1102. OpName %3 "i"
  1103. OpName %4 "A"
  1104. OpName %5 "B"
  1105. %6 = OpTypeVoid
  1106. %7 = OpTypeFunction %6
  1107. %8 = OpTypeInt 32 1
  1108. %9 = OpTypePointer Function %8
  1109. %10 = OpConstant %8 0
  1110. %11 = OpConstant %8 10
  1111. %12 = OpTypeBool
  1112. %13 = OpTypeFloat 32
  1113. %14 = OpTypeInt 32 0
  1114. %15 = OpConstant %14 10
  1115. %16 = OpTypeArray %13 %15
  1116. %17 = OpTypePointer Function %16
  1117. %18 = OpTypePointer Function %13
  1118. %19 = OpConstant %8 1
  1119. %2 = OpFunction %6 None %7
  1120. %20 = OpLabel
  1121. %3 = OpVariable %9 Function
  1122. %4 = OpVariable %17 Function
  1123. %5 = OpVariable %17 Function
  1124. OpBranch %21
  1125. %21 = OpLabel
  1126. %22 = OpPhi %8 %10 %20 %23 %24
  1127. OpLoopMerge %25 %24 None
  1128. OpBranch %26
  1129. %26 = OpLabel
  1130. %27 = OpSLessThan %12 %22 %11
  1131. OpBranchConditional %27 %28 %25
  1132. %28 = OpLabel
  1133. %29 = OpAccessChain %18 %5 %22
  1134. %30 = OpLoad %13 %29
  1135. %31 = OpAccessChain %18 %4 %22
  1136. OpStore %31 %30
  1137. %32 = OpAccessChain %18 %4 %22
  1138. %33 = OpLoad %13 %32
  1139. %34 = OpAccessChain %18 %5 %22
  1140. OpStore %34 %33
  1141. OpBranch %24
  1142. %24 = OpLabel
  1143. %23 = OpIAdd %8 %22 %19
  1144. OpBranch %21
  1145. %25 = OpLabel
  1146. OpStore %3 %22
  1147. OpReturn
  1148. OpFunctionEnd
  1149. )";
  1150. std::unique_ptr<IRContext> context =
  1151. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source,
  1152. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1153. Module* module = context->module();
  1154. EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
  1155. << source << std::endl;
  1156. Function* f = &*module->begin();
  1157. LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis();
  1158. const RegisterLiveness* register_liveness = liveness_analysis->Get(f);
  1159. LoopDescriptor& ld = *context->GetLoopDescriptor(f);
  1160. analysis::DefUseManager& def_use_mgr = *context->get_def_use_mgr();
  1161. {
  1162. RegisterLiveness::RegionRegisterLiveness l1_sim_resut;
  1163. RegisterLiveness::RegionRegisterLiveness l2_sim_resut;
  1164. std::unordered_set<Instruction*> moved_instructions{
  1165. def_use_mgr.GetDef(29), def_use_mgr.GetDef(30), def_use_mgr.GetDef(31),
  1166. def_use_mgr.GetDef(31)->NextNode()};
  1167. std::unordered_set<Instruction*> copied_instructions{
  1168. def_use_mgr.GetDef(22), def_use_mgr.GetDef(27),
  1169. def_use_mgr.GetDef(27)->NextNode(), def_use_mgr.GetDef(23)};
  1170. register_liveness->SimulateFission(*ld[21], moved_instructions,
  1171. copied_instructions, &l1_sim_resut,
  1172. &l2_sim_resut);
  1173. {
  1174. SCOPED_TRACE("L1 simulation");
  1175. std::unordered_set<uint32_t> live_in{
  1176. 3, // %3 = OpVariable %9 Function
  1177. 4, // %4 = OpVariable %17 Function
  1178. 5, // %5 = OpVariable %17 Function
  1179. 22, // %22 = OpPhi %8 %10 %20 %23 %24
  1180. };
  1181. CompareSets(l1_sim_resut.live_in_, live_in);
  1182. std::unordered_set<uint32_t> live_out{
  1183. 3, // %3 = OpVariable %9 Function
  1184. 4, // %4 = OpVariable %17 Function
  1185. 5, // %5 = OpVariable %17 Function
  1186. 22, // %22 = OpPhi %8 %10 %20 %23 %24
  1187. };
  1188. CompareSets(l1_sim_resut.live_out_, live_out);
  1189. EXPECT_EQ(l1_sim_resut.used_registers_, 6u);
  1190. }
  1191. {
  1192. SCOPED_TRACE("L2 simulation");
  1193. std::unordered_set<uint32_t> live_in{
  1194. 3, // %3 = OpVariable %9 Function
  1195. 4, // %4 = OpVariable %17 Function
  1196. 5, // %5 = OpVariable %17 Function
  1197. 22, // %22 = OpPhi %8 %10 %20 %23 %24
  1198. };
  1199. CompareSets(l2_sim_resut.live_in_, live_in);
  1200. std::unordered_set<uint32_t> live_out{
  1201. 3, // %3 = OpVariable %9 Function
  1202. 22, // %22 = OpPhi %8 %10 %20 %23 %24
  1203. };
  1204. CompareSets(l2_sim_resut.live_out_, live_out);
  1205. EXPECT_EQ(l2_sim_resut.used_registers_, 6u);
  1206. }
  1207. }
  1208. }
  1209. } // namespace
  1210. } // namespace opt
  1211. } // namespace spvtools