Skip to content

Commit 2462370

Browse files
committed
[OPT] fix loop with recursive types in trim pass
When a type was recursive (or for the matter any instruction ID usage), the DFSWhile implementation would loop indefinitely. Added a history map to keep track of the visited instructions. Required for microsoft/DirectXShaderCompiler#7163 Signed-off-by: Nathan Gauër <[email protected]>
1 parent a48b473 commit 2462370

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

source/opt/trim_capabilities_pass.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,20 @@ constexpr uint32_t kOpExtInstImportNameInIndex = 0;
6161
template <class UnaryPredicate>
6262
static void DFSWhile(const Instruction* instruction, UnaryPredicate condition) {
6363
std::stack<uint32_t> instructions_to_visit;
64+
std::unordered_set<uint32_t> visited_instructions;
6465
instructions_to_visit.push(instruction->result_id());
6566
const auto* def_use_mgr = instruction->context()->get_def_use_mgr();
6667

6768
while (!instructions_to_visit.empty()) {
6869
const Instruction* item = def_use_mgr->GetDef(instructions_to_visit.top());
6970
instructions_to_visit.pop();
7071

72+
// Forward references can be allowed, meaning we can have cycles
73+
// between ID uses. Need to keep track of this.
74+
if (visited_instructions.count(item->result_id()))
75+
continue;
76+
visited_instructions.insert(item->result_id());
77+
7178
if (!condition(item)) {
7279
continue;
7380
}

test/opt/trim_capabilities_pass_test.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3606,6 +3606,35 @@ TEST_F(TrimCapabilitiesPassTest, QuadControlKHR_RemainsWithQuadAny) {
36063606
EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange);
36073607
}
36083608

3609+
TEST_F(TrimCapabilitiesPassTest, PhysicalStorageBuffer_RecursiveTypes) {
3610+
const std::string kTest = R"(
3611+
OpCapability Shader
3612+
OpCapability PhysicalStorageBufferAddresses
3613+
; CHECK: OpCapability PhysicalStorageBufferAddresses
3614+
OpExtension "SPV_KHR_physical_storage_buffer"
3615+
; CHECK: OpExtension "SPV_KHR_physical_storage_buffer"
3616+
OpMemoryModel PhysicalStorageBuffer64 GLSL450
3617+
OpEntryPoint Fragment %1 "main"
3618+
OpExecutionMode %1 OriginUpperLeft
3619+
OpSource HLSL 600
3620+
OpMemberDecorate %_struct_2 0 Offset 0
3621+
OpMemberDecorate %_struct_2 1 Offset 16
3622+
OpTypeForwardPointer %_ptr_PhysicalStorageBuffer__struct_2 PhysicalStorageBuffer
3623+
%int = OpTypeInt 32 1
3624+
%_struct_2 = OpTypeStruct %int %_ptr_PhysicalStorageBuffer__struct_2
3625+
%_ptr_PhysicalStorageBuffer__struct_2 = OpTypePointer PhysicalStorageBuffer %_struct_2
3626+
%void = OpTypeVoid
3627+
%6 = OpTypeFunction %void
3628+
%1 = OpFunction %void None %6
3629+
%7 = OpLabel
3630+
OpReturn
3631+
OpFunctionEnd
3632+
)";
3633+
const auto result =
3634+
SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false);
3635+
EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange);
3636+
}
3637+
36093638
INSTANTIATE_TEST_SUITE_P(
36103639
TrimCapabilitiesPassTestSubgroupClustered_Unsigned_I,
36113640
TrimCapabilitiesPassTestSubgroupClustered_Unsigned,

0 commit comments

Comments
 (0)