diff options
| author | davli-nv <davli@nvidia.com> | 2025-10-16 18:22:39 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-17 01:22:39 +0000 |
| commit | ff064b9a0f1316007f46710432f854777a520fdf (patch) | |
| tree | 54a469024b8b7fe748223c67d38669685ecb55e0 | |
| parent | 74d93c0fecdac121320ffac16352979ad4b16c45 (diff) | |
Fix infinite loop in SPIRVLegalizationContext::processWorkList (#8712)
When slangc is invoked with -g, a source shader that has static infinite
loop can generate IR that have branch to a block that contains a branch
to the first block that contains the first branch, resulting in infinite
loop.
Change SPIRVLegalizationContext::processWorkList to only add branch
target to work list via its parent, this avoids the infinite loop above.
Also change addToWorkList to stop addUsersToWorkList, users should be
added explicitly by logic for specific insts.
Add regression test as tests/spirv/infinite-loop.slang
Fixes #8669
| -rw-r--r-- | source/slang/slang-ir-spirv-legalize.cpp | 18 | ||||
| -rw-r--r-- | tests/spirv/infinite-loop.slang | 17 |
2 files changed, 23 insertions, 12 deletions
diff --git a/source/slang/slang-ir-spirv-legalize.cpp b/source/slang/slang-ir-spirv-legalize.cpp index 965d6dc9b..97649f4ad 100644 --- a/source/slang/slang-ir-spirv-legalize.cpp +++ b/source/slang/slang-ir-spirv-legalize.cpp @@ -184,13 +184,7 @@ struct SPIRVLegalizationContext : public SourceEmitterBase // OrderedHashSet<IRInst*> workList; - void addToWorkList(IRInst* inst) - { - if (workList.add(inst)) - { - addUsersToWorkList(inst); - } - } + void addToWorkList(IRInst* inst) { workList.add(inst); } void addUsersToWorkList(IRInst* inst) { @@ -1692,8 +1686,6 @@ struct SPIRVLegalizationContext : public SourceEmitterBase } }; - void processBranch(IRInst* branch) { addToWorkList(branch->getOperand(0)); } - void processPtrLit(IRInst* inst) { IRBuilder builder(inst); @@ -1844,9 +1836,11 @@ struct SPIRVLegalizationContext : public SourceEmitterBase case kIROp_PtrLit: processPtrLit(inst); break; - case kIROp_UnconditionalBranch: - processBranch(inst); - break; + // kIROp_UnconditionalBranch is handled in default case that only + // adds children inst and not target inst to work list. + // Branch target should be added to work list via its parent, + // to avoid cycle when branch target block has branch to the block + // that's parent of this branch inst. case kIROp_SPIRVAsm: processSPIRVAsm(as<IRSPIRVAsm>(inst)); break; diff --git a/tests/spirv/infinite-loop.slang b/tests/spirv/infinite-loop.slang new file mode 100644 index 000000000..1562f7334 --- /dev/null +++ b/tests/spirv/infinite-loop.slang @@ -0,0 +1,17 @@ +// Simple regression test for SPIRV compilation hang when there is cycle between unconditional branch and block. +// The -g was necessary to reproduce the hang prior to fix for https://github.com/shader-slang/slang/issues/8669 + +//TEST:SIMPLE(filecheck=CHECK): -target spirv -stage fragment -entry main -g +//CHECK: main +//CHECK: OpBranch +//CHECK: OpUnreachable + +layout(location = 0) out float4 output_color; +[shader("fragment")] +void main() +{ + while (true) { + int i = 0; + } + output_color = float4(1, 2, 3, 4); +} |
