Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 3 commits into from
Dec 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions source/opcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 8 additions & 0 deletions source/opcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion source/opt/basic_block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
});
Expand Down
7 changes: 2 additions & 5 deletions source/opt/inline_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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());
});
}

Expand Down
2 changes: 1 addition & 1 deletion source/opt/ir_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion source/opt/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 0 additions & 4 deletions source/opt/reflect.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
57 changes: 57 additions & 0 deletions test/opt/inline_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand Down