Skip to content

Commit

Permalink
Add RemoveOpNameInstruction reduction pass (KhronosGroup#2187)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
hevrard authored and s-perron committed Dec 10, 2018
1 parent 8fc8dfe commit 4aeadc0
Show file tree
Hide file tree
Showing 7 changed files with 389 additions and 1 deletion.
2 changes: 2 additions & 0 deletions source/reduce/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ set(SPIRV_TOOLS_REDUCE_SOURCES
reduction_opportunity.h
reduction_pass.h
remove_instruction_reduction_opportunity.h
remove_opname_instruction_reduction_pass.h
remove_unreferenced_instruction_reduction_pass.h
structured_loop_to_selection_reduction_opportunity.h
structured_loop_to_selection_reduction_pass.h
Expand All @@ -31,6 +32,7 @@ set(SPIRV_TOOLS_REDUCE_SOURCES
reduction_pass.cpp
remove_instruction_reduction_opportunity.cpp
remove_unreferenced_instruction_reduction_pass.cpp
remove_opname_instruction_reduction_pass.cpp
structured_loop_to_selection_reduction_opportunity.cpp
structured_loop_to_selection_reduction_pass.cpp
)
Expand Down
44 changes: 44 additions & 0 deletions source/reduce/remove_opname_instruction_reduction_pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// 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 "remove_opname_instruction_reduction_pass.h"
#include "remove_instruction_reduction_opportunity.h"
#include "source/opcode.h"
#include "source/opt/instruction.h"

namespace spvtools {
namespace reduce {

using namespace opt;

std::vector<std::unique_ptr<ReductionOpportunity>>
RemoveOpNameInstructionReductionPass::GetAvailableOpportunities(
opt::IRContext* context) const {
std::vector<std::unique_ptr<ReductionOpportunity>> result;

for (auto& inst : context->module()->debugs2()) {
if (inst.opcode() == SpvOpName || inst.opcode() == SpvOpMemberName) {
result.push_back(
MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
}
}
return result;
}

std::string RemoveOpNameInstructionReductionPass::GetName() const {
return "RemoveOpNameInstructionReductionPass";
}

} // namespace reduce
} // namespace spvtools
50 changes: 50 additions & 0 deletions source/reduce/remove_opname_instruction_reduction_pass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// 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.

#ifndef SOURCE_REDUCE_REMOVE_OPNAME_INSTRUCTION_REDUCTION_PASS_H_
#define SOURCE_REDUCE_REMOVE_OPNAME_INSTRUCTION_REDUCTION_PASS_H_

#include "reduction_pass.h"

namespace spvtools {
namespace reduce {

// A reduction pass for removing OpName instructions. As well as making the
// module smaller, removing an OpName instruction may create opportunities to
// remove the instruction that create the id to which the OpName applies.
class RemoveOpNameInstructionReductionPass : public ReductionPass {
public:
// Creates the reduction pass in the context of the given target environment
// |target_env|
explicit RemoveOpNameInstructionReductionPass(const spv_target_env target_env)
: ReductionPass(target_env) {}

~RemoveOpNameInstructionReductionPass() override = default;

// The name of this pass.
std::string GetName() const final;

protected:
// Finds all opportunities for removing opName instructions in the
// given module.
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
opt::IRContext* context) const final;

private:
};

} // namespace reduce
} // namespace spvtools

#endif // SOURCE_REDUCE_REMOVE_OpName_INSTRUCTION_REDUCTION_PASS_H_
1 change: 1 addition & 0 deletions test/reduce/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ add_spvtools_unittest(TARGET reduce
reduce_test_util.cpp
reduce_test_util.h
reducer_test.cpp
remove_opname_instruction_reduction_pass_test.cpp
remove_unreferenced_instruction_reduction_pass_test.cpp
structured_loop_to_selection_reduction_pass_test.cpp
LIBS SPIRV-Tools-reduce
Expand Down
74 changes: 73 additions & 1 deletion test/reduce/reducer_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "source/reduce/operand_to_const_reduction_pass.h"
#include "source/reduce/reducer.h"
#include "source/reduce/remove_opname_instruction_reduction_pass.h"
#include "source/reduce/remove_unreferenced_instruction_reduction_pass.h"

namespace spvtools {
Expand All @@ -27,7 +28,7 @@ void NopDiagnostic(spv_message_level_t /*level*/, const char* /*source*/,
const spv_position_t& /*position*/,
const char* /*message*/) {}

// This changes is its mind each time IsInteresting is invoked as to whether the
// This changes its mind each time IsInteresting is invoked as to whether the
// binary is interesting, until some limit is reached after which the binary is
// always deemed interesting. This is useful to test that reduction passes
// interleave in interesting ways for a while, and then always succeed after
Expand Down Expand Up @@ -238,6 +239,77 @@ TEST(ReducerTest, ExprToConstantAndRemoveUnreferenced) {
CheckEqual(env, expected, binary_out);
}

TEST(ReducerTest, RemoveOpnameAndRemoveUnreferenced) {
const std::string original = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %2 "main"
OpExecutionMode %2 OriginUpperLeft
OpSource ESSL 310
OpName %2 "main"
OpName %3 "a"
OpName %4 "this-name-counts-as-usage-for-load-instruction"
%5 = OpTypeVoid
%6 = OpTypeFunction %5
%7 = OpTypeFloat 32
%8 = OpTypePointer Function %7
%9 = OpConstant %7 1
%2 = OpFunction %5 None %6
%10 = OpLabel
%3 = OpVariable %8 Function
%4 = OpLoad %7 %3
OpStore %3 %7
OpReturn
OpFunctionEnd
)";

const std::string expected = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %2 "main"
OpExecutionMode %2 OriginUpperLeft
OpSource ESSL 310
%5 = OpTypeVoid
%6 = OpTypeFunction %5
%7 = OpTypeFloat 32
%8 = OpTypePointer Function %7
%9 = OpConstant %7 1
%2 = OpFunction %5 None %6
%10 = OpLabel
OpReturn
OpFunctionEnd
)";

spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
Reducer reducer(env);
// Make ping-pong interesting very quickly, as there are not much
// opportunities.
PingPongInteresting ping_pong_interesting(1);
reducer.SetMessageConsumer(NopDiagnostic);
reducer.SetInterestingnessFunction(
[&](const std::vector<uint32_t>& binary, uint32_t) -> bool {
return ping_pong_interesting.IsInteresting(binary);
});
reducer.AddReductionPass(
MakeUnique<RemoveOpNameInstructionReductionPass>(env));
reducer.AddReductionPass(
MakeUnique<RemoveUnreferencedInstructionReductionPass>(env));

std::vector<uint32_t> binary_in;
SpirvTools t(env);

ASSERT_TRUE(t.Assemble(original, &binary_in, kReduceAssembleOption));
std::vector<uint32_t> binary_out;
spvtools::ReducerOptions reducer_options;
reducer_options.set_step_limit(500);

reducer.Run(std::move(binary_in), &binary_out, reducer_options);

CheckEqual(env, expected, binary_out);
}

} // namespace
} // namespace reduce
} // namespace spvtools
Loading

0 comments on commit 4aeadc0

Please sign in to comment.