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