Instrument: Add missing def-use analysis. (#2985)

diff --git a/source/opt/instrument_pass.cpp b/source/opt/instrument_pass.cpp
index 246cdbb..2a3e7f0 100644
--- a/source/opt/instrument_pass.cpp
+++ b/source/opt/instrument_pass.cpp
@@ -325,29 +325,36 @@
     std::unordered_map<uint32_t, uint32_t>* same_blk_post,
     std::unordered_map<uint32_t, Instruction*>* same_blk_pre,
     BasicBlock* block_ptr) {
-  (*inst)->ForEachInId(
-      [&same_blk_post, &same_blk_pre, &block_ptr, this](uint32_t* iid) {
-        const auto map_itr = (*same_blk_post).find(*iid);
-        if (map_itr == (*same_blk_post).end()) {
-          const auto map_itr2 = (*same_blk_pre).find(*iid);
-          if (map_itr2 != (*same_blk_pre).end()) {
-            // Clone pre-call same-block ops, map result id.
-            const Instruction* in_inst = map_itr2->second;
-            std::unique_ptr<Instruction> sb_inst(in_inst->Clone(context()));
-            CloneSameBlockOps(&sb_inst, same_blk_post, same_blk_pre, block_ptr);
-            const uint32_t rid = sb_inst->result_id();
-            const uint32_t nid = this->TakeNextId();
-            get_decoration_mgr()->CloneDecorations(rid, nid);
-            sb_inst->SetResultId(nid);
-            (*same_blk_post)[rid] = nid;
-            *iid = nid;
-            block_ptr->AddInstruction(std::move(sb_inst));
-          }
-        } else {
-          // Reset same-block op operand.
-          *iid = map_itr->second;
-        }
-      });
+  bool changed = false;
+  (*inst)->ForEachInId([&same_blk_post, &same_blk_pre, &block_ptr, &changed,
+                        this](uint32_t* iid) {
+    const auto map_itr = (*same_blk_post).find(*iid);
+    if (map_itr == (*same_blk_post).end()) {
+      const auto map_itr2 = (*same_blk_pre).find(*iid);
+      if (map_itr2 != (*same_blk_pre).end()) {
+        // Clone pre-call same-block ops, map result id.
+        const Instruction* in_inst = map_itr2->second;
+        std::unique_ptr<Instruction> sb_inst(in_inst->Clone(context()));
+        const uint32_t rid = sb_inst->result_id();
+        const uint32_t nid = this->TakeNextId();
+        get_decoration_mgr()->CloneDecorations(rid, nid);
+        sb_inst->SetResultId(nid);
+        get_def_use_mgr()->AnalyzeInstDefUse(&*sb_inst);
+        (*same_blk_post)[rid] = nid;
+        *iid = nid;
+        changed = true;
+        CloneSameBlockOps(&sb_inst, same_blk_post, same_blk_pre, block_ptr);
+        block_ptr->AddInstruction(std::move(sb_inst));
+      }
+    } else {
+      // Reset same-block op operand if necessary
+      if (*iid != map_itr->second) {
+        *iid = map_itr->second;
+        changed = true;
+      }
+    }
+  });
+  if (changed) get_def_use_mgr()->AnalyzeInstUse(&**inst);
 }
 
 void InstrumentPass::UpdateSucceedingPhis(
diff --git a/test/opt/inst_bindless_check_test.cpp b/test/opt/inst_bindless_check_test.cpp
index 130f70d..b4db2d5 100644
--- a/test/opt/inst_bindless_check_test.cpp
+++ b/test/opt/inst_bindless_check_test.cpp
@@ -10820,6 +10820,415 @@
       true, 7u, 23u, true, true, 2u);
 }
 
+TEST_F(InstBindlessTest, InstBoundsInitSameBlockOpReplication) {
+  // Test that same block ops like OpSampledImage are replicated properly
+  // where needed.
+  //
+  // clang-format off
+  //
+  // #version 450 core
+  // #extension GL_EXT_nonuniform_qualifier : enable
+  //
+  // layout(location = 0) in vec2 inTexcoord;
+  // layout(location = 0) out vec4 outColor;
+  //
+  // layout(set = 0, binding = 0) uniform Uniforms {
+  //   vec2 var0;
+  // } uniforms;
+  //
+  // layout(set = 0, binding = 1) uniform sampler uniformSampler;
+  // layout(set = 0, binding = 2) uniform texture2D uniformTex;
+  // layout(set = 0, binding = 3) uniform texture2D uniformTexArr[8];
+  //
+  // void main() {
+  //   int index = 0;
+  //   float x = texture(sampler2D(uniformTexArr[nonuniformEXT(index)], uniformSampler), inTexcoord.xy).x;
+  //   float y = texture(sampler2D(uniformTex, uniformSampler), inTexcoord.xy * uniforms.var0.xy).x;
+  //   outColor = vec4(x, y, 0.0, 0.0);
+  // }
+  //
+  // clang-format on
+
+  const std::string defs_before =
+      R"(OpCapability Shader
+OpCapability ShaderNonUniformEXT
+OpCapability SampledImageArrayNonUniformIndexingEXT
+OpExtension "SPV_EXT_descriptor_indexing"
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %inTexcoord %outColor
+OpExecutionMode %main OriginUpperLeft
+OpSource GLSL 450
+OpSourceExtension "GL_EXT_nonuniform_qualifier"
+OpName %main "main"
+OpName %index "index"
+OpName %x "x"
+OpName %uniformTexArr "uniformTexArr"
+OpName %uniformSampler "uniformSampler"
+OpName %inTexcoord "inTexcoord"
+OpName %y "y"
+OpName %uniformTex "uniformTex"
+OpName %Uniforms "Uniforms"
+OpMemberName %Uniforms 0 "var0"
+OpName %uniforms "uniforms"
+OpName %outColor "outColor"
+OpDecorate %uniformTexArr DescriptorSet 0
+OpDecorate %uniformTexArr Binding 3
+OpDecorate %19 NonUniformEXT
+OpDecorate %22 NonUniformEXT
+OpDecorate %uniformSampler DescriptorSet 0
+OpDecorate %uniformSampler Binding 1
+OpDecorate %inTexcoord Location 0
+OpDecorate %uniformTex DescriptorSet 0
+OpDecorate %uniformTex Binding 2
+OpMemberDecorate %Uniforms 0 Offset 0
+OpDecorate %Uniforms Block
+OpDecorate %uniforms DescriptorSet 0
+OpDecorate %uniforms Binding 0
+OpDecorate %outColor Location 0
+%void = OpTypeVoid
+%3 = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+%int_0 = OpConstant %int 0
+%float = OpTypeFloat 32
+%_ptr_Function_float = OpTypePointer Function %float
+%13 = OpTypeImage %float 2D 0 0 0 1 Unknown
+%uint = OpTypeInt 32 0
+%uint_8 = OpConstant %uint 8
+%_arr_13_uint_8 = OpTypeArray %13 %uint_8
+%_ptr_UniformConstant__arr_13_uint_8 = OpTypePointer UniformConstant %_arr_13_uint_8
+%uniformTexArr = OpVariable %_ptr_UniformConstant__arr_13_uint_8 UniformConstant
+%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
+%23 = OpTypeSampler
+%_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23
+%uniformSampler = OpVariable %_ptr_UniformConstant_23 UniformConstant
+%27 = OpTypeSampledImage %13
+%v2float = OpTypeVector %float 2
+%_ptr_Input_v2float = OpTypePointer Input %v2float
+%inTexcoord = OpVariable %_ptr_Input_v2float Input
+%v4float = OpTypeVector %float 4
+%uint_0 = OpConstant %uint 0
+%uniformTex = OpVariable %_ptr_UniformConstant_13 UniformConstant
+%Uniforms = OpTypeStruct %v2float
+%_ptr_Uniform_Uniforms = OpTypePointer Uniform %Uniforms
+%uniforms = OpVariable %_ptr_Uniform_Uniforms Uniform
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%outColor = OpVariable %_ptr_Output_v4float Output
+%float_0 = OpConstant %float 0
+)";
+
+  const std::string defs_after =
+      R"(OpCapability Shader
+OpCapability ShaderNonUniform
+OpCapability SampledImageArrayNonUniformIndexing
+OpExtension "SPV_EXT_descriptor_indexing"
+OpExtension "SPV_KHR_storage_buffer_storage_class"
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %inTexcoord %outColor %gl_FragCoord
+OpExecutionMode %main OriginUpperLeft
+OpSource GLSL 450
+OpSourceExtension "GL_EXT_nonuniform_qualifier"
+OpName %main "main"
+OpName %index "index"
+OpName %x "x"
+OpName %uniformTexArr "uniformTexArr"
+OpName %uniformSampler "uniformSampler"
+OpName %inTexcoord "inTexcoord"
+OpName %y "y"
+OpName %uniformTex "uniformTex"
+OpName %Uniforms "Uniforms"
+OpMemberName %Uniforms 0 "var0"
+OpName %uniforms "uniforms"
+OpName %outColor "outColor"
+OpDecorate %uniformTexArr DescriptorSet 0
+OpDecorate %uniformTexArr Binding 3
+OpDecorate %19 NonUniform
+OpDecorate %22 NonUniform
+OpDecorate %uniformSampler DescriptorSet 0
+OpDecorate %uniformSampler Binding 1
+OpDecorate %inTexcoord Location 0
+OpDecorate %uniformTex DescriptorSet 0
+OpDecorate %uniformTex Binding 2
+OpMemberDecorate %Uniforms 0 Offset 0
+OpDecorate %Uniforms Block
+OpDecorate %uniforms DescriptorSet 0
+OpDecorate %uniforms Binding 0
+OpDecorate %outColor Location 0
+OpDecorate %63 NonUniform
+OpDecorate %_runtimearr_uint ArrayStride 4
+OpDecorate %_struct_75 Block
+OpMemberDecorate %_struct_75 0 Offset 0
+OpMemberDecorate %_struct_75 1 Offset 4
+OpDecorate %77 DescriptorSet 7
+OpDecorate %77 Binding 0
+OpDecorate %gl_FragCoord BuiltIn FragCoord
+OpDecorate %_struct_132 Block
+OpMemberDecorate %_struct_132 0 Offset 0
+OpDecorate %134 DescriptorSet 7
+OpDecorate %134 Binding 1
+OpDecorate %151 NonUniform
+%void = OpTypeVoid
+%3 = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%_ptr_Function_int = OpTypePointer Function %int
+%int_0 = OpConstant %int 0
+%float = OpTypeFloat 32
+%_ptr_Function_float = OpTypePointer Function %float
+%13 = OpTypeImage %float 2D 0 0 0 1 Unknown
+%uint = OpTypeInt 32 0
+%uint_8 = OpConstant %uint 8
+%_arr_13_uint_8 = OpTypeArray %13 %uint_8
+%_ptr_UniformConstant__arr_13_uint_8 = OpTypePointer UniformConstant %_arr_13_uint_8
+%uniformTexArr = OpVariable %_ptr_UniformConstant__arr_13_uint_8 UniformConstant
+%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
+%23 = OpTypeSampler
+%_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23
+%uniformSampler = OpVariable %_ptr_UniformConstant_23 UniformConstant
+%27 = OpTypeSampledImage %13
+%v2float = OpTypeVector %float 2
+%_ptr_Input_v2float = OpTypePointer Input %v2float
+%inTexcoord = OpVariable %_ptr_Input_v2float Input
+%v4float = OpTypeVector %float 4
+%uint_0 = OpConstant %uint 0
+%uniformTex = OpVariable %_ptr_UniformConstant_13 UniformConstant
+%Uniforms = OpTypeStruct %v2float
+%_ptr_Uniform_Uniforms = OpTypePointer Uniform %Uniforms
+%uniforms = OpVariable %_ptr_Uniform_Uniforms Uniform
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%outColor = OpVariable %_ptr_Output_v4float Output
+%float_0 = OpConstant %float 0
+%bool = OpTypeBool
+%68 = OpTypeFunction %void %uint %uint %uint %uint
+%_runtimearr_uint = OpTypeRuntimeArray %uint
+%_struct_75 = OpTypeStruct %uint %_runtimearr_uint
+%_ptr_StorageBuffer__struct_75 = OpTypePointer StorageBuffer %_struct_75
+%77 = OpVariable %_ptr_StorageBuffer__struct_75 StorageBuffer
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%uint_10 = OpConstant %uint 10
+%uint_4 = OpConstant %uint 4
+%uint_1 = OpConstant %uint 1
+%uint_23 = OpConstant %uint 23
+%uint_2 = OpConstant %uint 2
+%uint_3 = OpConstant %uint 3
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+%v4uint = OpTypeVector %uint 4
+%uint_5 = OpConstant %uint 5
+%uint_7 = OpConstant %uint 7
+%uint_9 = OpConstant %uint 9
+%uint_79 = OpConstant %uint 79
+%122 = OpConstantNull %v4float
+%126 = OpTypeFunction %uint %uint %uint %uint %uint
+%_struct_132 = OpTypeStruct %_runtimearr_uint
+%_ptr_StorageBuffer__struct_132 = OpTypePointer StorageBuffer %_struct_132
+%134 = OpVariable %_ptr_StorageBuffer__struct_132 StorageBuffer
+%uint_87 = OpConstant %uint 87
+%165 = OpConstantNull %v2float
+%uint_89 = OpConstant %uint 89
+)";
+
+  const std::string func_before =
+      R"(%main = OpFunction %void None %3
+%5 = OpLabel
+%index = OpVariable %_ptr_Function_int Function
+%x = OpVariable %_ptr_Function_float Function
+%y = OpVariable %_ptr_Function_float Function
+OpStore %index %int_0
+%19 = OpLoad %int %index
+%21 = OpAccessChain %_ptr_UniformConstant_13 %uniformTexArr %19
+%22 = OpLoad %13 %21
+%26 = OpLoad %23 %uniformSampler
+%28 = OpSampledImage %27 %22 %26
+%32 = OpLoad %v2float %inTexcoord
+%34 = OpImageSampleImplicitLod %v4float %28 %32
+%36 = OpCompositeExtract %float %34 0
+OpStore %x %36
+%39 = OpLoad %13 %uniformTex
+%40 = OpLoad %23 %uniformSampler
+%41 = OpSampledImage %27 %39 %40
+%42 = OpLoad %v2float %inTexcoord
+%47 = OpAccessChain %_ptr_Uniform_v2float %uniforms %int_0
+%48 = OpLoad %v2float %47
+%49 = OpFMul %v2float %42 %48
+%50 = OpImageSampleImplicitLod %v4float %41 %49
+%51 = OpCompositeExtract %float %50 0
+OpStore %y %51
+%54 = OpLoad %float %x
+%55 = OpLoad %float %y
+%57 = OpCompositeConstruct %v4float %54 %55 %float_0 %float_0
+OpStore %outColor %57
+OpReturn
+OpFunctionEnd
+)";
+
+  const std::string func_after =
+      R"(%main = OpFunction %void None %3
+%5 = OpLabel
+%index = OpVariable %_ptr_Function_int Function
+%x = OpVariable %_ptr_Function_float Function
+%y = OpVariable %_ptr_Function_float Function
+OpStore %index %int_0
+%19 = OpLoad %int %index
+%21 = OpAccessChain %_ptr_UniformConstant_13 %uniformTexArr %19
+%22 = OpLoad %13 %21
+%26 = OpLoad %23 %uniformSampler
+%28 = OpSampledImage %27 %22 %26
+%32 = OpLoad %v2float %inTexcoord
+%59 = OpULessThan %bool %19 %uint_8
+OpSelectionMerge %60 None
+OpBranchConditional %59 %61 %62
+%61 = OpLabel
+%63 = OpLoad %13 %21
+%64 = OpSampledImage %27 %63 %26
+%124 = OpBitcast %uint %19
+%146 = OpFunctionCall %uint %125 %uint_0 %uint_0 %uint_3 %124
+%147 = OpINotEqual %bool %146 %uint_0
+OpSelectionMerge %148 None
+OpBranchConditional %147 %149 %150
+%149 = OpLabel
+%151 = OpLoad %13 %21
+%152 = OpSampledImage %27 %151 %26
+%153 = OpImageSampleImplicitLod %v4float %152 %32
+OpBranch %148
+%150 = OpLabel
+%154 = OpBitcast %uint %19
+%155 = OpFunctionCall %void %67 %uint_79 %uint_1 %154 %uint_0
+OpBranch %148
+%148 = OpLabel
+%156 = OpPhi %v4float %153 %149 %122 %150
+OpBranch %60
+%62 = OpLabel
+%66 = OpBitcast %uint %19
+%121 = OpFunctionCall %void %67 %uint_79 %uint_0 %66 %uint_8
+OpBranch %60
+%60 = OpLabel
+%123 = OpPhi %v4float %156 %148 %122 %62
+%36 = OpCompositeExtract %float %123 0
+OpStore %x %36
+%39 = OpLoad %13 %uniformTex
+%40 = OpLoad %23 %uniformSampler
+%41 = OpSampledImage %27 %39 %40
+%42 = OpLoad %v2float %inTexcoord
+%47 = OpAccessChain %_ptr_Uniform_v2float %uniforms %int_0
+%157 = OpFunctionCall %uint %125 %uint_0 %uint_0 %uint_0 %uint_0
+%158 = OpINotEqual %bool %157 %uint_0
+OpSelectionMerge %159 None
+OpBranchConditional %158 %160 %161
+%160 = OpLabel
+%162 = OpLoad %v2float %47
+OpBranch %159
+%161 = OpLabel
+%164 = OpFunctionCall %void %67 %uint_87 %uint_1 %uint_0 %uint_0
+OpBranch %159
+%159 = OpLabel
+%166 = OpPhi %v2float %162 %160 %165 %161
+%49 = OpFMul %v2float %42 %166
+%167 = OpSampledImage %27 %39 %40
+%168 = OpFunctionCall %uint %125 %uint_0 %uint_0 %uint_2 %uint_0
+%169 = OpINotEqual %bool %168 %uint_0
+OpSelectionMerge %170 None
+OpBranchConditional %169 %171 %172
+%171 = OpLabel
+%173 = OpLoad %13 %uniformTex
+%174 = OpSampledImage %27 %173 %40
+%175 = OpImageSampleImplicitLod %v4float %174 %49
+OpBranch %170
+%172 = OpLabel
+%177 = OpFunctionCall %void %67 %uint_89 %uint_1 %uint_0 %uint_0
+OpBranch %170
+%170 = OpLabel
+%178 = OpPhi %v4float %175 %171 %122 %172
+%51 = OpCompositeExtract %float %178 0
+OpStore %y %51
+%54 = OpLoad %float %x
+%55 = OpLoad %float %y
+%57 = OpCompositeConstruct %v4float %54 %55 %float_0 %float_0
+OpStore %outColor %57
+OpReturn
+OpFunctionEnd
+)";
+
+  const std::string new_funcs =
+      R"(%67 = OpFunction %void None %68
+%69 = OpFunctionParameter %uint
+%70 = OpFunctionParameter %uint
+%71 = OpFunctionParameter %uint
+%72 = OpFunctionParameter %uint
+%73 = OpLabel
+%79 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_0
+%82 = OpAtomicIAdd %uint %79 %uint_4 %uint_0 %uint_10
+%83 = OpIAdd %uint %82 %uint_10
+%84 = OpArrayLength %uint %77 1
+%85 = OpULessThanEqual %bool %83 %84
+OpSelectionMerge %86 None
+OpBranchConditional %85 %87 %86
+%87 = OpLabel
+%88 = OpIAdd %uint %82 %uint_0
+%90 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %88
+OpStore %90 %uint_10
+%92 = OpIAdd %uint %82 %uint_1
+%93 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %92
+OpStore %93 %uint_23
+%95 = OpIAdd %uint %82 %uint_2
+%96 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %95
+OpStore %96 %69
+%98 = OpIAdd %uint %82 %uint_3
+%99 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %98
+OpStore %99 %uint_4
+%102 = OpLoad %v4float %gl_FragCoord
+%104 = OpBitcast %v4uint %102
+%105 = OpCompositeExtract %uint %104 0
+%106 = OpIAdd %uint %82 %uint_4
+%107 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %106
+OpStore %107 %105
+%108 = OpCompositeExtract %uint %104 1
+%110 = OpIAdd %uint %82 %uint_5
+%111 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %110
+OpStore %111 %108
+%113 = OpIAdd %uint %82 %uint_7
+%114 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %113
+OpStore %114 %70
+%115 = OpIAdd %uint %82 %uint_8
+%116 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %115
+OpStore %116 %71
+%118 = OpIAdd %uint %82 %uint_9
+%119 = OpAccessChain %_ptr_StorageBuffer_uint %77 %uint_1 %118
+OpStore %119 %72
+OpBranch %86
+%86 = OpLabel
+OpReturn
+OpFunctionEnd
+%125 = OpFunction %uint None %126
+%127 = OpFunctionParameter %uint
+%128 = OpFunctionParameter %uint
+%129 = OpFunctionParameter %uint
+%130 = OpFunctionParameter %uint
+%131 = OpLabel
+%135 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %127
+%136 = OpLoad %uint %135
+%137 = OpIAdd %uint %136 %128
+%138 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %137
+%139 = OpLoad %uint %138
+%140 = OpIAdd %uint %139 %129
+%141 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %140
+%142 = OpLoad %uint %141
+%143 = OpIAdd %uint %142 %130
+%144 = OpAccessChain %_ptr_StorageBuffer_uint %134 %uint_0 %143
+%145 = OpLoad %uint %144
+OpReturnValue %145
+OpFunctionEnd
+)";
+
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndCheck<InstBindlessCheckPass>(
+      defs_before + func_before, defs_after + func_after + new_funcs, true,
+      true, 7u, 23u, true, true, 2u);
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //   Compute shader