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