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.
This commit is contained in:
Alastair Donaldson 2019-08-22 23:33:09 +01:00 committed by GitHub
parent b00ef0d26e
commit 8336d1925f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 269 additions and 3 deletions

View File

@ -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

View File

@ -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<OperandToUndefReductionOpportunityFinder>());
AddReductionPass(

View File

@ -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<std::unique_ptr<ReductionOpportunity>>
RemoveRelaxedPrecisionDecorationOpportunityFinder::GetAvailableOpportunities(
opt::IRContext* context) const {
std::vector<std::unique_ptr<ReductionOpportunity>> 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<RemoveInstructionReductionOpportunity>(&inst));
}
}
return result;
}
std::string RemoveRelaxedPrecisionDecorationOpportunityFinder::GetName() const {
return "RemoveRelaxedPrecisionDecorationOpportunityFinder";
}
} // namespace reduce
} // namespace spvtools

View File

@ -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<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
opt::IRContext* context) const override;
std::string GetName() const override;
};
} // namespace reduce
} // namespace spvtools
#endif // SOURCE_REDUCE_REMOVE_RELAXED_PRECISION_OPPORTUNITY_FINDER_H_

View File

@ -21,11 +21,9 @@
namespace spvtools {
namespace reduce {
using opt::IRContext;
std::vector<std::unique_ptr<ReductionOpportunity>>
RemoveUnreferencedInstructionReductionOpportunityFinder::
GetAvailableOpportunities(IRContext* context) const {
GetAvailableOpportunities(opt::IRContext* context) const {
std::vector<std::unique_ptr<ReductionOpportunity>> result;
for (auto& function : *context->module()) {

View File

@ -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

View File

@ -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