Take new (raytracing) termination instructions into account. (#4050)

* Take new (raytracing) termination instructions into account.

* Remove duplicate function and add unit test.

* Use KHR for symbols in the test.
This commit is contained in:
Ehsan 2020-12-07 09:26:05 -06:00 committed by GitHub
parent 21f7c5675d
commit cd05078662
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 89 additions and 14 deletions

View File

@ -444,15 +444,32 @@ bool spvOpcodeIsReturn(SpvOp opcode) {
}
}
bool spvOpcodeIsAbort(SpvOp opcode) {
switch (opcode) {
case SpvOpKill:
case SpvOpUnreachable:
case SpvOpTerminateInvocation:
case SpvOpTerminateRayKHR:
case SpvOpIgnoreIntersectionKHR:
return true;
default:
return false;
}
}
bool spvOpcodeIsReturnOrAbort(SpvOp opcode) {
return spvOpcodeIsReturn(opcode) || opcode == SpvOpKill ||
opcode == SpvOpUnreachable || opcode == SpvOpTerminateInvocation;
return spvOpcodeIsReturn(opcode) || spvOpcodeIsAbort(opcode);
}
bool spvOpcodeIsBlockTerminator(SpvOp opcode) {
return spvOpcodeIsBranch(opcode) || spvOpcodeIsReturnOrAbort(opcode);
}
bool spvOpcodeTerminatesExecution(SpvOp opcode) {
return opcode == SpvOpKill || opcode == SpvOpTerminateInvocation ||
opcode == SpvOpTerminateRayKHR || opcode == SpvOpIgnoreIntersectionKHR;
}
bool spvOpcodeIsBaseOpaqueType(SpvOp opcode) {
switch (opcode) {
case SpvOpTypeImage:

View File

@ -110,10 +110,18 @@ bool spvOpcodeIsBranch(SpvOp opcode);
// Returns true if the given opcode is a return instruction.
bool spvOpcodeIsReturn(SpvOp opcode);
// Returns true if the given opcode aborts execution.
bool spvOpcodeIsAbort(SpvOp opcode);
// Returns true if the given opcode is a return instruction or it aborts
// execution.
bool spvOpcodeIsReturnOrAbort(SpvOp opcode);
// Returns true if the given opcode is a kill instruction or it terminates
// execution. Note that branches, returns, and unreachables do not terminate
// execution.
bool spvOpcodeTerminatesExecution(SpvOp opcode);
// Returns true if the given opcode is a basic block terminator.
bool spvOpcodeIsBlockTerminator(SpvOp opcode);

View File

@ -230,7 +230,7 @@ std::string BasicBlock::PrettyPrint(uint32_t options) const {
std::ostringstream str;
ForEachInst([&str, options](const Instruction* inst) {
str << inst->PrettyPrint(options);
if (!IsTerminatorInst(inst->opcode())) {
if (!spvOpcodeIsBlockTerminator(inst->opcode())) {
str << std::endl;
}
});

View File

@ -383,9 +383,7 @@ std::unique_ptr<BasicBlock> InlinePass::InlineReturn(
uint32_t returnLabelId = 0;
for (auto callee_block_itr = calleeFn->begin();
callee_block_itr != calleeFn->end(); ++callee_block_itr) {
if (callee_block_itr->tail()->opcode() == SpvOpUnreachable ||
callee_block_itr->tail()->opcode() == SpvOpKill ||
callee_block_itr->tail()->opcode() == SpvOpTerminateInvocation) {
if (spvOpcodeIsAbort(callee_block_itr->tail()->opcode())) {
returnLabelId = context()->TakeNextId();
break;
}
@ -759,8 +757,7 @@ bool InlinePass::IsInlinableFunction(Function* func) {
bool InlinePass::ContainsKillOrTerminateInvocation(Function* func) const {
return !func->WhileEachInst([](Instruction* inst) {
const auto opcode = inst->opcode();
return (opcode != SpvOpKill) && (opcode != SpvOpTerminateInvocation);
return !spvOpcodeTerminatesExecution(inst->opcode());
});
}

View File

@ -137,7 +137,7 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
return false;
}
block_ = MakeUnique<BasicBlock>(std::move(spv_inst));
} else if (IsTerminatorInst(opcode)) {
} else if (spvOpcodeIsBlockTerminator(opcode)) {
if (function_ == nullptr) {
Error(consumer_, src, loc, "terminator instruction outside function");
return false;

View File

@ -188,7 +188,7 @@ void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
i->ToBinaryWithoutAttachedDebugInsts(binary);
}
// Update the last line instruction.
if (IsTerminatorInst(opcode) || opcode == SpvOpNoLine) {
if (spvOpcodeIsBlockTerminator(opcode) || opcode == SpvOpNoLine) {
last_line_inst = nullptr;
} else if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
between_merge_and_branch = true;

View File

@ -59,10 +59,6 @@ inline bool IsCompileTimeConstantInst(SpvOp opcode) {
inline bool IsSpecConstantInst(SpvOp opcode) {
return opcode >= SpvOpSpecConstantTrue && opcode <= SpvOpSpecConstantOp;
}
inline bool IsTerminatorInst(SpvOp opcode) {
return (opcode >= SpvOpBranch && opcode <= SpvOpUnreachable) ||
(opcode == SpvOpTerminateInvocation);
}
} // namespace opt
} // namespace spvtools

View File

@ -2581,6 +2581,63 @@ OpFunctionEnd
SinglePassRunAndCheck<InlineExhaustivePass>(before, after, false, true);
}
TEST_F(InlineTest, InlineFuncWithOpTerminateRayNotInContinue) {
const std::string text =
R"(
OpCapability RayTracingKHR
OpExtension "SPV_KHR_ray_tracing"
OpMemoryModel Logical GLSL450
OpEntryPoint AnyHitKHR %MyAHitMain2 "MyAHitMain2" %a
OpSource HLSL 630
OpName %a "a"
OpName %MyAHitMain2 "MyAHitMain2"
OpName %param_var_a "param.var.a"
OpName %src_MyAHitMain2 "src.MyAHitMain2"
OpName %a_0 "a"
OpName %bb_entry "bb.entry"
%int = OpTypeInt 32 1
%_ptr_IncomingRayPayloadKHR_int = OpTypePointer IncomingRayPayloadKHR %int
%void = OpTypeVoid
%6 = OpTypeFunction %void
%_ptr_Function_int = OpTypePointer Function %int
%14 = OpTypeFunction %void %_ptr_Function_int
%a = OpVariable %_ptr_IncomingRayPayloadKHR_int IncomingRayPayloadKHR
%MyAHitMain2 = OpFunction %void None %6
%7 = OpLabel
%param_var_a = OpVariable %_ptr_Function_int Function
%10 = OpLoad %int %a
OpStore %param_var_a %10
%11 = OpFunctionCall %void %src_MyAHitMain2 %param_var_a
%13 = OpLoad %int %param_var_a
OpStore %a %13
OpReturn
OpFunctionEnd
%src_MyAHitMain2 = OpFunction %void None %14
%a_0 = OpFunctionParameter %_ptr_Function_int
%bb_entry = OpLabel
%17 = OpLoad %int %a_0
OpStore %a %17
OpTerminateRayKHR
OpFunctionEnd
; CHECK: %MyAHitMain2 = OpFunction %void None
; CHECK-NEXT: OpLabel
; CHECK-NEXT: %param_var_a = OpVariable %_ptr_Function_int Function
; CHECK-NEXT: OpLoad %int %a
; CHECK-NEXT: OpStore %param_var_a {{%\d+}}
; CHECK-NEXT: OpLoad %int %param_var_a
; CHECK-NEXT: OpStore %a {{%\d+}}
; CHECK-NEXT: OpTerminateRayKHR
; CHECK-NEXT: OpLabel
; CHECK-NEXT: OpLoad %int %param_var_a
; CHECK-NEXT: OpStore %a %16
; CHECK-NEXT: OpReturn
; CHECK-NEXT: OpFunctionEnd
)";
SinglePassRunAndMatch<InlineExhaustivePass>(text, false);
}
TEST_F(InlineTest, EarlyReturnFunctionInlined) {
// #version 140
//