Add --strip-reflect pass

Strips reflection info. This is limited to decorations and
decoration instructions related to the SPV_GOOGLE_hlsl_functionality1
extension.
It will remove the OpExtension for SPV_GOOGLE_hlsl_functionality1.
It will also remove the OpExtension for SPV_GOOGLE_decorate_string
if there are no further remaining uses of OpDecorateStringGOOGLE.

Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/1398
This commit is contained in:
David Neto 2018-03-09 16:08:57 -05:00 committed by Lei Zhang
parent 2e3aec23ca
commit 844e186cf7
10 changed files with 210 additions and 0 deletions

View File

@ -119,6 +119,7 @@ SPVTOOLS_OPT_SRC_FILES := \
source/opt/simplification_pass.cpp \
source/opt/strength_reduction_pass.cpp \
source/opt/strip_debug_info_pass.cpp \
source/opt/strip_reflect_info_pass.cpp \
source/opt/type_manager.cpp \
source/opt/types.cpp \
source/opt/unify_const_pass.cpp \

View File

@ -133,6 +133,13 @@ Optimizer::PassToken CreateNullPass();
// Section 3.32.2 of the SPIR-V spec) of the SPIR-V module to be optimized.
Optimizer::PassToken CreateStripDebugInfoPass();
// Creates a strip-reflect-info pass.
// A strip-reflect-info pass removes all reflections instructions.
// For now, this is limited to removing decorations defined in
// SPV_GOOGLE_hlsl_functionality1. The coverage may expand in
// the future.
Optimizer::PassToken CreateStripReflectInfoPass();
// Creates an eliminate-dead-functions pass.
// An eliminate-dead-functions pass will remove all functions that are not in
// the call trees rooted at entry points and exported functions. These

View File

@ -80,6 +80,7 @@ add_library(SPIRV-Tools-opt
simplification_pass.h
strength_reduction_pass.h
strip_debug_info_pass.h
strip_reflect_info_pass.h
tree_iterator.h
type_manager.h
types.h
@ -150,6 +151,7 @@ add_library(SPIRV-Tools-opt
simplification_pass.cpp
strength_reduction_pass.cpp
strip_debug_info_pass.cpp
strip_reflect_info_pass.cpp
type_manager.cpp
types.cpp
unify_const_pass.cpp

View File

@ -220,6 +220,11 @@ Optimizer::PassToken CreateStripDebugInfoPass() {
MakeUnique<opt::StripDebugInfoPass>());
}
Optimizer::PassToken CreateStripReflectInfoPass() {
return MakeUnique<Optimizer::PassToken::Impl>(
MakeUnique<opt::StripReflectInfoPass>());
}
Optimizer::PassToken CreateEliminateDeadFunctionsPass() {
return MakeUnique<Optimizer::PassToken::Impl>(
MakeUnique<opt::EliminateDeadFunctionsPass>());

View File

@ -53,6 +53,7 @@
#include "set_spec_constant_default_value_pass.h"
#include "strength_reduction_pass.h"
#include "strip_debug_info_pass.h"
#include "strip_reflect_info_pass.h"
#include "unify_const_pass.h"
#include "workaround1209.h"
#endif // LIBSPIRV_OPT_PASSES_H_

View File

@ -0,0 +1,75 @@
// 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 "strip_reflect_info_pass.h"
#include <cstring>
#include "instruction.h"
#include "ir_context.h"
namespace spvtools {
namespace opt {
using spvtools::ir::Instruction;
Pass::Status StripReflectInfoPass::Process(ir::IRContext* irContext) {
bool modified = false;
std::vector<Instruction*> to_remove;
bool other_uses_for_decorate_string = false;
for (auto& inst : irContext->module()->annotations()) {
switch (inst.opcode()) {
case SpvOpDecorateStringGOOGLE:
if (inst.GetSingleWordInOperand(1) == SpvDecorationHlslSemanticGOOGLE) {
to_remove.push_back(&inst);
} else {
other_uses_for_decorate_string = true;
}
break;
case SpvOpDecorateId:
if (inst.GetSingleWordInOperand(1) ==
SpvDecorationHlslCounterBufferGOOGLE) {
to_remove.push_back(&inst);
}
break;
default:
break;
}
}
for (auto& inst : irContext->module()->extensions()) {
const char* ext_name =
reinterpret_cast<const char*>(&inst.GetInOperand(0).words[0]);
if (0 == std::strcmp(ext_name, "SPV_GOOGLE_hlsl_functionality1")) {
to_remove.push_back(&inst);
} else if (!other_uses_for_decorate_string &&
0 == std::strcmp(ext_name, "SPV_GOOGLE_decorate_string")) {
to_remove.push_back(&inst);
}
}
for (auto* inst : to_remove) {
modified = true;
irContext->KillInst(inst);
}
return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
}
} // namespace opt
} // namespace spvtools

View File

@ -0,0 +1,44 @@
// 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 LIBSPIRV_OPT_STRIP_REFLECT_INFO_PASS_H_
#define LIBSPIRV_OPT_STRIP_REFLECT_INFO_PASS_H_
#include "ir_context.h"
#include "module.h"
#include "pass.h"
namespace spvtools {
namespace opt {
// See optimizer.hpp for documentation.
class StripReflectInfoPass : public Pass {
public:
const char* name() const override { return "strip-reflect"; }
Status Process(ir::IRContext* irContext) override;
// Return the mask of preserved Analyses.
ir::IRContext::Analysis GetPreservedAnalyses() override {
return ir::IRContext::kAnalysisInstrToBlockMapping |
ir::IRContext::kAnalysisCombinators | ir::IRContext::kAnalysisCFG |
ir::IRContext::kAnalysisDominatorAnalysis |
ir::IRContext::kAnalysisLoopAnalysis |
ir::IRContext::kAnalysisNameMap;
}
};
} // namespace opt
} // namespace spvtools
#endif // LIBSPIRV_OPT_STRIP_REFLECT_INFO_PASS_H_

View File

@ -46,6 +46,11 @@ add_spvtools_unittest(TARGET pass_strip_debug_info
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_strip_reflect_info
SRCS strip_reflect_info_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_compact_ids
SRCS compact_ids_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt

View File

@ -0,0 +1,65 @@
// 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 "pass_fixture.h"
#include "pass_utils.h"
namespace {
using namespace spvtools;
using StripLineReflectInfoTest = PassTest<::testing::Test>;
TEST_F(StripLineReflectInfoTest, StripHlslSemantic) {
// This is a non-sensical example, but exercises the instructions.
std::string before = R"(OpCapability Shader
OpCapability Linkage
OpExtension "SPV_GOOGLE_decorate_string"
OpExtension "SPV_GOOGLE_hlsl_functionality1"
OpMemoryModel Logical Simple
OpDecorateStringGOOGLE %float HlslSemanticGOOGLE "foobar"
OpDecorateStringGOOGLE %void HlslSemanticGOOGLE "my goodness"
%void = OpTypeVoid
%float = OpTypeFloat 32
)";
std::string after = R"(OpCapability Shader
OpCapability Linkage
OpMemoryModel Logical Simple
%void = OpTypeVoid
%float = OpTypeFloat 32
)";
SinglePassRunAndCheck<opt::StripReflectInfoPass>(before, after, false);
}
TEST_F(StripLineReflectInfoTest, StripHlslCounterBuffer) {
std::string before = R"(OpCapability Shader
OpCapability Linkage
OpExtension "SPV_GOOGLE_hlsl_functionality1"
OpMemoryModel Logical Simple
OpDecorateId %void HlslCounterBufferGOOGLE %float
%void = OpTypeVoid
%float = OpTypeFloat 32
)";
std::string after = R"(OpCapability Shader
OpCapability Linkage
OpMemoryModel Logical Simple
%void = OpTypeVoid
%float = OpTypeFloat 32
)";
SinglePassRunAndCheck<opt::StripReflectInfoPass>(before, after, false);
}
} // anonymous namespace

View File

@ -278,6 +278,9 @@ Options (in lexicographical order):
Replaces instructions with equivalent and less expensive ones.
--strip-debug
Remove all debug instructions.
--strip-reflect
Remove all reflection information. For now, this covers
reflection information defined by SPV_GOOGLE_hlsl_functionality1.
--workaround-1209
Rewrites instructions for which there are known driver bugs to
avoid triggering those bugs.
@ -411,6 +414,8 @@ OptStatus ParseFlags(int argc, const char** argv, Optimizer* optimizer,
}
} else if (0 == strcmp(cur_arg, "--strip-debug")) {
optimizer->RegisterPass(CreateStripDebugInfoPass());
} else if (0 == strcmp(cur_arg, "--strip-reflect")) {
optimizer->RegisterPass(CreateStripReflectInfoPass());
} else if (0 == strcmp(cur_arg, "--set-spec-const-default-value")) {
if (++argi < argc) {
auto spec_ids_vals =