From 82b378d671836b51343b010ca9ec32db14485147 Mon Sep 17 00:00:00 2001 From: Junda Liu Date: Fri, 30 Oct 2020 04:38:56 +0800 Subject: [PATCH] spirv-opt: Add support to prevent functions from being inlined if they have DontInline flag (#3858) This commit add support for optimizer to not inline functions with DontInline control flag, so that the [noinline] attribute in HLSL will be useful in DXC SPIR-V generation. This is part of work of github.com/microsoft/DirectXShaderCompiler/issues/3158 --- source/opt/function.h | 3 +++ source/opt/inline_pass.cpp | 6 ++++++ test/opt/inline_test.cpp | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/source/opt/function.h b/source/opt/function.h index b7c17a6b2..4b20dcb9b 100644 --- a/source/opt/function.h +++ b/source/opt/function.h @@ -94,6 +94,9 @@ class Function { // Returns function's return type id inline uint32_t type_id() const { return def_inst_->type_id(); } + // Returns the function's control mask + inline uint32_t control_mask() const { return def_inst_->GetSingleWordInOperand(0); } + // Returns the entry basic block for this function. const std::unique_ptr& entry() const { return blocks_.front(); } diff --git a/source/opt/inline_pass.cpp b/source/opt/inline_pass.cpp index 6021a7c53..eaf29aa05 100644 --- a/source/opt/inline_pass.cpp +++ b/source/opt/inline_pass.cpp @@ -727,6 +727,12 @@ void InlinePass::AnalyzeReturns(Function* func) { bool InlinePass::IsInlinableFunction(Function* func) { // We can only inline a function if it has blocks. if (func->cbegin() == func->cend()) return false; + + // Do not inline functions with DontInline flag. + if (func->control_mask() & SpvFunctionControlDontInlineMask) { + return false; + } + // Do not inline functions with returns in loops. Currently early return // functions are inlined by wrapping them in a one trip loop and implementing // the returns as a branch to the loop's merge block. However, this can only diff --git a/test/opt/inline_test.cpp b/test/opt/inline_test.cpp index 951721bfa..c0ca6da7f 100644 --- a/test/opt/inline_test.cpp +++ b/test/opt/inline_test.cpp @@ -2405,6 +2405,38 @@ OpFunctionEnd SinglePassRunAndCheck(test, test, false, true); } +TEST_F(InlineTest, DontInlineFuncWithDontInline) { + // Check that the function with DontInline flag is not inlined. + const std::string text = R"( +; CHECK: %foo = OpFunction %int DontInline +; CHECK: OpReturnValue %int_0 + +OpCapability Shader +OpMemoryModel Logical GLSL450 +OpEntryPoint Fragment %main "main" +OpExecutionMode %main OriginUpperLeft +OpSource HLSL 600 +OpName %main "main" +OpName %foo "foo" +%int = OpTypeInt 32 1 +%int_0 = OpConstant %int 0 +%void = OpTypeVoid +%6 = OpTypeFunction %void +%7 = OpTypeFunction %int +%main = OpFunction %void None %6 +%8 = OpLabel +%9 = OpFunctionCall %int %foo +OpReturn +OpFunctionEnd +%foo = OpFunction %int DontInline %7 +%10 = OpLabel +OpReturnValue %int_0 +OpFunctionEnd +)"; + + SinglePassRunAndMatch(text, true); +} + TEST_F(InlineTest, InlineFuncWithOpKillNotInContinue) { const std::string before = R"(OpCapability Shader