SPIR-V 1.6 requires the true and false labels of OpBranchConditional to
differ. Two places produced the same label for both:
- The structured terminator emitter, for a conditional branch whose
targets are the same block, such as s_cbranch_scc0 to the next
instruction. It now emits OpBranch, keeping OpLoopMerge on a loop
header.
- Pipeline specialization, when it folded a branch on a constant and
kept the selection merge because the taken path is not linear. It
wrote the taken label twice; the untaken side now names the
selection's merge block, which the constant condition never takes.
Found by recompiling mutated compute shaders with SPIR-V validation on;
before this, 169 of 20000 were rejected for this rule, and builds
without SPIRV-Tools handed the module to the driver.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb