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
diff --git a/Android.mk b/Android.mk
index a0cf5e8..e2afc82 100644
--- a/Android.mk
+++ b/Android.mk
@@ -119,6 +119,7 @@
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 \
diff --git a/include/spirv-tools/optimizer.hpp b/include/spirv-tools/optimizer.hpp
index bedf436..03eb1c2 100644
--- a/include/spirv-tools/optimizer.hpp
+++ b/include/spirv-tools/optimizer.hpp
@@ -133,6 +133,13 @@
// 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
diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt
index 854c950..4121f7c 100644
--- a/source/opt/CMakeLists.txt
+++ b/source/opt/CMakeLists.txt
@@ -80,6 +80,7 @@
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 @@
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
diff --git a/source/opt/optimizer.cpp b/source/opt/optimizer.cpp
index b897a77..ba8961b 100644
--- a/source/opt/optimizer.cpp
+++ b/source/opt/optimizer.cpp
@@ -220,6 +220,11 @@
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>());
diff --git a/source/opt/passes.h b/source/opt/passes.h
index f0fb289..04f3123 100644
--- a/source/opt/passes.h
+++ b/source/opt/passes.h
@@ -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_
diff --git a/source/opt/strip_reflect_info_pass.cpp b/source/opt/strip_reflect_info_pass.cpp
new file mode 100644
index 0000000..d863e66
--- /dev/null
+++ b/source/opt/strip_reflect_info_pass.cpp
@@ -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
diff --git a/source/opt/strip_reflect_info_pass.h b/source/opt/strip_reflect_info_pass.h
new file mode 100644
index 0000000..b6e9f33
--- /dev/null
+++ b/source/opt/strip_reflect_info_pass.h
@@ -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_
diff --git a/test/opt/CMakeLists.txt b/test/opt/CMakeLists.txt
index 6029e8e..66eae1a 100644
--- a/test/opt/CMakeLists.txt
+++ b/test/opt/CMakeLists.txt
@@ -46,6 +46,11 @@
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
diff --git a/test/opt/strip_reflect_info_test.cpp b/test/opt/strip_reflect_info_test.cpp
new file mode 100644
index 0000000..3cf2cdc
--- /dev/null
+++ b/test/opt/strip_reflect_info_test.cpp
@@ -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
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index ca63c19..ccfbd0b 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -278,6 +278,9 @@
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 @@
}
} 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 =