Add DebugBuildIdentifier to the live worklist during initialization (#6626)

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
placefor safety.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
diff --git a/source/opt/aggressive_dead_code_elim_pass.cpp b/source/opt/aggressive_dead_code_elim_pass.cpp
index 698d4e6..8ca2518 100644
--- a/source/opt/aggressive_dead_code_elim_pass.cpp
+++ b/source/opt/aggressive_dead_code_elim_pass.cpp
@@ -768,7 +768,8 @@
         op == NonSemanticShaderDebugInfoDebugSourceContinued ||
         op == NonSemanticShaderDebugInfoDebugLocalVariable ||
         op == NonSemanticShaderDebugInfoDebugExpression ||
-        op == NonSemanticShaderDebugInfoDebugOperation) {
+        op == NonSemanticShaderDebugInfoDebugOperation ||
+        op == NonSemanticShaderDebugInfoDebugBuildIdentifier) {
       AddToWorklist(&dbg);
     }
   }
diff --git a/test/opt/aggressive_dead_code_elim_test.cpp b/test/opt/aggressive_dead_code_elim_test.cpp
index 9665a18..2763afb 100644
--- a/test/opt/aggressive_dead_code_elim_test.cpp
+++ b/test/opt/aggressive_dead_code_elim_test.cpp
@@ -9218,6 +9218,45 @@
   SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
 }
 
+TEST_F(AggressiveDCETest, KeepDebugBuildIdentifier) {
+  // Regression test for https://github.com/KhronosGroup/SPIRV-Tools/issues/6619
+  //
+  // DebugBuildIdentifier was not added to the live-instruction worklist during
+  // initialization, so its operand dependencies (e.g. OpTypeInt used only by
+  // a constant that is only referenced by DebugBuildIdentifier) were never
+  // visited and were incorrectly eliminated. The surviving constant then
+  // referenced a deleted type, producing invalid SPIR-V.
+  //
+  // After the fix, DebugBuildIdentifier is enqueued in the worklist so its
+  // transitive operands (OpTypeInt 32 0, OpConstant %uint 0) are marked live.
+
+  const std::string spirv = R"(
+; CHECK: [[ext:%\w+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK: [[str:%\w+]] = OpString
+; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
+; CHECK: [[uint_0:%\w+]] = OpConstant [[uint]] 0
+; CHECK: OpExtInst %void [[ext]] DebugBuildIdentifier [[str]] [[uint_0]]
+               OpCapability Shader
+               OpExtension "SPV_KHR_non_semantic_info"
+          %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+          %2 = OpString "01cfb4b77c321225f096da8ac72f29d42f0632a7"
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+          %3 = OpTypeFunction %void
+          %4 = OpExtInst %void %1 DebugBuildIdentifier %2 %uint_0
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools