diff --git a/Android.mk b/Android.mk index a0cf5e846..e2afc821f 100644 --- a/Android.mk +++ b/Android.mk @@ -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 \ diff --git a/include/spirv-tools/optimizer.hpp b/include/spirv-tools/optimizer.hpp index bedf436ef..03eb1c293 100644 --- a/include/spirv-tools/optimizer.hpp +++ b/include/spirv-tools/optimizer.hpp @@ -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 diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt index 854c9509c..4121f7c31 100644 --- a/source/opt/CMakeLists.txt +++ b/source/opt/CMakeLists.txt @@ -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 diff --git a/source/opt/optimizer.cpp b/source/opt/optimizer.cpp index b897a7728..ba8961bb6 100644 --- a/source/opt/optimizer.cpp +++ b/source/opt/optimizer.cpp @@ -220,6 +220,11 @@ Optimizer::PassToken CreateStripDebugInfoPass() { MakeUnique()); } +Optimizer::PassToken CreateStripReflectInfoPass() { + return MakeUnique( + MakeUnique()); +} + Optimizer::PassToken CreateEliminateDeadFunctionsPass() { return MakeUnique( MakeUnique()); diff --git a/source/opt/passes.h b/source/opt/passes.h index f0fb289a1..04f3123fd 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 000000000..d863e6600 --- /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 + +#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 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(&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 000000000..b6e9f33fb --- /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 6029e8ea3..66eae1ae4 100644 --- a/test/opt/CMakeLists.txt +++ b/test/opt/CMakeLists.txt @@ -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 diff --git a/test/opt/strip_reflect_info_test.cpp b/test/opt/strip_reflect_info_test.cpp new file mode 100644 index 000000000..3cf2cdce7 --- /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(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(before, after, false); +} + +} // anonymous namespace diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index ca63c1965..ccfbd0b27 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -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 =