Preserve debug info in dead-insert-elim pass (#3652)

When we determine the liveness of an insert, we have to ignore the debug
instruction (it must not have any impact on the decision).
diff --git a/source/opt/dead_insert_elim_pass.cpp b/source/opt/dead_insert_elim_pass.cpp
index 7d56343..46f4f12 100644
--- a/source/opt/dead_insert_elim_pass.cpp
+++ b/source/opt/dead_insert_elim_pass.cpp
@@ -196,6 +196,7 @@
       }
       const uint32_t id = ii->result_id();
       get_def_use_mgr()->ForEachUser(id, [&ii, this](Instruction* user) {
+        if (user->IsOpenCL100DebugInstr()) return;
         switch (user->opcode()) {
           case SpvOpCompositeInsert:
           case SpvOpPhi:
diff --git a/test/opt/dead_insert_elim_test.cpp b/test/opt/dead_insert_elim_test.cpp
index 8ae6894..9ea948a 100644
--- a/test/opt/dead_insert_elim_test.cpp
+++ b/test/opt/dead_insert_elim_test.cpp
@@ -563,6 +563,113 @@
                                             after_predefs + after, true, true);
 }
 
+TEST_F(DeadInsertElimTest, DebugInsertAfterInsertElim) {
+  // With two insertions to the same offset, the first is dead.
+  //
+  // Note: The SPIR-V assembly has had store/load elimination
+  // performed to allow the inserts and extracts to directly
+  // reference each other.
+  //
+  // #version 450
+  //
+  // layout (location=0) in float In0;
+  // layout (location=1) in float In1;
+  // layout (location=2) in vec2 In2;
+  // layout (location=0) out vec4 OutColor;
+  //
+  // void main()
+  // {
+  //     vec2 v = In2;
+  //     v.x = In0 + In1; // dead
+  //     v.x = 0.0;
+  //     OutColor = v.xyxy;
+  // }
+
+  const std::string text =
+      R"(OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+%ext = OpExtInstImport "OpenCL.DebugInfo.100"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
+OpExecutionMode %main OriginUpperLeft
+OpSource GLSL 450
+%file_name = OpString "test"
+%float_name = OpString "float"
+%main_name = OpString "main"
+%f_name = OpString "f"
+OpName %main "main"
+OpName %In2 "In2"
+OpName %In0 "In0"
+OpName %In1 "In1"
+OpName %OutColor "OutColor"
+OpName %_Globals_ "_Globals_"
+OpMemberName %_Globals_ 0 "g_b"
+OpMemberName %_Globals_ 1 "g_n"
+OpName %_ ""
+OpDecorate %In2 Location 2
+OpDecorate %In0 Location 0
+OpDecorate %In1 Location 1
+OpDecorate %OutColor Location 0
+OpMemberDecorate %_Globals_ 0 Offset 0
+OpMemberDecorate %_Globals_ 1 Offset 4
+OpDecorate %_Globals_ Block
+OpDecorate %_ DescriptorSet 0
+OpDecorate %_ Binding 0
+%void = OpTypeVoid
+%11 = OpTypeFunction %void
+%float = OpTypeFloat 32
+%v2float = OpTypeVector %float 2
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+%_ptr_Input_v2float = OpTypePointer Input %v2float
+%In2 = OpVariable %_ptr_Input_v2float Input
+%_ptr_Input_float = OpTypePointer Input %float
+%In0 = OpVariable %_ptr_Input_float Input
+%In1 = OpVariable %_ptr_Input_float Input
+%uint = OpTypeInt 32 0
+%uint_32 = OpConstant %uint 32
+%_ptr_Function_float = OpTypePointer Function %float
+%float_0 = OpConstant %float 0
+%v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%OutColor = OpVariable %_ptr_Output_v4float Output
+%int = OpTypeInt 32 1
+%_Globals_ = OpTypeStruct %uint %int
+%_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
+%_ = OpVariable %_ptr_Uniform__Globals_ Uniform
+
+%nullexpr = OpExtInst %void %ext DebugExpression
+%src = OpExtInst %void %ext DebugSource %file_name
+%cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
+%dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
+%dbg_v2f = OpExtInst %void %ext DebugTypeVector %dbg_tf 2
+%main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
+%dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 0 %main
+%dbg_foo = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v2f %src 0 0 %dbg_main FlagIsLocal
+
+%main = OpFunction %void None %11
+%25 = OpLabel
+%26 = OpLoad %v2float %In2
+%27 = OpLoad %float %In0
+%28 = OpLoad %float %In1
+%29 = OpFAdd %float %27 %28
+
+; CHECK:      [[repl:%\w+]] = OpLoad %v2float %In2
+; CHECK-NOT:  OpCompositeInsert
+; CHECK:      DebugValue {{%\w+}} [[repl:%\w+]]
+; CHECK-NEXT: OpCompositeInsert %v2float %float_0 [[repl]] 0
+%35 = OpCompositeInsert %v2float %29 %26 0
+%value = OpExtInst %void %ext DebugValue %dbg_foo %35 %nullexpr
+%37 = OpCompositeInsert %v2float %float_0 %35 0
+
+%33 = OpVectorShuffle %v4float %37 %37 0 1 0 1
+OpStore %OutColor %33
+OpReturn
+OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<DeadInsertElimPass>(text, true);
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //