Home | History | Annotate | Download | only in opt
      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 
     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 */
     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 */
    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 
   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