mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-26 17:51:02 +00:00
4aeadc0199
Add a spirv-reduce pass which removes OpName and OpMemberName instructions. This is useful to enable other reduction passes, e.g. RemoveUnreferencedInstruction may not be able to remove an instruction creating an id whose only usage is an OpName for this id.
217 lines
6.7 KiB
C++
217 lines
6.7 KiB
C++
// 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 "reduce_test_util.h"
|
|
|
|
#include "source/opt/build_module.h"
|
|
#include "source/reduce/reduction_opportunity.h"
|
|
#include "source/reduce/remove_opname_instruction_reduction_pass.h"
|
|
|
|
namespace spvtools {
|
|
namespace reduce {
|
|
namespace {
|
|
|
|
TEST(RemoveOpnameInstructionReductionPassTest, NothingToRemove) {
|
|
const std::string source = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
const auto context =
|
|
BuildModule(env, consumer, source, kReduceAssembleOption);
|
|
const auto pass = TestSubclass<RemoveOpNameInstructionReductionPass>(env);
|
|
const auto ops = pass.WrapGetAvailableOpportunities(context.get());
|
|
ASSERT_EQ(0, ops.size());
|
|
}
|
|
|
|
TEST(RemoveOpnameInstructionReductionPassTest, RemoveSingleOpName) {
|
|
const std::string prologue = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
)";
|
|
|
|
const std::string epilogue = R"(
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const std::string original = prologue + R"(
|
|
OpName %4 "main"
|
|
)" + epilogue;
|
|
|
|
const std::string expected = prologue + epilogue;
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
const auto context =
|
|
BuildModule(env, consumer, original, kReduceAssembleOption);
|
|
const auto pass = TestSubclass<RemoveOpNameInstructionReductionPass>(env);
|
|
const auto ops = pass.WrapGetAvailableOpportunities(context.get());
|
|
ASSERT_EQ(1, ops.size());
|
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
|
ops[0]->TryToApply();
|
|
|
|
CheckEqual(env, expected, context.get());
|
|
}
|
|
|
|
TEST(RemoveOpnameInstructionReductionPassTest, TryApplyRemovesAllOpName) {
|
|
const std::string prologue = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
)";
|
|
|
|
const std::string epilogue = R"(
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypePointer Function %6
|
|
%9 = OpConstant %6 1
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%8 = OpVariable %7 Function
|
|
%10 = OpVariable %7 Function
|
|
%11 = OpVariable %7 Function
|
|
%12 = OpVariable %7 Function
|
|
OpStore %8 %9
|
|
OpStore %10 %9
|
|
OpStore %11 %9
|
|
OpStore %12 %9
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const std::string original = prologue + R"(
|
|
OpName %4 "main"
|
|
OpName %8 "a"
|
|
OpName %10 "b"
|
|
OpName %11 "c"
|
|
OpName %12 "d"
|
|
)" + epilogue;
|
|
|
|
const std::string expected = prologue + epilogue;
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
auto pass = TestSubclass<RemoveOpNameInstructionReductionPass>(env);
|
|
|
|
{
|
|
// Check the right number of opportunities is detected
|
|
const auto consumer = nullptr;
|
|
const auto context =
|
|
BuildModule(env, consumer, original, kReduceAssembleOption);
|
|
const auto ops = pass.WrapGetAvailableOpportunities(context.get());
|
|
ASSERT_EQ(5, ops.size());
|
|
}
|
|
|
|
{
|
|
// The reduction should remove all OpName
|
|
std::vector<uint32_t> binary;
|
|
SpirvTools t(env);
|
|
ASSERT_TRUE(t.Assemble(original, &binary, kReduceAssembleOption));
|
|
auto reduced_binary = pass.TryApplyReduction(binary);
|
|
CheckEqual(env, expected, reduced_binary);
|
|
}
|
|
}
|
|
|
|
TEST(RemoveOpnameInstructionReductionPassTest,
|
|
TryApplyRemovesAllOpNameAndOpMemberName) {
|
|
const std::string prologue = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
)";
|
|
|
|
const std::string epilogue = R"(
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypeInt 32 1
|
|
%8 = OpTypeVector %6 3
|
|
%9 = OpTypeStruct %6 %7 %8
|
|
%10 = OpTypePointer Function %9
|
|
%12 = OpConstant %7 0
|
|
%13 = OpConstant %6 1
|
|
%14 = OpTypePointer Function %6
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%11 = OpVariable %10 Function
|
|
%15 = OpAccessChain %14 %11 %12
|
|
OpStore %15 %13
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const std::string original = prologue + R"(
|
|
OpName %4 "main"
|
|
OpName %9 "S"
|
|
OpMemberName %9 0 "f"
|
|
OpMemberName %9 1 "i"
|
|
OpMemberName %9 2 "v"
|
|
OpName %11 "s"
|
|
)" + epilogue;
|
|
|
|
const std::string expected = prologue + epilogue;
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
auto pass = TestSubclass<RemoveOpNameInstructionReductionPass>(env);
|
|
|
|
{
|
|
// Check the right number of opportunities is detected
|
|
const auto consumer = nullptr;
|
|
const auto context =
|
|
BuildModule(env, consumer, original, kReduceAssembleOption);
|
|
const auto ops = pass.WrapGetAvailableOpportunities(context.get());
|
|
ASSERT_EQ(6, ops.size());
|
|
}
|
|
|
|
{
|
|
// The reduction should remove all OpName
|
|
std::vector<uint32_t> binary;
|
|
SpirvTools t(env);
|
|
ASSERT_TRUE(t.Assemble(original, &binary, kReduceAssembleOption));
|
|
auto reduced_binary = pass.TryApplyReduction(binary);
|
|
CheckEqual(env, expected, reduced_binary);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace reduce
|
|
} // namespace spvtools
|