diff options
author | Steven Perron <stevenperron@google.com> | 2022-03-07 17:45:17 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-07 12:45:17 -0500 |
commit | 920156cf183baa11f6b65d159da6fba9fdab684e (patch) | |
tree | 712531eb825661f1eae11741e098fe7066120278 | |
parent | 273d2a45adda86c0a4299032dc9e71b270373739 (diff) | |
download | spirv-tools-920156cf183baa11f6b65d159da6fba9fdab684e.tar.gz |
Add pass to remove DontInline function control (#4747)
Swift shader needs a way to inline all functions, even those marked as
DontInline. See https://github.com/KhronosGroup/SPIRV-Tools/pull/4471.
This implements the suggestion I made in the PR. We add a pass that
will remove the DontInline function control, so that the inlining passes
will inline them.
SwiftShader will still have to modify their code to add this pass before
the other passes are run.
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | BUILD.gn | 2 | ||||
-rw-r--r-- | include/spirv-tools/optimizer.hpp | 4 | ||||
-rw-r--r-- | source/opt/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/opt/optimizer.cpp | 6 | ||||
-rw-r--r-- | source/opt/passes.h | 1 | ||||
-rw-r--r-- | source/opt/remove_dontinline_pass.cpp | 49 | ||||
-rw-r--r-- | source/opt/remove_dontinline_pass.h | 42 | ||||
-rw-r--r-- | test/opt/CMakeLists.txt | 1 | ||||
-rw-r--r-- | test/opt/remove_dontinline_test.cpp | 127 |
10 files changed, 235 insertions, 0 deletions
@@ -156,6 +156,7 @@ SPVTOOLS_OPT_SRC_FILES := \ source/opt/redundancy_elimination.cpp \ source/opt/register_pressure.cpp \ source/opt/relax_float_ops_pass.cpp \ + source/opt/remove_dontinline_pass.cpp \ source/opt/remove_duplicates_pass.cpp \ source/opt/remove_unused_interface_variables_pass.cpp \ source/opt/replace_desc_array_access_using_var_index.cpp \ @@ -716,6 +716,8 @@ static_library("spvtools_opt") { "source/opt/register_pressure.h", "source/opt/relax_float_ops_pass.cpp", "source/opt/relax_float_ops_pass.h", + "source/opt/remove_dontinline_pass.cpp", + "source/opt/remove_dontinline_pass.h", "source/opt/remove_duplicates_pass.cpp", "source/opt/remove_duplicates_pass.h", "source/opt/remove_unused_interface_variables_pass.cpp", diff --git a/include/spirv-tools/optimizer.hpp b/include/spirv-tools/optimizer.hpp index fdb2e648..2273e85d 100644 --- a/include/spirv-tools/optimizer.hpp +++ b/include/spirv-tools/optimizer.hpp @@ -896,6 +896,10 @@ Optimizer::PassToken CreateConvertToSampledImagePass( const std::vector<opt::DescriptorSetAndBinding>& descriptor_set_binding_pairs); +// Creates a remove-dont-inline pass to remove the |DontInline| function control +// from every function in the module. This is useful if you want the inliner to +// inline these functions some reason. +Optimizer::PassToken CreateRemoveDontInlinePass(); } // namespace spvtools #endif // INCLUDE_SPIRV_TOOLS_OPTIMIZER_HPP_ diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt index 7508dc02..05c02fcd 100644 --- a/source/opt/CMakeLists.txt +++ b/source/opt/CMakeLists.txt @@ -99,6 +99,7 @@ set(SPIRV_TOOLS_OPT_SOURCES reflect.h register_pressure.h relax_float_ops_pass.h + remove_dontinline_pass.h remove_duplicates_pass.h remove_unused_interface_variables_pass.h replace_desc_array_access_using_var_index.h @@ -207,6 +208,7 @@ set(SPIRV_TOOLS_OPT_SOURCES redundancy_elimination.cpp register_pressure.cpp relax_float_ops_pass.cpp + remove_dontinline_pass.cpp remove_duplicates_pass.cpp remove_unused_interface_variables_pass.cpp replace_desc_array_access_using_var_index.cpp diff --git a/source/opt/optimizer.cpp b/source/opt/optimizer.cpp index 330093e4..ec2c8ea2 100644 --- a/source/opt/optimizer.cpp +++ b/source/opt/optimizer.cpp @@ -521,6 +521,8 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) { RegisterPass(CreateAmdExtToKhrPass()); } else if (pass_name == "interpolate-fixup") { RegisterPass(CreateInterpolateFixupPass()); + } else if (pass_name == "remove-dont-inline") { + RegisterPass(CreateRemoveDontInlinePass()); } else if (pass_name == "convert-to-sampled-image") { if (pass_args.size() > 0) { auto descriptor_set_binding_pairs = @@ -1009,4 +1011,8 @@ Optimizer::PassToken CreateConvertToSampledImagePass( MakeUnique<opt::ConvertToSampledImagePass>(descriptor_set_binding_pairs)); } +Optimizer::PassToken CreateRemoveDontInlinePass() { + return MakeUnique<Optimizer::PassToken::Impl>( + MakeUnique<opt::RemoveDontInline>()); +} } // namespace spvtools diff --git a/source/opt/passes.h b/source/opt/passes.h index d51c306e..26739cdc 100644 --- a/source/opt/passes.h +++ b/source/opt/passes.h @@ -64,6 +64,7 @@ #include "source/opt/reduce_load_size.h" #include "source/opt/redundancy_elimination.h" #include "source/opt/relax_float_ops_pass.h" +#include "source/opt/remove_dontinline_pass.h" #include "source/opt/remove_duplicates_pass.h" #include "source/opt/remove_unused_interface_variables_pass.h" #include "source/opt/replace_desc_array_access_using_var_index.h" diff --git a/source/opt/remove_dontinline_pass.cpp b/source/opt/remove_dontinline_pass.cpp new file mode 100644 index 00000000..4dd1cd4f --- /dev/null +++ b/source/opt/remove_dontinline_pass.cpp @@ -0,0 +1,49 @@ +// Copyright (c) 2022 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/opt/remove_dontinline_pass.h" + +namespace spvtools { +namespace opt { + +Pass::Status RemoveDontInline::Process() { + bool modified = false; + modified = ClearDontInlineFunctionControl(); + return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange); +} + +bool RemoveDontInline::ClearDontInlineFunctionControl() { + bool modified = false; + for (auto& func : *get_module()) { + ClearDontInlineFunctionControl(&func); + } + return modified; +} + +bool RemoveDontInline::ClearDontInlineFunctionControl(Function* function) { + constexpr uint32_t kFunctionControlInOperandIdx = 0; + Instruction* function_inst = &function->DefInst(); + uint32_t function_control = + function_inst->GetSingleWordInOperand(kFunctionControlInOperandIdx); + + if ((function_control & SpvFunctionControlDontInlineMask) == 0) { + return false; + } + function_control &= ~SpvFunctionControlDontInlineMask; + function_inst->SetInOperand(kFunctionControlInOperandIdx, {function_control}); + return true; +} + +} // namespace opt +} // namespace spvtools diff --git a/source/opt/remove_dontinline_pass.h b/source/opt/remove_dontinline_pass.h new file mode 100644 index 00000000..16243199 --- /dev/null +++ b/source/opt/remove_dontinline_pass.h @@ -0,0 +1,42 @@ +// Copyright (c) 2022 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_OPT_REMOVE_DONTINLINE_PASS_H_ +#define SOURCE_OPT_REMOVE_DONTINLINE_PASS_H_ + +#include "source/opt/pass.h" + +namespace spvtools { +namespace opt { + +// See optimizer.hpp for documentation. +class RemoveDontInline : public Pass { + public: + const char* name() const override { return "remove-dont-inline"; } + Status Process() override; + + private: + // Clears the DontInline function control from every function in the module. + // Returns true of a change was made. + bool ClearDontInlineFunctionControl(); + + // Clears the DontInline function control from |function|. + // Returns true of a change was made. + bool ClearDontInlineFunctionControl(Function* function); +}; + +} // namespace opt +} // namespace spvtools + +#endif // SOURCE_OPT_REMOVE_DONTINLINE_PASS_H_ diff --git a/test/opt/CMakeLists.txt b/test/opt/CMakeLists.txt index 759d4237..f50fddad 100644 --- a/test/opt/CMakeLists.txt +++ b/test/opt/CMakeLists.txt @@ -82,6 +82,7 @@ add_spvtools_unittest(TARGET opt propagator_test.cpp reduce_load_size_test.cpp redundancy_elimination_test.cpp + remove_dontinline_test.cpp remove_unused_interface_variables_test.cpp register_liveness.cpp relax_float_ops_test.cpp diff --git a/test/opt/remove_dontinline_test.cpp b/test/opt/remove_dontinline_test.cpp new file mode 100644 index 00000000..c5425e8c --- /dev/null +++ b/test/opt/remove_dontinline_test.cpp @@ -0,0 +1,127 @@ +// Copyright (c) 2017 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 <vector> + +#include "test/opt/pass_fixture.h" +#include "test/opt/pass_utils.h" + +namespace spvtools { +namespace opt { +namespace { + +using StrengthReductionBasicTest = PassTest<::testing::Test>; + +TEST_F(StrengthReductionBasicTest, ClearDontInline) { + const std::vector<const char*> text = { + // clang-format off + "OpCapability Shader", + "%1 = OpExtInstImport \"GLSL.std.450\"", + "OpMemoryModel Logical GLSL450", + "OpEntryPoint Vertex %main \"main\"", + "%void = OpTypeVoid", + "%4 = OpTypeFunction %void", +"; CHECK: OpFunction %void None", + "%main = OpFunction %void DontInline %4", + "%8 = OpLabel", + "OpReturn", + "OpFunctionEnd" + // clang-format on + }; + + SinglePassRunAndMatch<RemoveDontInline>(JoinAllInsts(text), true); +} + +TEST_F(StrengthReductionBasicTest, LeaveUnchanged1) { + const std::vector<const char*> text = { + // clang-format off + "OpCapability Shader", + "%1 = OpExtInstImport \"GLSL.std.450\"", + "OpMemoryModel Logical GLSL450", + "OpEntryPoint Vertex %main \"main\"", + "%void = OpTypeVoid", + "%4 = OpTypeFunction %void", + "%main = OpFunction %void None %4", + "%8 = OpLabel", + "OpReturn", + "OpFunctionEnd" + // clang-format on + }; + + EXPECT_EQ(Pass::Status::SuccessWithoutChange, + std::get<1>(SinglePassRunAndDisassemble<RemoveDontInline>( + JoinAllInsts(text), false, true))); +} + +TEST_F(StrengthReductionBasicTest, LeaveUnchanged2) { + const std::vector<const char*> text = { + // clang-format off + "OpCapability Shader", + "%1 = OpExtInstImport \"GLSL.std.450\"", + "OpMemoryModel Logical GLSL450", + "OpEntryPoint Vertex %main \"main\"", + "%void = OpTypeVoid", + "%4 = OpTypeFunction %void", + "%main = OpFunction %void Inline %4", + "%8 = OpLabel", + "OpReturn", + "OpFunctionEnd" + // clang-format on + }; + + EXPECT_EQ(Pass::Status::SuccessWithoutChange, + std::get<1>(SinglePassRunAndDisassemble<RemoveDontInline>( + JoinAllInsts(text), false, true))); +} + +TEST_F(StrengthReductionBasicTest, ClearMultipleDontInline) { + const std::vector<const char*> text = { + // clang-format off + "OpCapability Shader", + "%1 = OpExtInstImport \"GLSL.std.450\"", + "OpMemoryModel Logical GLSL450", + "OpEntryPoint Vertex %main1 \"main1\"", + "OpEntryPoint Vertex %main2 \"main2\"", + "OpEntryPoint Vertex %main3 \"main3\"", + "OpEntryPoint Vertex %main4 \"main4\"", + "%void = OpTypeVoid", + "%4 = OpTypeFunction %void", + "; CHECK: OpFunction %void None", + "%main1 = OpFunction %void DontInline %4", + "%8 = OpLabel", + "OpReturn", + "OpFunctionEnd", + "; CHECK: OpFunction %void Inline", + "%main2 = OpFunction %void Inline %4", + "%9 = OpLabel", + "OpReturn", + "OpFunctionEnd", + "; CHECK: OpFunction %void Pure", + "%main3 = OpFunction %void DontInline|Pure %4", + "%10 = OpLabel", + "OpReturn", + "OpFunctionEnd", + "; CHECK: OpFunction %void None", + "%main4 = OpFunction %void None %4", + "%11 = OpLabel", + "OpReturn", + "OpFunctionEnd" + // clang-format on + }; + + SinglePassRunAndMatch<RemoveDontInline>(JoinAllInsts(text), true); +} +} // namespace +} // namespace opt +} // namespace spvtools |