Skip to content

Add DebugBuildIdentifier to the live worklist during initialization#6618

Open
jkwak-work wants to merge 1 commit intoKhronosGroup:mainfrom
jkwak-work:main
Open

Add DebugBuildIdentifier to the live worklist during initialization#6618
jkwak-work wants to merge 1 commit intoKhronosGroup:mainfrom
jkwak-work:main

Conversation

@jkwak-work
Copy link
Copy Markdown

DebugBuildIdentifier was missing from the set of NonSemantic debug instructions added to the worklist in InitializeModuleScopeLiveInstructions.
Instead it was handled in ProcessGlobalValues (after the worklist is
exhausted) using live_insts_.Set() on its direct operands.

live_insts_.Set() marks an instruction live but does not enqueue it, so transitive operand dependencies are never visited. In shaders where the only use of a type (e.g. OpTypeInt) is through a constant that is itself only referenced by DebugBuildIdentifier's flags argument, the type instruction is not marked live and is incorrectly killed by ADCE.

The surviving constant then references a deleted type, producing invalid SPIR-V. Any subsequent pass that rebuilds the DefUseManager (e.g. CCP) will fail with "Definition is not registered."

Fix: include NonSemanticShaderDebugInfo100DebugBuildIdentifier in the worklist loop alongside the other always-live debug instructions. The worklist's transitive closure correctly marks all operand dependencies live before global-value cleanup runs. The existing special-case code in ProcessGlobalValues becomes unreachable for this opcode (IsLive returns true, so the early continue fires) and is now dead; it is left in place for safety.

DebugBuildIdentifier was missing from the set of NonSemantic debug                                                                             instructions added to the worklist in InitializeModuleScopeLiveInstructions.
Instead it was handled in ProcessGlobalValues (after the worklist is
exhausted) using live_insts_.Set() on its direct operands.

live_insts_.Set() marks an instruction live but does not enqueue it, so
transitive operand dependencies are never visited. In shaders where the
only use of a type (e.g. OpTypeInt) is through a constant that is itself
only referenced by DebugBuildIdentifier's flags argument, the type
instruction is not marked live and is incorrectly killed by ADCE.

The surviving constant then references a deleted type, producing invalid
SPIR-V. Any subsequent pass that rebuilds the DefUseManager (e.g. CCP)
will fail with "Definition is not registered."

Fix: include NonSemanticShaderDebugInfo100DebugBuildIdentifier in the
worklist loop alongside the other always-live debug instructions. The
worklist's transitive closure correctly marks all operand dependencies
live before global-value cleanup runs. The existing special-case code in
ProcessGlobalValues becomes unreachable for this opcode (IsLive returns
true, so the early continue fires) and is now dead; it is left in place
for safety.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 27, 2026

CLA assistant check
All committers have signed the CLA.

@jkwak-work
Copy link
Copy Markdown
Author

jkwak-work commented Mar 27, 2026

I am not able to make a simple repro SPIRV for this issue.

As far as I can tell the problem is on the fact that the constant variable used for DebugBuildIdentifier is not recognized and it causes an assertion failure as following:

Assertion failed: def && "Definition is not registered.", file D:\sbf\git\SPIRV-Tools\source\opt\def_use_manager.cpp, line 56

This issue was observed only with an option, --eliminate-dead-code-aggressive.

If I can somehow make a simpler repro case later, I will share it to have it as a regression test.

@jkwak-work
Copy link
Copy Markdown
Author

I found a small repro Spirv Code for the issue.

Fixes #6619

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants