Debug info preservation in convert-local-access-chains pass (#3835)

1. DebugValue/DebugDeclare references of load/store must not change
the behaviors of the convert-local-access-chains pass
2. We have to properly set the scope and line information of new
instructions made by the convert-local-access-chains pass
diff --git a/source/opt/local_access_chain_convert_pass.cpp b/source/opt/local_access_chain_convert_pass.cpp
index b57dd29..205cd7a 100644
--- a/source/opt/local_access_chain_convert_pass.cpp
+++ b/source/opt/local_access_chain_convert_pass.cpp
@@ -95,9 +95,12 @@
     return false;
   }
 
+  new_inst[0]->UpdateDebugInfoFrom(original_load);
   context()->get_decoration_mgr()->CloneDecorations(
       original_load->result_id(), ldResultId, {SpvDecorationRelaxedPrecision});
   original_load->InsertBefore(std::move(new_inst));
+  context()->get_debug_info_mgr()->AnalyzeDebugInst(
+      original_load->PreviousNode());
 
   // Rewrite |original_load| into an extract.
   Instruction::OperandList new_operands;
@@ -181,6 +184,10 @@
 bool LocalAccessChainConvertPass::HasOnlySupportedRefs(uint32_t ptrId) {
   if (supported_ref_ptrs_.find(ptrId) != supported_ref_ptrs_.end()) return true;
   if (get_def_use_mgr()->WhileEachUser(ptrId, [this](Instruction* user) {
+        if (user->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugValue ||
+            user->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugDeclare) {
+          return true;
+        }
         SpvOp op = user->opcode();
         if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) {
           if (!HasOnlySupportedRefs(user->result_id())) {
@@ -251,7 +258,6 @@
           Instruction* ptrInst = GetPtr(&*ii, &varId);
           if (!IsNonPtrAccessChain(ptrInst->opcode())) break;
           if (!IsTargetVar(varId)) break;
-          std::vector<std::unique_ptr<Instruction>> newInsts;
           if (!ReplaceAccessChainLoad(ptrInst, &*ii)) {
             return Status::Failure;
           }
@@ -259,21 +265,26 @@
         } break;
         case SpvOpStore: {
           uint32_t varId;
-          Instruction* ptrInst = GetPtr(&*ii, &varId);
+          Instruction* store = &*ii;
+          Instruction* ptrInst = GetPtr(store, &varId);
           if (!IsNonPtrAccessChain(ptrInst->opcode())) break;
           if (!IsTargetVar(varId)) break;
           std::vector<std::unique_ptr<Instruction>> newInsts;
-          uint32_t valId = ii->GetSingleWordInOperand(kStoreValIdInIdx);
+          uint32_t valId = store->GetSingleWordInOperand(kStoreValIdInIdx);
           if (!GenAccessChainStoreReplacement(ptrInst, valId, &newInsts)) {
             return Status::Failure;
           }
           size_t num_of_instructions_to_skip = newInsts.size() - 1;
-          dead_instructions.push_back(&*ii);
+          dead_instructions.push_back(store);
           ++ii;
           ii = ii.InsertBefore(std::move(newInsts));
           for (size_t i = 0; i < num_of_instructions_to_skip; ++i) {
+            ii->UpdateDebugInfoFrom(store);
+            context()->get_debug_info_mgr()->AnalyzeDebugInst(&*ii);
             ++ii;
           }
+          ii->UpdateDebugInfoFrom(store);
+          context()->get_debug_info_mgr()->AnalyzeDebugInst(&*ii);
           modified = true;
         } break;
         default:
diff --git a/test/opt/local_access_chain_convert_test.cpp b/test/opt/local_access_chain_convert_test.cpp
index 3161d90..521e0c8 100644
--- a/test/opt/local_access_chain_convert_test.cpp
+++ b/test/opt/local_access_chain_convert_test.cpp
@@ -96,6 +96,211 @@
                                                      true);
 }
 
+TEST_F(LocalAccessChainConvertTest, DebugScopeAndLineInfoForNewInstructions) {
+  //  #version 140
+  //
+  //  in vec4 BaseColor;
+  //
+  //  struct S_t {
+  //      vec4 v0;
+  //      vec4 v1;
+  //  };
+  //
+  //  void main()
+  //  {
+  //      S_t s0;
+  //      s0.v1 = BaseColor;
+  //      gl_FragColor = s0.v1;
+  //  }
+
+  const std::string predefs_before =
+      R"(OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+%ext = OpExtInstImport "OpenCL.DebugInfo.100"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
+OpExecutionMode %main OriginUpperLeft
+OpSource GLSL 140
+OpName %main "main"
+OpName %S_t "S_t"
+OpMemberName %S_t 0 "v0"
+OpMemberName %S_t 1 "v1"
+OpName %s0 "s0"
+OpName %BaseColor "BaseColor"
+OpName %gl_FragColor "gl_FragColor"
+%5 = OpString "ps.hlsl"
+%6 = OpString "float"
+%var_name = OpString "s0"
+%main_name = OpString "main"
+%void = OpTypeVoid
+%8 = OpTypeFunction %void
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%S_t = OpTypeStruct %v4float %v4float
+%_ptr_Function_S_t = OpTypePointer Function %S_t
+%int = OpTypeInt 32 1
+%int_1 = OpConstant %int 1
+%int_32 = OpConstant %int 32
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%BaseColor = OpVariable %_ptr_Input_v4float Input
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%gl_FragColor = OpVariable %_ptr_Output_v4float Output
+%20 = OpExtInst %void %ext DebugSource %5
+%21 = OpExtInst %void %ext DebugCompilationUnit 1 4 %20 HLSL
+%22 = OpExtInst %void %ext DebugTypeBasic %6 %int_32 Float
+%23 = OpExtInst %void %ext DebugTypeVector %22 4
+%24 = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
+%dbg_main = OpExtInst %void %ext DebugFunction %main_name %24 %20 4 1 %21 %main_name FlagIsProtected|FlagIsPrivate 4 %main
+%25 = OpExtInst %void %ext DebugLocalVariable %var_name %23 %20 0 0 %dbg_main FlagIsLocal
+)";
+
+  const std::string before =
+      R"(
+; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
+; CHECK: OpLine {{%\w+}} 1 0
+; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
+; CHECK: OpLine {{%\w+}} 1 0
+; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
+; CHECK: OpLine {{%\w+}} 1 0
+; CHECK: OpStore %s0 [[ex1]]
+; CHECK: OpLine {{%\w+}} 3 0
+; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
+; CHECK: OpLine {{%\w+}} 3 0
+; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
+; CHECK: OpLine {{%\w+}} 4 0
+; CHECK: OpStore %gl_FragColor [[ex2]]
+%main = OpFunction %void None %8
+%17 = OpLabel
+%26 = OpExtInst %void %ext DebugScope %dbg_main
+%s0 = OpVariable %_ptr_Function_S_t Function
+%18 = OpLoad %v4float %BaseColor
+OpLine %5 0 0
+%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
+OpLine %5 1 0
+OpStore %19 %18
+OpLine %5 2 0
+%27 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
+OpLine %5 3 0
+%28 = OpLoad %v4float %27
+OpLine %5 4 0
+OpStore %gl_FragColor %28
+OpReturn
+OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
+                                                     true);
+}
+
+TEST_F(LocalAccessChainConvertTest, TestTargetsReferencedByDebugValue) {
+  //  #version 140
+  //
+  //  in vec4 BaseColor;
+  //
+  //  struct S_t {
+  //      vec4 v0;
+  //      vec4 v1;
+  //  };
+  //
+  //  void main()
+  //  {
+  //      S_t s0;
+  //      s0.v1 = BaseColor;
+  //      gl_FragColor = s0.v1;
+  //  }
+
+  const std::string predefs_before =
+      R"(OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+%ext = OpExtInstImport "OpenCL.DebugInfo.100"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
+OpExecutionMode %main OriginUpperLeft
+OpSource GLSL 140
+OpName %main "main"
+OpName %S_t "S_t"
+OpMemberName %S_t 0 "v0"
+OpMemberName %S_t 1 "v1"
+OpName %s0 "s0"
+OpName %BaseColor "BaseColor"
+OpName %gl_FragColor "gl_FragColor"
+%5 = OpString "ps.hlsl"
+%6 = OpString "float"
+%var_name = OpString "s0"
+%main_name = OpString "main"
+%void = OpTypeVoid
+%8 = OpTypeFunction %void
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%S_t = OpTypeStruct %v4float %v4float
+%_ptr_Function_S_t = OpTypePointer Function %S_t
+%int = OpTypeInt 32 1
+%int_1 = OpConstant %int 1
+%int_32 = OpConstant %int 32
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%BaseColor = OpVariable %_ptr_Input_v4float Input
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%gl_FragColor = OpVariable %_ptr_Output_v4float Output
+%deref = OpExtInst %void %ext DebugOperation Deref
+%deref_expr = OpExtInst %void %ext DebugExpression %deref
+%null_expr = OpExtInst %void %ext DebugExpression
+%20 = OpExtInst %void %ext DebugSource %5
+%21 = OpExtInst %void %ext DebugCompilationUnit 1 4 %20 HLSL
+%22 = OpExtInst %void %ext DebugTypeBasic %6 %int_32 Float
+%23 = OpExtInst %void %ext DebugTypeVector %22 4
+%24 = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
+%dbg_main = OpExtInst %void %ext DebugFunction %main_name %24 %20 4 1 %21 %main_name FlagIsProtected|FlagIsPrivate 4 %main
+%25 = OpExtInst %void %ext DebugLocalVariable %var_name %23 %20 0 0 %dbg_main FlagIsLocal
+)";
+
+  const std::string before =
+      R"(
+; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
+; CHECK: OpLine {{%\w+}} 0 0
+; CHECK: [[s0_1_ptr:%\w+]] = OpAccessChain %_ptr_Function_v4float %s0 %int_1
+; CHECK: DebugValue [[dbg_s0:%\w+]] [[s0_1_ptr]]
+; CHECK: OpLine {{%\w+}} 1 0
+; CHECK: [[s0:%\w+]] = OpLoad %S_t %s0
+; CHECK: OpLine {{%\w+}} 1 0
+; CHECK: [[comp:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[s0]] 1
+; CHECK: OpLine {{%\w+}} 1 0
+; CHECK: OpStore %s0 [[comp]]
+; CHECK: OpLine {{%\w+}} 2 0
+; CHECK: [[s0_2_ptr:%\w+]] = OpAccessChain %_ptr_Function_v4float %s0 %int_1
+; CHECK: OpLine {{%\w+}} 3 0
+; CHECK: [[s0:%\w+]] = OpLoad %S_t %s0
+; CHECK: OpLine {{%\w+}} 3 0
+; CHECK: [[s0_2_val:%\w+]] = OpCompositeExtract %v4float [[s0]] 1
+; CHECK: DebugValue [[dbg_s0]] [[s0_2_val]]
+; CHECK: OpLine {{%\w+}} 4 0
+; CHECK: OpStore %gl_FragColor [[s0_2_val]]
+%main = OpFunction %void None %8
+%17 = OpLabel
+%26 = OpExtInst %void %ext DebugScope %dbg_main
+%s0 = OpVariable %_ptr_Function_S_t Function
+%18 = OpLoad %v4float %BaseColor
+OpLine %5 0 0
+%19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
+%29 = OpExtInst %void %ext DebugValue %25 %19 %deref_expr %int_1
+OpLine %5 1 0
+OpStore %19 %18
+OpLine %5 2 0
+%27 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
+OpLine %5 3 0
+%28 = OpLoad %v4float %27
+%30 = OpExtInst %void %ext DebugValue %25 %28 %null_expr %int_1
+OpLine %5 4 0
+OpStore %gl_FragColor %28
+OpReturn
+OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
+                                                     true);
+}
+
 TEST_F(LocalAccessChainConvertTest, InBoundsAccessChainsConverted) {
   //  #version 140
   //