| // Copyright (c) 2018 Google LLC. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include <memory> | |
| #include <unordered_set> | |
| #include <vector> | |
| #include "gmock/gmock.h" | |
| #include "source/opt/register_pressure.h" | |
| #include "test/opt/assembly_builder.h" | |
| #include "test/opt/function_utils.h" | |
| #include "test/opt/pass_fixture.h" | |
| #include "test/opt/pass_utils.h" | |
| namespace spvtools { | |
| namespace opt { | |
| namespace { | |
| using ::testing::UnorderedElementsAre; | |
| using PassClassTest = PassTest<::testing::Test>; | |
| void CompareSets(const std::unordered_set<Instruction*>& computed, | |
| const std::unordered_set<uint32_t>& expected) { | |
| for (Instruction* insn : computed) { | |
| EXPECT_TRUE(expected.count(insn->result_id())) | |
| << "Unexpected instruction in live set: " << *insn; | |
| } | |
| EXPECT_EQ(computed.size(), expected.size()); | |
| } | |
| /* | |
| Generated from the following GLSL | |
| #version 330 | |
| in vec4 BaseColor; | |
| flat in int Count; | |
| void main() | |
| { | |
| vec4 color = BaseColor; | |
| vec4 acc; | |
| if (Count == 0) { | |
| acc = color; | |
| } | |
| else { | |
| acc = color + vec4(0,1,2,0); | |
| } | |
| gl_FragColor = acc + color; | |
| } | |
| */ | |
| TEST_F(PassClassTest, LivenessWithIf) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %4 "main" %11 %15 %32 | |
| OpExecutionMode %4 OriginLowerLeft | |
| OpSource GLSL 330 | |
| OpName %4 "main" | |
| OpName %11 "BaseColor" | |
| OpName %15 "Count" | |
| OpName %32 "gl_FragColor" | |
| OpDecorate %11 Location 0 | |
| OpDecorate %15 Flat | |
| OpDecorate %15 Location 0 | |
| OpDecorate %32 Location 0 | |
| %2 = OpTypeVoid | |
| %3 = OpTypeFunction %2 | |
| %6 = OpTypeFloat 32 | |
| %7 = OpTypeVector %6 4 | |
| %10 = OpTypePointer Input %7 | |
| %11 = OpVariable %10 Input | |
| %13 = OpTypeInt 32 1 | |
| %14 = OpTypePointer Input %13 | |
| %15 = OpVariable %14 Input | |
| %17 = OpConstant %13 0 | |
| %18 = OpTypeBool | |
| %26 = OpConstant %6 0 | |
| %27 = OpConstant %6 1 | |
| %28 = OpConstant %6 2 | |
| %29 = OpConstantComposite %7 %26 %27 %28 %26 | |
| %31 = OpTypePointer Output %7 | |
| %32 = OpVariable %31 Output | |
| %4 = OpFunction %2 None %3 | |
| %5 = OpLabel | |
| %12 = OpLoad %7 %11 | |
| %16 = OpLoad %13 %15 | |
| %19 = OpIEqual %18 %16 %17 | |
| OpSelectionMerge %21 None | |
| OpBranchConditional %19 %20 %24 | |
| %20 = OpLabel | |
| OpBranch %21 | |
| %24 = OpLabel | |
| %30 = OpFAdd %7 %12 %29 | |
| OpBranch %21 | |
| %21 = OpLabel | |
| %36 = OpPhi %7 %12 %20 %30 %24 | |
| %35 = OpFAdd %7 %36 %12 | |
| OpStore %32 %35 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| Module* module = context->module(); | |
| EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" | |
| << text << std::endl; | |
| Function* f = &*module->begin(); | |
| LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); | |
| const RegisterLiveness* register_liveness = liveness_analysis->Get(f); | |
| { | |
| SCOPED_TRACE("Block 5"); | |
| auto live_sets = register_liveness->Get(5); | |
| std::unordered_set<uint32_t> live_in{ | |
| 11, // %11 = OpVariable %10 Input | |
| 15, // %15 = OpVariable %14 Input | |
| 32, // %32 = OpVariable %31 Output | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 32, // %32 = OpVariable %31 Output | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| } | |
| { | |
| SCOPED_TRACE("Block 20"); | |
| auto live_sets = register_liveness->Get(20); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 32, // %32 = OpVariable %31 Output | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| } | |
| { | |
| SCOPED_TRACE("Block 24"); | |
| auto live_sets = register_liveness->Get(24); | |
| std::unordered_set<uint32_t> live_in{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 32, // %32 = OpVariable %31 Output | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 30, // %30 = OpFAdd %7 %12 %29 | |
| 32, // %32 = OpVariable %31 Output | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| } | |
| { | |
| SCOPED_TRACE("Block 21"); | |
| auto live_sets = register_liveness->Get(21); | |
| std::unordered_set<uint32_t> live_in{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 32, // %32 = OpVariable %31 Output | |
| 36, // %36 = OpPhi %7 %12 %20 %30 %24 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{}; | |
| CompareSets(live_sets->live_out_, live_out); | |
| } | |
| } | |
| /* | |
| Generated from the following GLSL | |
| #version 330 | |
| in vec4 bigColor; | |
| in vec4 BaseColor; | |
| in float f; | |
| flat in int Count; | |
| flat in uvec4 v4; | |
| void main() | |
| { | |
| vec4 color = BaseColor; | |
| for (int i = 0; i < Count; ++i) | |
| color += bigColor; | |
| float sum = 0.0; | |
| for (int i = 0; i < 4; ++i) { | |
| float acc = 0.0; | |
| if (sum == 0.0) { | |
| acc = v4[i]; | |
| } | |
| else { | |
| acc = BaseColor[i]; | |
| } | |
| sum += acc + v4[i]; | |
| } | |
| vec4 tv4; | |
| for (int i = 0; i < 4; ++i) | |
| tv4[i] = v4[i] * 4u; | |
| color += vec4(sum) + tv4; | |
| vec4 r; | |
| r.xyz = BaseColor.xyz; | |
| for (int i = 0; i < Count; ++i) | |
| r.w = f; | |
| color.xyz += r.xyz; | |
| for (int i = 0; i < 16; i += 4) | |
| for (int j = 0; j < 4; j++) | |
| color *= f; | |
| gl_FragColor = color + tv4; | |
| } | |
| */ | |
| TEST_F(PassClassTest, RegisterLiveness) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %4 "main" %11 %24 %28 %55 %124 %176 | |
| OpExecutionMode %4 OriginLowerLeft | |
| OpSource GLSL 330 | |
| OpName %4 "main" | |
| OpName %11 "BaseColor" | |
| OpName %24 "Count" | |
| OpName %28 "bigColor" | |
| OpName %55 "v4" | |
| OpName %84 "tv4" | |
| OpName %124 "f" | |
| OpName %176 "gl_FragColor" | |
| OpDecorate %11 Location 0 | |
| OpDecorate %24 Flat | |
| OpDecorate %24 Location 0 | |
| OpDecorate %28 Location 0 | |
| OpDecorate %55 Flat | |
| OpDecorate %55 Location 0 | |
| OpDecorate %124 Location 0 | |
| OpDecorate %176 Location 0 | |
| %2 = OpTypeVoid | |
| %3 = OpTypeFunction %2 | |
| %6 = OpTypeFloat 32 | |
| %7 = OpTypeVector %6 4 | |
| %8 = OpTypePointer Function %7 | |
| %10 = OpTypePointer Input %7 | |
| %11 = OpVariable %10 Input | |
| %13 = OpTypeInt 32 1 | |
| %16 = OpConstant %13 0 | |
| %23 = OpTypePointer Input %13 | |
| %24 = OpVariable %23 Input | |
| %26 = OpTypeBool | |
| %28 = OpVariable %10 Input | |
| %33 = OpConstant %13 1 | |
| %35 = OpTypePointer Function %6 | |
| %37 = OpConstant %6 0 | |
| %45 = OpConstant %13 4 | |
| %52 = OpTypeInt 32 0 | |
| %53 = OpTypeVector %52 4 | |
| %54 = OpTypePointer Input %53 | |
| %55 = OpVariable %54 Input | |
| %57 = OpTypePointer Input %52 | |
| %63 = OpTypePointer Input %6 | |
| %89 = OpConstant %52 4 | |
| %102 = OpTypeVector %6 3 | |
| %124 = OpVariable %63 Input | |
| %158 = OpConstant %13 16 | |
| %175 = OpTypePointer Output %7 | |
| %176 = OpVariable %175 Output | |
| %195 = OpUndef %7 | |
| %4 = OpFunction %2 None %3 | |
| %5 = OpLabel | |
| %84 = OpVariable %8 Function | |
| %12 = OpLoad %7 %11 | |
| OpBranch %17 | |
| %17 = OpLabel | |
| %191 = OpPhi %7 %12 %5 %31 %18 | |
| %184 = OpPhi %13 %16 %5 %34 %18 | |
| %25 = OpLoad %13 %24 | |
| %27 = OpSLessThan %26 %184 %25 | |
| OpLoopMerge %19 %18 None | |
| OpBranchConditional %27 %18 %19 | |
| %18 = OpLabel | |
| %29 = OpLoad %7 %28 | |
| %31 = OpFAdd %7 %191 %29 | |
| %34 = OpIAdd %13 %184 %33 | |
| OpBranch %17 | |
| %19 = OpLabel | |
| OpBranch %39 | |
| %39 = OpLabel | |
| %188 = OpPhi %6 %37 %19 %73 %51 | |
| %185 = OpPhi %13 %16 %19 %75 %51 | |
| %46 = OpSLessThan %26 %185 %45 | |
| OpLoopMerge %41 %51 None | |
| OpBranchConditional %46 %40 %41 | |
| %40 = OpLabel | |
| %49 = OpFOrdEqual %26 %188 %37 | |
| OpSelectionMerge %51 None | |
| OpBranchConditional %49 %50 %61 | |
| %50 = OpLabel | |
| %58 = OpAccessChain %57 %55 %185 | |
| %59 = OpLoad %52 %58 | |
| %60 = OpConvertUToF %6 %59 | |
| OpBranch %51 | |
| %61 = OpLabel | |
| %64 = OpAccessChain %63 %11 %185 | |
| %65 = OpLoad %6 %64 | |
| OpBranch %51 | |
| %51 = OpLabel | |
| %210 = OpPhi %6 %60 %50 %65 %61 | |
| %68 = OpAccessChain %57 %55 %185 | |
| %69 = OpLoad %52 %68 | |
| %70 = OpConvertUToF %6 %69 | |
| %71 = OpFAdd %6 %210 %70 | |
| %73 = OpFAdd %6 %188 %71 | |
| %75 = OpIAdd %13 %185 %33 | |
| OpBranch %39 | |
| %41 = OpLabel | |
| OpBranch %77 | |
| %77 = OpLabel | |
| %186 = OpPhi %13 %16 %41 %94 %78 | |
| %83 = OpSLessThan %26 %186 %45 | |
| OpLoopMerge %79 %78 None | |
| OpBranchConditional %83 %78 %79 | |
| %78 = OpLabel | |
| %87 = OpAccessChain %57 %55 %186 | |
| %88 = OpLoad %52 %87 | |
| %90 = OpIMul %52 %88 %89 | |
| %91 = OpConvertUToF %6 %90 | |
| %92 = OpAccessChain %35 %84 %186 | |
| OpStore %92 %91 | |
| %94 = OpIAdd %13 %186 %33 | |
| OpBranch %77 | |
| %79 = OpLabel | |
| %96 = OpCompositeConstruct %7 %188 %188 %188 %188 | |
| %97 = OpLoad %7 %84 | |
| %98 = OpFAdd %7 %96 %97 | |
| %100 = OpFAdd %7 %191 %98 | |
| %104 = OpVectorShuffle %102 %12 %12 0 1 2 | |
| %106 = OpVectorShuffle %7 %195 %104 4 5 6 3 | |
| OpBranch %108 | |
| %108 = OpLabel | |
| %197 = OpPhi %7 %106 %79 %208 %133 | |
| %196 = OpPhi %13 %16 %79 %143 %133 | |
| %115 = OpSLessThan %26 %196 %25 | |
| OpLoopMerge %110 %133 None | |
| OpBranchConditional %115 %109 %110 | |
| %109 = OpLabel | |
| OpBranch %117 | |
| %117 = OpLabel | |
| %209 = OpPhi %7 %197 %109 %181 %118 | |
| %204 = OpPhi %13 %16 %109 %129 %118 | |
| %123 = OpSLessThan %26 %204 %45 | |
| OpLoopMerge %119 %118 None | |
| OpBranchConditional %123 %118 %119 | |
| %118 = OpLabel | |
| %125 = OpLoad %6 %124 | |
| %181 = OpCompositeInsert %7 %125 %209 3 | |
| %129 = OpIAdd %13 %204 %33 | |
| OpBranch %117 | |
| %119 = OpLabel | |
| OpBranch %131 | |
| %131 = OpLabel | |
| %208 = OpPhi %7 %209 %119 %183 %132 | |
| %205 = OpPhi %13 %16 %119 %141 %132 | |
| %137 = OpSLessThan %26 %205 %45 | |
| OpLoopMerge %133 %132 None | |
| OpBranchConditional %137 %132 %133 | |
| %132 = OpLabel | |
| %138 = OpLoad %6 %124 | |
| %183 = OpCompositeInsert %7 %138 %208 3 | |
| %141 = OpIAdd %13 %205 %33 | |
| OpBranch %131 | |
| %133 = OpLabel | |
| %143 = OpIAdd %13 %196 %33 | |
| OpBranch %108 | |
| %110 = OpLabel | |
| %145 = OpVectorShuffle %102 %197 %197 0 1 2 | |
| %147 = OpVectorShuffle %102 %100 %100 0 1 2 | |
| %148 = OpFAdd %102 %147 %145 | |
| %150 = OpVectorShuffle %7 %100 %148 4 5 6 3 | |
| OpBranch %152 | |
| %152 = OpLabel | |
| %200 = OpPhi %7 %150 %110 %203 %163 | |
| %199 = OpPhi %13 %16 %110 %174 %163 | |
| %159 = OpSLessThan %26 %199 %158 | |
| OpLoopMerge %154 %163 None | |
| OpBranchConditional %159 %153 %154 | |
| %153 = OpLabel | |
| OpBranch %161 | |
| %161 = OpLabel | |
| %203 = OpPhi %7 %200 %153 %170 %162 | |
| %201 = OpPhi %13 %16 %153 %172 %162 | |
| %167 = OpSLessThan %26 %201 %45 | |
| OpLoopMerge %163 %162 None | |
| OpBranchConditional %167 %162 %163 | |
| %162 = OpLabel | |
| %168 = OpLoad %6 %124 | |
| %170 = OpVectorTimesScalar %7 %203 %168 | |
| %172 = OpIAdd %13 %201 %33 | |
| OpBranch %161 | |
| %163 = OpLabel | |
| %174 = OpIAdd %13 %199 %45 | |
| OpBranch %152 | |
| %154 = OpLabel | |
| %178 = OpLoad %7 %84 | |
| %179 = OpFAdd %7 %200 %178 | |
| OpStore %176 %179 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| Module* module = context->module(); | |
| EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" | |
| << text << std::endl; | |
| Function* f = &*module->begin(); | |
| LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); | |
| const RegisterLiveness* register_liveness = liveness_analysis->Get(f); | |
| LoopDescriptor& ld = *context->GetLoopDescriptor(f); | |
| { | |
| SCOPED_TRACE("Block 5"); | |
| auto live_sets = register_liveness->Get(5); | |
| std::unordered_set<uint32_t> live_in{ | |
| 11, // %11 = OpVariable %10 Input | |
| 24, // %24 = OpVariable %23 Input | |
| 28, // %28 = OpVariable %10 Input | |
| 55, // %55 = OpVariable %54 Input | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 24, // %24 = OpVariable %23 Input | |
| 28, // %28 = OpVariable %10 Input | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 8u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 17"); | |
| auto live_sets = register_liveness->Get(17); | |
| std::unordered_set<uint32_t> live_in{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 24, // %24 = OpVariable %23 Input | |
| 28, // %28 = OpVariable %10 Input | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 184, // %184 = OpPhi %13 %16 %5 %34 %18 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 28, // %28 = OpVariable %10 Input | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 184, // %184 = OpPhi %13 %16 %5 %34 %18 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 11u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 18"); | |
| auto live_sets = register_liveness->Get(18); | |
| std::unordered_set<uint32_t> live_in{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 24, // %24 = OpVariable %23 Input | |
| 28, // %28 = OpVariable %10 Input | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 184, // %184 = OpPhi %13 %16 %5 %34 %18 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 24, // %24 = OpVariable %23 Input | |
| 28, // %28 = OpVariable %10 Input | |
| 31, // %31 = OpFAdd %7 %191 %29 | |
| 34, // %34 = OpIAdd %13 %184 %33 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 12u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 19"); | |
| auto live_sets = register_liveness->Get(19); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 8u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 39"); | |
| auto live_sets = register_liveness->Get(39); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 185, // %185 = OpPhi %13 %16 %19 %75 %51 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 11u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 40"); | |
| auto live_sets = register_liveness->Get(40); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 185, // %185 = OpPhi %13 %16 %19 %75 %51 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 11u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 50"); | |
| auto live_sets = register_liveness->Get(50); | |
| std::unordered_set<uint32_t> live_in{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 185, // %185 = OpPhi %13 %16 %19 %75 %51 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 60, // %60 = OpConvertUToF %6 %59 | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 185, // %185 = OpPhi %13 %16 %19 %75 %51 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 12u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 61"); | |
| auto live_sets = register_liveness->Get(61); | |
| std::unordered_set<uint32_t> live_in{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 185, // %185 = OpPhi %13 %16 %19 %75 %51 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 65, // %65 = OpLoad %6 %64 | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 185, // %185 = OpPhi %13 %16 %19 %75 %51 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 12u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 51"); | |
| auto live_sets = register_liveness->Get(51); | |
| std::unordered_set<uint32_t> live_in{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 185, // %185 = OpPhi %13 %16 %19 %75 %51 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| 210, // %210 = OpPhi %6 %60 %50 %65 %61 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 73, // %73 = OpFAdd %6 %188 %71 | |
| 75, // %75 = OpIAdd %13 %185 %33 | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 13u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 41"); | |
| auto live_sets = register_liveness->Get(41); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 8u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 77"); | |
| auto live_sets = register_liveness->Get(77); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 186, // %186 = OpPhi %13 %16 %41 %94 %78 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 10u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 78"); | |
| auto live_sets = register_liveness->Get(78); | |
| std::unordered_set<uint32_t> live_in{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 186, // %186 = OpPhi %13 %16 %41 %94 %78 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 94, // %94 = OpIAdd %13 %186 %33 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 11u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 79"); | |
| auto live_sets = register_liveness->Get(79); | |
| std::unordered_set<uint32_t> live_in{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 106, // %106 = OpVectorShuffle %7 %195 %104 4 5 6 3 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 9u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 108"); | |
| auto live_sets = register_liveness->Get(108); | |
| std::unordered_set<uint32_t> live_in{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| 197, // %197 = OpPhi %7 %106 %79 %208 %133 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| 197, // %197 = OpPhi %7 %106 %79 %208 %133 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 8u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 109"); | |
| auto live_sets = register_liveness->Get(109); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| 197, // %197 = OpPhi %7 %106 %79 %208 %133 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 7u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 117"); | |
| auto live_sets = register_liveness->Get(117); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| 204, // %204 = OpPhi %13 %16 %109 %129 %118 | |
| 209, // %209 = OpPhi %7 %197 %109 %181 %118 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 9u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 118"); | |
| auto live_sets = register_liveness->Get(118); | |
| std::unordered_set<uint32_t> live_in{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| 204, // %204 = OpPhi %13 %16 %109 %129 %118 | |
| 209, // %209 = OpPhi %7 %197 %109 %181 %118 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 129, // %129 = OpIAdd %13 %204 %33 | |
| 176, // %176 = OpVariable %175 Output | |
| 181, // %181 = OpCompositeInsert %7 %125 %209 3 | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 10u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 119"); | |
| auto live_sets = register_liveness->Get(119); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| 209, // %209 = OpPhi %7 %197 %109 %181 %118 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 7u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 131"); | |
| auto live_sets = register_liveness->Get(131); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| 205, // %205 = OpPhi %13 %16 %119 %141 %132 | |
| 208, // %208 = OpPhi %7 %209 %119 %183 %132 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 9u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 132"); | |
| auto live_sets = register_liveness->Get(132); | |
| std::unordered_set<uint32_t> live_in{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| 205, // %205 = OpPhi %13 %16 %119 %141 %132 | |
| 208, // %208 = OpPhi %7 %209 %119 %183 %132 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 141, // %141 = OpIAdd %13 %205 %33 | |
| 176, // %176 = OpVariable %175 Output | |
| 183, // %183 = OpCompositeInsert %7 %138 %208 3 | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 10u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 133"); | |
| auto live_sets = register_liveness->Get(133); | |
| std::unordered_set<uint32_t> live_in{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 196, // %196 = OpPhi %13 %16 %79 %143 %133 | |
| 208, // %208 = OpPhi %7 %209 %119 %183 %132 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 25, // %25 = OpLoad %13 %24 | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 143, // %143 = OpIAdd %13 %196 %33 | |
| 176, // %176 = OpVariable %175 Output | |
| 208, // %208 = OpPhi %7 %209 %119 %183 %132 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 8u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 110"); | |
| auto live_sets = register_liveness->Get(110); | |
| std::unordered_set<uint32_t> live_in{ | |
| 84, // %84 = OpVariable %8 Function | |
| 100, // %100 = OpFAdd %7 %191 %98 | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 197, // %197 = OpPhi %7 %106 %79 %208 %133 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 150, // %150 = OpVectorShuffle %7 %100 %148 4 5 6 3 | |
| 176, // %176 = OpVariable %175 Output | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 7u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 152"); | |
| auto live_sets = register_liveness->Get(152); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 199, // %199 = OpPhi %13 %16 %110 %174 %163 | |
| 200, // %200 = OpPhi %7 %150 %110 %203 %163 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 6u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 153"); | |
| auto live_sets = register_liveness->Get(153); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 199, // %199 = OpPhi %13 %16 %110 %174 %163 | |
| 200, // %200 = OpPhi %7 %150 %110 %203 %163 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 5u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 161"); | |
| auto live_sets = register_liveness->Get(161); | |
| std::unordered_set<uint32_t> live_inout{ | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 199, // %199 = OpPhi %13 %16 %110 %174 %163 | |
| 201, // %201 = OpPhi %13 %16 %153 %172 %162 | |
| 203, // %203 = OpPhi %7 %200 %153 %170 %162 | |
| }; | |
| CompareSets(live_sets->live_in_, live_inout); | |
| CompareSets(live_sets->live_out_, live_inout); | |
| EXPECT_EQ(live_sets->used_registers_, 7u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 162"); | |
| auto live_sets = register_liveness->Get(162); | |
| std::unordered_set<uint32_t> live_in{ | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 199, // %199 = OpPhi %13 %16 %110 %174 %163 | |
| 201, // %201 = OpPhi %13 %16 %153 %172 %162 | |
| 203, // %203 = OpPhi %7 %200 %153 %170 %162 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 170, // %170 = OpVectorTimesScalar %7 %203 %168 | |
| 172, // %172 = OpIAdd %13 %201 %33 | |
| 176, // %176 = OpVariable %175 Output | |
| 199, // %199 = OpPhi %13 %16 %110 %174 %163 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 8u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 163"); | |
| auto live_sets = register_liveness->Get(163); | |
| std::unordered_set<uint32_t> live_in{ | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 199, // %199 = OpPhi %13 %16 %110 %174 %163 | |
| 203, // %203 = OpPhi %7 %200 %153 %170 %162 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 174, // %174 = OpIAdd %13 %199 %45 | |
| 176, // %176 = OpVariable %175 Output | |
| 203, // %203 = OpPhi %7 %200 %153 %170 %162 | |
| }; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 6u); | |
| } | |
| { | |
| SCOPED_TRACE("Block 154"); | |
| auto live_sets = register_liveness->Get(154); | |
| std::unordered_set<uint32_t> live_in{ | |
| 84, // %84 = OpVariable %8 Function | |
| 176, // %176 = OpVariable %175 Output | |
| 200, // %200 = OpPhi %7 %150 %110 %203 %163 | |
| }; | |
| CompareSets(live_sets->live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{}; | |
| CompareSets(live_sets->live_out_, live_out); | |
| EXPECT_EQ(live_sets->used_registers_, 4u); | |
| } | |
| { | |
| SCOPED_TRACE("Compute loop pressure"); | |
| RegisterLiveness::RegionRegisterLiveness loop_reg_pressure; | |
| register_liveness->ComputeLoopRegisterPressure(*ld[39], &loop_reg_pressure); | |
| // Generate(*context->cfg()->block(39), &loop_reg_pressure); | |
| std::unordered_set<uint32_t> live_in{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 185, // %185 = OpPhi %13 %16 %19 %75 %51 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(loop_reg_pressure.live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(loop_reg_pressure.live_out_, live_out); | |
| EXPECT_EQ(loop_reg_pressure.used_registers_, 13u); | |
| } | |
| { | |
| SCOPED_TRACE("Loop Fusion simulation"); | |
| RegisterLiveness::RegionRegisterLiveness simulation_resut; | |
| register_liveness->SimulateFusion(*ld[17], *ld[39], &simulation_resut); | |
| std::unordered_set<uint32_t> live_in{ | |
| 11, // %11 = OpVariable %10 Input | |
| 12, // %12 = OpLoad %7 %11 | |
| 24, // %24 = OpVariable %23 Input | |
| 25, // %25 = OpLoad %13 %24 | |
| 28, // %28 = OpVariable %10 Input | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 184, // %184 = OpPhi %13 %16 %5 %34 %18 | |
| 185, // %185 = OpPhi %13 %16 %19 %75 %51 | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(simulation_resut.live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 12, // %12 = OpLoad %7 %11 | |
| 25, // %25 = OpLoad %13 %24 | |
| 55, // %55 = OpVariable %54 Input | |
| 84, // %84 = OpVariable %8 Function | |
| 124, // %124 = OpVariable %63 Input | |
| 176, // %176 = OpVariable %175 Output | |
| 188, // %188 = OpPhi %6 %37 %19 %73 %51 | |
| 191, // %191 = OpPhi %7 %12 %5 %31 %18 | |
| }; | |
| CompareSets(simulation_resut.live_out_, live_out); | |
| EXPECT_EQ(simulation_resut.used_registers_, 17u); | |
| } | |
| } | |
| TEST_F(PassClassTest, FissionSimulation) { | |
| const std::string source = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %2 "main" | |
| OpExecutionMode %2 OriginUpperLeft | |
| OpSource GLSL 430 | |
| OpName %2 "main" | |
| OpName %3 "i" | |
| OpName %4 "A" | |
| OpName %5 "B" | |
| %6 = OpTypeVoid | |
| %7 = OpTypeFunction %6 | |
| %8 = OpTypeInt 32 1 | |
| %9 = OpTypePointer Function %8 | |
| %10 = OpConstant %8 0 | |
| %11 = OpConstant %8 10 | |
| %12 = OpTypeBool | |
| %13 = OpTypeFloat 32 | |
| %14 = OpTypeInt 32 0 | |
| %15 = OpConstant %14 10 | |
| %16 = OpTypeArray %13 %15 | |
| %17 = OpTypePointer Function %16 | |
| %18 = OpTypePointer Function %13 | |
| %19 = OpConstant %8 1 | |
| %2 = OpFunction %6 None %7 | |
| %20 = OpLabel | |
| %3 = OpVariable %9 Function | |
| %4 = OpVariable %17 Function | |
| %5 = OpVariable %17 Function | |
| OpBranch %21 | |
| %21 = OpLabel | |
| %22 = OpPhi %8 %10 %20 %23 %24 | |
| OpLoopMerge %25 %24 None | |
| OpBranch %26 | |
| %26 = OpLabel | |
| %27 = OpSLessThan %12 %22 %11 | |
| OpBranchConditional %27 %28 %25 | |
| %28 = OpLabel | |
| %29 = OpAccessChain %18 %5 %22 | |
| %30 = OpLoad %13 %29 | |
| %31 = OpAccessChain %18 %4 %22 | |
| OpStore %31 %30 | |
| %32 = OpAccessChain %18 %4 %22 | |
| %33 = OpLoad %13 %32 | |
| %34 = OpAccessChain %18 %5 %22 | |
| OpStore %34 %33 | |
| OpBranch %24 | |
| %24 = OpLabel | |
| %23 = OpIAdd %8 %22 %19 | |
| OpBranch %21 | |
| %25 = OpLabel | |
| OpStore %3 %22 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, source, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| Module* module = context->module(); | |
| EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" | |
| << source << std::endl; | |
| Function* f = &*module->begin(); | |
| LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); | |
| const RegisterLiveness* register_liveness = liveness_analysis->Get(f); | |
| LoopDescriptor& ld = *context->GetLoopDescriptor(f); | |
| analysis::DefUseManager& def_use_mgr = *context->get_def_use_mgr(); | |
| { | |
| RegisterLiveness::RegionRegisterLiveness l1_sim_resut; | |
| RegisterLiveness::RegionRegisterLiveness l2_sim_resut; | |
| std::unordered_set<Instruction*> moved_instructions{ | |
| def_use_mgr.GetDef(29), def_use_mgr.GetDef(30), def_use_mgr.GetDef(31), | |
| def_use_mgr.GetDef(31)->NextNode()}; | |
| std::unordered_set<Instruction*> copied_instructions{ | |
| def_use_mgr.GetDef(22), def_use_mgr.GetDef(27), | |
| def_use_mgr.GetDef(27)->NextNode(), def_use_mgr.GetDef(23)}; | |
| register_liveness->SimulateFission(*ld[21], moved_instructions, | |
| copied_instructions, &l1_sim_resut, | |
| &l2_sim_resut); | |
| { | |
| SCOPED_TRACE("L1 simulation"); | |
| std::unordered_set<uint32_t> live_in{ | |
| 3, // %3 = OpVariable %9 Function | |
| 4, // %4 = OpVariable %17 Function | |
| 5, // %5 = OpVariable %17 Function | |
| 22, // %22 = OpPhi %8 %10 %20 %23 %24 | |
| }; | |
| CompareSets(l1_sim_resut.live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 3, // %3 = OpVariable %9 Function | |
| 4, // %4 = OpVariable %17 Function | |
| 5, // %5 = OpVariable %17 Function | |
| 22, // %22 = OpPhi %8 %10 %20 %23 %24 | |
| }; | |
| CompareSets(l1_sim_resut.live_out_, live_out); | |
| EXPECT_EQ(l1_sim_resut.used_registers_, 6u); | |
| } | |
| { | |
| SCOPED_TRACE("L2 simulation"); | |
| std::unordered_set<uint32_t> live_in{ | |
| 3, // %3 = OpVariable %9 Function | |
| 4, // %4 = OpVariable %17 Function | |
| 5, // %5 = OpVariable %17 Function | |
| 22, // %22 = OpPhi %8 %10 %20 %23 %24 | |
| }; | |
| CompareSets(l2_sim_resut.live_in_, live_in); | |
| std::unordered_set<uint32_t> live_out{ | |
| 3, // %3 = OpVariable %9 Function | |
| 22, // %22 = OpPhi %8 %10 %20 %23 %24 | |
| }; | |
| CompareSets(l2_sim_resut.live_out_, live_out); | |
| EXPECT_EQ(l2_sim_resut.used_registers_, 6u); | |
| } | |
| } | |
| } | |
| // Test that register liveness does not fail when there is an unreachable block. | |
| // We are not testing if the liveness is computed correctly because the specific | |
| // results do not matter for unreachable blocks. | |
| TEST_F(PassClassTest, RegisterLivenessWithUnreachableBlock) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %2 "main" | |
| OpExecutionMode %2 OriginLowerLeft | |
| OpSource GLSL 330 | |
| OpSourceExtension "GL_ARB_shading_language_420pack" | |
| %void = OpTypeVoid | |
| %4 = OpTypeFunction %void | |
| %2 = OpFunction %void None %4 | |
| %5 = OpLabel | |
| OpBranch %6 | |
| %6 = OpLabel | |
| OpLoopMerge %7 %8 None | |
| OpBranch %9 | |
| %9 = OpLabel | |
| OpBranch %7 | |
| %8 = OpLabel | |
| OpBranch %6 | |
| %7 = OpLabel | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| Module* module = context->module(); | |
| EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" | |
| << text << std::endl; | |
| Function* f = &*module->begin(); | |
| LivenessAnalysis* liveness_analysis = context->GetLivenessAnalysis(); | |
| liveness_analysis->Get(f); | |
| } | |
| } // namespace | |
| } // namespace opt | |
| } // namespace spvtools |