From 8336d1925ffebe3d663e029defe772e01db23be0 Mon Sep 17 00:00:00 2001 From: Alastair Donaldson Date: Thu, 22 Aug 2019 23:33:09 +0100 Subject: [PATCH] Extend reducer to remove relaxed precision decorations (#2797) Adds a reduction pass that removes OpDecorate and OpMemberDecorate instructions that annotate instructions and members with RelaxedPrecision. As well as being useful in its own right, removing such references allows other passes to remove further instructions. --- source/reduce/CMakeLists.txt | 2 + source/reduce/reducer.cpp | 3 + ...recision_decoration_opportunity_finder.cpp | 49 +++++ ..._precision_decoration_opportunity_finder.h | 36 ++++ ...struction_reduction_opportunity_finder.cpp | 4 +- test/reduce/CMakeLists.txt | 1 + ...move_relaxed_precision_decoration_test.cpp | 177 ++++++++++++++++++ 7 files changed, 269 insertions(+), 3 deletions(-) create mode 100644 source/reduce/remove_relaxed_precision_decoration_opportunity_finder.cpp create mode 100644 source/reduce/remove_relaxed_precision_decoration_opportunity_finder.h create mode 100644 test/reduce/remove_relaxed_precision_decoration_test.cpp diff --git a/source/reduce/CMakeLists.txt b/source/reduce/CMakeLists.txt index def4d2104..7651e8664 100644 --- a/source/reduce/CMakeLists.txt +++ b/source/reduce/CMakeLists.txt @@ -30,6 +30,7 @@ set(SPIRV_TOOLS_REDUCE_SOURCES remove_function_reduction_opportunity.h remove_function_reduction_opportunity_finder.h remove_opname_instruction_reduction_opportunity_finder.h + remove_relaxed_precision_decoration_opportunity_finder.h remove_selection_reduction_opportunity.h remove_selection_reduction_opportunity_finder.h remove_unreferenced_instruction_reduction_opportunity_finder.h @@ -56,6 +57,7 @@ set(SPIRV_TOOLS_REDUCE_SOURCES remove_function_reduction_opportunity.cpp remove_function_reduction_opportunity_finder.cpp remove_instruction_reduction_opportunity.cpp + remove_relaxed_precision_decoration_opportunity_finder.cpp remove_selection_reduction_opportunity.cpp remove_selection_reduction_opportunity_finder.cpp remove_unreferenced_instruction_reduction_opportunity_finder.cpp diff --git a/source/reduce/reducer.cpp b/source/reduce/reducer.cpp index a677be35b..ebb5d471e 100644 --- a/source/reduce/reducer.cpp +++ b/source/reduce/reducer.cpp @@ -25,6 +25,7 @@ #include "source/reduce/remove_block_reduction_opportunity_finder.h" #include "source/reduce/remove_function_reduction_opportunity_finder.h" #include "source/reduce/remove_opname_instruction_reduction_opportunity_finder.h" +#include "source/reduce/remove_relaxed_precision_decoration_opportunity_finder.h" #include "source/reduce/remove_selection_reduction_opportunity_finder.h" #include "source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.h" #include "source/reduce/simple_conditional_branch_to_branch_opportunity_finder.h" @@ -175,6 +176,8 @@ Reducer::ReductionResultStatus Reducer::Run( void Reducer::AddDefaultReductionPasses() { AddReductionPass(spvtools::MakeUnique< RemoveOpNameInstructionReductionOpportunityFinder>()); + AddReductionPass(spvtools::MakeUnique< + RemoveRelaxedPrecisionDecorationOpportunityFinder>()); AddReductionPass( spvtools::MakeUnique()); AddReductionPass( diff --git a/source/reduce/remove_relaxed_precision_decoration_opportunity_finder.cpp b/source/reduce/remove_relaxed_precision_decoration_opportunity_finder.cpp new file mode 100644 index 000000000..352cefb68 --- /dev/null +++ b/source/reduce/remove_relaxed_precision_decoration_opportunity_finder.cpp @@ -0,0 +1,49 @@ +// Copyright (c) 2018 Google Inc. +// +// 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 "source/reduce/remove_relaxed_precision_decoration_opportunity_finder.h" + +#include "source/reduce/remove_instruction_reduction_opportunity.h" + +namespace spvtools { +namespace reduce { + +std::vector> +RemoveRelaxedPrecisionDecorationOpportunityFinder::GetAvailableOpportunities( + opt::IRContext* context) const { + std::vector> result; + + // Consider all annotation instructions + for (auto& inst : context->module()->annotations()) { + // We are interested in removing instructions of the form: + // SpvOpDecorate %id RelaxedPrecision + // and + // SpvOpMemberDecorate %id member RelaxedPrecision + if ((inst.opcode() == SpvOpDecorate && + inst.GetSingleWordInOperand(1) == SpvDecorationRelaxedPrecision) || + (inst.opcode() == SpvOpMemberDecorate && + inst.GetSingleWordInOperand(2) == SpvDecorationRelaxedPrecision)) { + result.push_back( + MakeUnique(&inst)); + } + } + return result; +} + +std::string RemoveRelaxedPrecisionDecorationOpportunityFinder::GetName() const { + return "RemoveRelaxedPrecisionDecorationOpportunityFinder"; +} + +} // namespace reduce +} // namespace spvtools diff --git a/source/reduce/remove_relaxed_precision_decoration_opportunity_finder.h b/source/reduce/remove_relaxed_precision_decoration_opportunity_finder.h new file mode 100644 index 000000000..673049cc8 --- /dev/null +++ b/source/reduce/remove_relaxed_precision_decoration_opportunity_finder.h @@ -0,0 +1,36 @@ +// Copyright (c) 2019 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. + +#ifndef SOURCE_REDUCE_REMOVE_RELAXED_PRECISION_OPPORTUNITY_FINDER_H_ +#define SOURCE_REDUCE_REMOVE_RELAXED_PRECISION_OPPORTUNITY_FINDER_H_ + +#include "source/reduce/reduction_opportunity_finder.h" + +namespace spvtools { +namespace reduce { + +// A finder for opportunities to remove relaxed precision decorations. +class RemoveRelaxedPrecisionDecorationOpportunityFinder + : public ReductionOpportunityFinder { + public: + std::vector> GetAvailableOpportunities( + opt::IRContext* context) const override; + + std::string GetName() const override; +}; + +} // namespace reduce +} // namespace spvtools + +#endif // SOURCE_REDUCE_REMOVE_RELAXED_PRECISION_OPPORTUNITY_FINDER_H_ diff --git a/source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.cpp b/source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.cpp index 8f3243519..dabee50cd 100644 --- a/source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.cpp +++ b/source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.cpp @@ -21,11 +21,9 @@ namespace spvtools { namespace reduce { -using opt::IRContext; - std::vector> RemoveUnreferencedInstructionReductionOpportunityFinder:: - GetAvailableOpportunities(IRContext* context) const { + GetAvailableOpportunities(opt::IRContext* context) const { std::vector> result; for (auto& function : *context->module()) { diff --git a/test/reduce/CMakeLists.txt b/test/reduce/CMakeLists.txt index 964abdd5e..2d3b37834 100644 --- a/test/reduce/CMakeLists.txt +++ b/test/reduce/CMakeLists.txt @@ -24,6 +24,7 @@ add_spvtools_unittest(TARGET reduce remove_block_test.cpp remove_function_test.cpp remove_opname_instruction_test.cpp + remove_relaxed_precision_decoration_test.cpp remove_selection_test.cpp remove_unreferenced_instruction_test.cpp structured_loop_to_selection_test.cpp diff --git a/test/reduce/remove_relaxed_precision_decoration_test.cpp b/test/reduce/remove_relaxed_precision_decoration_test.cpp new file mode 100644 index 000000000..f9ff081cc --- /dev/null +++ b/test/reduce/remove_relaxed_precision_decoration_test.cpp @@ -0,0 +1,177 @@ +// Copyright (c) 2019 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 "source/reduce/remove_relaxed_precision_decoration_opportunity_finder.h" + +#include "source/opt/build_module.h" +#include "source/reduce/reduction_opportunity.h" +#include "source/reduce/reduction_pass.h" +#include "test/reduce/reduce_test_util.h" + +namespace spvtools { +namespace reduce { +namespace { + +TEST(RemoveRelaxedPrecisionDecorationTest, 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 ops = RemoveRelaxedPrecisionDecorationOpportunityFinder() + .GetAvailableOpportunities(context.get()); + ASSERT_EQ(0, ops.size()); +} + +TEST(RemoveRelaxedPrecisionDecorationTest, RemoveDecorations) { + 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 + OpName %4 "main" + OpName %8 "f" + OpName %12 "i" + OpName %16 "v" + OpName %19 "S" + OpMemberName %19 0 "a" + OpMemberName %19 1 "b" + OpMemberName %19 2 "c" + OpName %21 "s" + OpDecorate %8 RelaxedPrecision + OpDecorate %12 RelaxedPrecision + OpDecorate %16 RelaxedPrecision + OpDecorate %17 RelaxedPrecision + OpDecorate %18 RelaxedPrecision + OpMemberDecorate %19 0 RelaxedPrecision + OpMemberDecorate %19 1 RelaxedPrecision + OpMemberDecorate %19 2 RelaxedPrecision + OpDecorate %22 RelaxedPrecision + OpDecorate %23 RelaxedPrecision + OpDecorate %24 RelaxedPrecision + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeFloat 32 + %7 = OpTypePointer Function %6 + %9 = OpConstant %6 2 + %10 = OpTypeInt 32 1 + %11 = OpTypePointer Function %10 + %13 = OpConstant %10 22 + %14 = OpTypeVector %6 2 + %15 = OpTypePointer Function %14 + %19 = OpTypeStruct %10 %6 %14 + %20 = OpTypePointer Function %19 + %4 = OpFunction %2 None %3 + %5 = OpLabel + %8 = OpVariable %7 Function + %12 = OpVariable %11 Function + %16 = OpVariable %15 Function + %21 = OpVariable %20 Function + OpStore %8 %9 + OpStore %12 %13 + %17 = OpLoad %6 %8 + %18 = OpCompositeConstruct %14 %17 %17 + OpStore %16 %18 + %22 = OpLoad %10 %12 + %23 = OpLoad %6 %8 + %24 = OpLoad %14 %16 + %25 = OpCompositeConstruct %19 %22 %23 %24 + OpStore %21 %25 + OpReturn + OpFunctionEnd + )"; + + const auto env = SPV_ENV_UNIVERSAL_1_3; + const auto consumer = nullptr; + const auto context = + BuildModule(env, consumer, source, kReduceAssembleOption); + const auto ops = RemoveRelaxedPrecisionDecorationOpportunityFinder() + .GetAvailableOpportunities(context.get()); + ASSERT_EQ(11, ops.size()); + + for (auto& op : ops) { + ASSERT_TRUE(op->PreconditionHolds()); + op->TryToApply(); + } + + const std::string expected = R"( + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %4 "main" + OpExecutionMode %4 OriginUpperLeft + OpSource ESSL 310 + OpName %4 "main" + OpName %8 "f" + OpName %12 "i" + OpName %16 "v" + OpName %19 "S" + OpMemberName %19 0 "a" + OpMemberName %19 1 "b" + OpMemberName %19 2 "c" + OpName %21 "s" + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeFloat 32 + %7 = OpTypePointer Function %6 + %9 = OpConstant %6 2 + %10 = OpTypeInt 32 1 + %11 = OpTypePointer Function %10 + %13 = OpConstant %10 22 + %14 = OpTypeVector %6 2 + %15 = OpTypePointer Function %14 + %19 = OpTypeStruct %10 %6 %14 + %20 = OpTypePointer Function %19 + %4 = OpFunction %2 None %3 + %5 = OpLabel + %8 = OpVariable %7 Function + %12 = OpVariable %11 Function + %16 = OpVariable %15 Function + %21 = OpVariable %20 Function + OpStore %8 %9 + OpStore %12 %13 + %17 = OpLoad %6 %8 + %18 = OpCompositeConstruct %14 %17 %17 + OpStore %16 %18 + %22 = OpLoad %10 %12 + %23 = OpLoad %6 %8 + %24 = OpLoad %14 %16 + %25 = OpCompositeConstruct %19 %22 %23 %24 + OpStore %21 %25 + OpReturn + OpFunctionEnd + )"; + + CheckEqual(env, expected, context.get()); +} + +} // namespace +} // namespace reduce +} // namespace spvtools