mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 19:20:05 +00:00
Add undef for inlined void function (#3720)
It is possible that the result of a void function call is used. In case it is used, we need something that still defines its id after inlining. We use an undef for that purpose. Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/3704
This commit is contained in:
parent
4dd122392f
commit
3f8501de9e
@ -619,6 +619,14 @@ bool InlinePass::GenInlineCode(
|
||||
assert(resId != 0);
|
||||
AddLoad(calleeTypeId, resId, returnVarId, &new_blk_ptr,
|
||||
call_inst_itr->dbg_line_inst(), call_inst_itr->GetDebugScope());
|
||||
} else {
|
||||
// Even though it is very unlikely, it is possible that the result id of
|
||||
// the void-function call is used, so we need to generate an instruction
|
||||
// with that result id.
|
||||
std::unique_ptr<Instruction> undef_inst(
|
||||
new Instruction(context(), SpvOpUndef, call_inst_itr->type_id(),
|
||||
call_inst_itr->result_id(), {}));
|
||||
context()->AddGlobalValue(std::move(undef_inst));
|
||||
}
|
||||
|
||||
// Move instructions of original caller block after call instruction.
|
||||
|
@ -90,7 +90,8 @@ OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%main = OpFunction %void None %12
|
||||
R"(%34 = OpUndef %void
|
||||
%main = OpFunction %void None %12
|
||||
%28 = OpLabel
|
||||
%s0 = OpVariable %_ptr_Function_S_t Function
|
||||
%param = OpVariable %_ptr_Function_S_t Function
|
||||
@ -289,7 +290,8 @@ OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%main2 = OpFunction %void None %13
|
||||
R"(%35 = OpUndef %void
|
||||
%main2 = OpFunction %void None %13
|
||||
%29 = OpLabel
|
||||
%s0 = OpVariable %_ptr_Function_S_t Function
|
||||
%param = OpVariable %_ptr_Function_S_t Function
|
||||
|
@ -381,6 +381,7 @@ TEST_F(InlineTest, InOutParameter) {
|
||||
|
||||
const std::vector<const char*> after = {
|
||||
// clang-format off
|
||||
"%26 = OpUndef %void",
|
||||
"%main = OpFunction %void None %11",
|
||||
"%23 = OpLabel",
|
||||
"%b = OpVariable %_ptr_Function_v4float Function",
|
||||
@ -1503,11 +1504,11 @@ OpSource OpenCL_C 120
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
)";
|
||||
|
||||
const std::string nonEntryFuncs =
|
||||
R"(%5 = OpTypeFunction %void
|
||||
%6 = OpFunction %void None %5
|
||||
R"(%6 = OpFunction %void None %5
|
||||
%7 = OpLabel
|
||||
OpBranch %8
|
||||
%8 = OpLabel
|
||||
@ -1542,9 +1543,11 @@ OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before,
|
||||
predefs + nonEntryFuncs + after,
|
||||
false, true);
|
||||
const std::string undef = "%11 = OpUndef %void\n";
|
||||
|
||||
SinglePassRunAndCheck<InlineExhaustivePass>(
|
||||
predefs + nonEntryFuncs + before, predefs + undef + nonEntryFuncs + after,
|
||||
false, true);
|
||||
}
|
||||
|
||||
TEST_F(InlineTest, MultiBlockLoopHeaderCallsMultiBlockCallee) {
|
||||
@ -1619,9 +1622,10 @@ OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before,
|
||||
predefs + nonEntryFuncs + after,
|
||||
false, true);
|
||||
const std::string undef = "%20 = OpUndef %void\n";
|
||||
SinglePassRunAndCheck<InlineExhaustivePass>(
|
||||
predefs + nonEntryFuncs + before, predefs + undef + nonEntryFuncs + after,
|
||||
false, true);
|
||||
}
|
||||
|
||||
TEST_F(InlineTest, SingleBlockLoopCallsMultiBlockCalleeHavingSelectionMerge) {
|
||||
@ -1707,10 +1711,10 @@ OpBranchConditional %true %13 %16
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before,
|
||||
predefs + nonEntryFuncs + after,
|
||||
false, true);
|
||||
const std::string undef = "%15 = OpUndef %void\n";
|
||||
SinglePassRunAndCheck<InlineExhaustivePass>(
|
||||
predefs + nonEntryFuncs + before, predefs + undef + nonEntryFuncs + after,
|
||||
false, true);
|
||||
}
|
||||
|
||||
TEST_F(InlineTest,
|
||||
@ -1789,9 +1793,10 @@ OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before,
|
||||
predefs + nonEntryFuncs + after,
|
||||
false, true);
|
||||
const std::string undef = "%20 = OpUndef %void\n";
|
||||
SinglePassRunAndCheck<InlineExhaustivePass>(
|
||||
predefs + nonEntryFuncs + before, predefs + undef + nonEntryFuncs + after,
|
||||
false, true);
|
||||
}
|
||||
|
||||
TEST_F(InlineTest, NonInlinableCalleeWithSingleReturn) {
|
||||
@ -2164,6 +2169,7 @@ OpName %foo "foo"
|
||||
OpName %foo_entry "foo_entry"
|
||||
%void = OpTypeVoid
|
||||
%void_fn = OpTypeFunction %void
|
||||
%3 = OpUndef %void
|
||||
%foo = OpFunction %void None %void_fn
|
||||
%foo_entry = OpLabel
|
||||
OpReturn
|
||||
@ -2437,6 +2443,7 @@ OpName %kill_ "kill("
|
||||
%3 = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
%16 = OpUndef %void
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpKill
|
||||
@ -2534,6 +2541,7 @@ OpName %kill_ "kill("
|
||||
%3 = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
%16 = OpUndef %void
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpTerminateInvocation
|
||||
@ -2761,6 +2769,7 @@ OpFunctionEnd
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%false = OpConstantFalse %bool
|
||||
%_ptr_Function_bool = OpTypePointer Function %bool
|
||||
%11 = OpUndef %void
|
||||
%foo_ = OpFunction %void None %4
|
||||
%7 = OpLabel
|
||||
%18 = OpVariable %_ptr_Function_bool Function %false
|
||||
@ -3849,6 +3858,35 @@ OpFunctionEnd
|
||||
SinglePassRunAndMatch<InlineExhaustivePass>(text, true);
|
||||
}
|
||||
|
||||
TEST_F(InlineTest, UsingVoidFunctionResult) {
|
||||
const std::string text = R"(
|
||||
; CHECK: [[undef:%\w+]] = OpUndef %void
|
||||
; CHECK: OpFunction
|
||||
; CHECK: OpCopyObject %void [[undef]]
|
||||
; CHECK: OpFunctionEnd
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main"
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 320
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
%8 = OpFunctionCall %2 %6
|
||||
%9 = OpCopyObject %2 %8
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%6 = OpFunction %2 None %3
|
||||
%7 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndMatch<InlineExhaustivePass>(text, true);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// Empty modules
|
||||
|
Loading…
Reference in New Issue
Block a user