spirv-reader (AST): split combined image samplers

Add end-to-end reader tests using input SPIR-V from unit tests for the two
spirv-opt transforms.  These are all expected to be readable now.

Update the dawn unit tests:
- a combined-image-sampler test now passes
- add an array-of-combined-image-sampler test that fails

Bug: 398231475
Change-Id: I3c906fb75b7eb66ecaa76d33d1d1e3b8246bf803
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/231534
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Auto-Submit: David Neto <dneto@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/dawn/tests/unittests/validation/ShaderModuleValidationTests.cpp b/src/dawn/tests/unittests/validation/ShaderModuleValidationTests.cpp
index 37bc486..8f8658b 100644
--- a/src/dawn/tests/unittests/validation/ShaderModuleValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/ShaderModuleValidationTests.cpp
@@ -73,7 +73,11 @@
     utils::CreateShaderModuleFromASM(device, shader);
 }
 
-// Test that it is not allowed to use combined texture and sampler.
+// Tint's SPIR-V reader transforms a combined image sampler into two
+// variables: an image part and a sampler part.  The sampler part's binding
+// number is incremented. This may produce a conflict, which is solved
+// by iterating further binding increments.  It's easy to use in simple cases:
+// a sampled image variable effectively takes up two binding slots.
 TEST_F(ShaderModuleValidationTest, CombinedTextureAndSampler) {
     // SPIR-V ASM produced by glslang for the following fragment shader:
     //
@@ -111,6 +115,44 @@
                OpFunctionEnd
         )";
 
+    utils::CreateShaderModuleFromASM(device, shader);
+}
+
+TEST_F(ShaderModuleValidationTest, ArrayOfCombinedTextureAndSampler) {
+    // SPIR-V ASM produced by glslang for the following fragment shader:
+    //
+    //   #version 450
+    //   layout(set = 0, binding = 0) uniform sampler2D tex[2];
+    //   void main () {}
+    //
+    // Dawn/WebGPU does not yet support arrays of sampled images.
+    const char* shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main"
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %tex "tex"
+               OpDecorate %tex Binding 0
+               OpDecorate %tex DescriptorSet 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+          %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
+          %8 = OpTypeSampledImage %7
+       %uint = OpTypeInt 32 0
+     %uint_2 = OpConstant %uint 2
+%_arr_8_uint_2 = OpTypeArray %8 %uint_2
+%_ptr_UniformConstant__arr_8_uint_2 = OpTypePointer UniformConstant %_arr_8_uint_2
+        %tex = OpVariable %_ptr_UniformConstant__arr_8_uint_2 UniformConstant
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+        )";
+
     ASSERT_DEVICE_ERROR(utils::CreateShaderModuleFromASM(device, shader));
 }
 
diff --git a/src/tint/lang/spirv/reader/ast_parser/BUILD.bazel b/src/tint/lang/spirv/reader/ast_parser/BUILD.bazel
index 35e1a22..c67f190 100644
--- a/src/tint/lang/spirv/reader/ast_parser/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/ast_parser/BUILD.bazel
@@ -96,6 +96,7 @@
     ":tint_build_spv_reader_or_tint_build_spv_writer": [
       "@spirv_headers//:spirv_cpp11_headers", "@spirv_headers//:spirv_c_headers",
       "@spirv_tools//:spirv_tools_opt",
+      "@spirv_tools",
     ],
     "//conditions:default": [],
   }),
diff --git a/src/tint/lang/spirv/reader/ast_parser/BUILD.cmake b/src/tint/lang/spirv/reader/ast_parser/BUILD.cmake
index 61a79da..8bc80db 100644
--- a/src/tint/lang/spirv/reader/ast_parser/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/ast_parser/BUILD.cmake
@@ -103,6 +103,7 @@
   tint_target_add_external_dependencies(tint_lang_spirv_reader_ast_parser lib
     "spirv-headers"
     "spirv-opt-internal"
+    "spirv-tools"
   )
 endif(TINT_BUILD_SPV_READER OR TINT_BUILD_SPV_WRITER)
 
diff --git a/src/tint/lang/spirv/reader/ast_parser/BUILD.gn b/src/tint/lang/spirv/reader/ast_parser/BUILD.gn
index 359f2b6..fe367ef 100644
--- a/src/tint/lang/spirv/reader/ast_parser/BUILD.gn
+++ b/src/tint/lang/spirv/reader/ast_parser/BUILD.gn
@@ -103,8 +103,10 @@
       deps += [
         "${tint_spirv_headers_dir}:spv_headers",
         "${tint_spirv_tools_dir}:spvtools",
+        "${tint_spirv_tools_dir}:spvtools_headers",
         "${tint_spirv_tools_dir}:spvtools_opt",
         "${tint_spirv_tools_dir}:spvtools_val",
+        "${tint_spirv_tools_dir}:spvtools_val",
       ]
     }
     public_configs = [ "${tint_spirv_tools_dir}/:spvtools_internal_config" ]
diff --git a/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc b/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
index 930a6c7..509a914 100644
--- a/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
@@ -33,6 +33,7 @@
 #include <utility>
 
 #include "source/opt/build_module.h"
+#include "spirv-tools/optimizer.hpp"
 #include "src/tint/lang/core/fluent_types.h"
 #include "src/tint/lang/core/type/depth_texture.h"
 #include "src/tint/lang/core/type/multisampled_texture.h"
@@ -337,6 +338,22 @@
         success_ = false;
         return false;
     }
+
+    // Split combined-image-samplers into separate image and sampler parts.
+    // Sampler bindings numbers get incremented. The increments are propagated
+    // among resource variaables until settling occurs.
+    {
+        spvtools::Optimizer optimizer(kInputEnv);
+        optimizer.SetMessageConsumer(message_consumer_);
+        optimizer.RegisterPass(spvtools::CreateSplitCombinedImageSamplerPass());
+        optimizer.RegisterPass(spvtools::CreateResolveBindingConflictsPass());
+        std::vector<uint32_t> new_binary;
+        if (!optimizer.Run(spv_binary_.data(), spv_binary_.size(), &new_binary)) {
+            return false;
+        }
+        spv_binary_ = std::move(new_binary);
+    }
+
     if (!BuildInternalModule()) {
         return false;
     }
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_0.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_0.spvasm
new file mode 100644
index 0000000..efd0f8a
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_0.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_1.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_1.spvasm
new file mode 100644
index 0000000..127492f
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_1.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_10.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_10.spvasm
new file mode 100644
index 0000000..194624e
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_10.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_11.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_11.spvasm
new file mode 100644
index 0000000..09d5763
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_11.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_12.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_12.spvasm
new file mode 100644
index 0000000..017a327
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_12.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_13.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_13.spvasm
new file mode 100644
index 0000000..2f287de
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_13.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_14.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_14.spvasm
new file mode 100644
index 0000000..9af8b50
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_14.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_15.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_15.spvasm
new file mode 100644
index 0000000..21af6b7
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_15.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_17.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_17.spvasm
new file mode 100644
index 0000000..86ff9ad
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_17.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_18.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_18.spvasm
new file mode 100644
index 0000000..d7b67d7
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_18.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_19.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_19.spvasm
new file mode 100644
index 0000000..685eb9c
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_19.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_2.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_2.spvasm
new file mode 100644
index 0000000..efeac2c
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_2.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_20.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_20.spvasm
new file mode 100644
index 0000000..d8f9e99
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_20.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_21.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_21.spvasm
new file mode 100644
index 0000000..a6696cb
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_21.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_22.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_22.spvasm
new file mode 100644
index 0000000..0ac0b6e
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_22.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_23.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_23.spvasm
new file mode 100644
index 0000000..18ef056
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_23.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_24.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_24.spvasm
new file mode 100644
index 0000000..4e9ec69
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_24.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_25.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_25.spvasm
new file mode 100644
index 0000000..a512ce3
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_25.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_26.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_26.spvasm
new file mode 100644
index 0000000..c0e2750
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_26.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_28.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_28.spvasm
new file mode 100644
index 0000000..f708b27
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_28.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_29.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_29.spvasm
new file mode 100644
index 0000000..c08fc68
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_29.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_3.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_3.spvasm
new file mode 100644
index 0000000..afc9e44
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_3.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_30.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_30.spvasm
new file mode 100644
index 0000000..a118c89
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_30.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_31.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_31.spvasm
new file mode 100644
index 0000000..1139852
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_31.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_32.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_32.spvasm
new file mode 100644
index 0000000..5c7de73
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_32.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_4.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_4.spvasm
new file mode 100644
index 0000000..413808b
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_4.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_6.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_6.spvasm
new file mode 100644
index 0000000..0c61fb5
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_6.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_7.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_7.spvasm
new file mode 100644
index 0000000..a1c53d4
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_7.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_8.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_8.spvasm
new file mode 100644
index 0000000..e561acb
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_8.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_9.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_9.spvasm
new file mode 100644
index 0000000..d4cb4b0
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_DeletesCopyObjectOfPtr_9.spvasm
@@ -0,0 +1,71 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpCopyObject %_ptr_UniformConstant_11 %100
+        %102 = OpLoad %11 %101
+        %103 = OpCopyObject %_ptr_UniformConstant_11 %101
+        %104 = OpCopyObject %11 %102 ;; this copy survives
+               OpReturn
+               OpFunctionEnd
+
+     ; The OpCopyObject instructions are removed.
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The only OpCopyObject that remains is the copy
+     ; of the copy of the sampled image value.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %[[si:\d+]] = OpSampledImage %11 %[[im]] %[[s]]
+     ; CHECK-NEXT: OpCopyObject %11 %[[si]]
+     ; CHECK-NEXT: OpReturn
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_0.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_0.spvasm
new file mode 100644
index 0000000..0b2fff1
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_0.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_1.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_1.spvasm
new file mode 100644
index 0000000..fba2fe9
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_1.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_10.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_10.spvasm
new file mode 100644
index 0000000..f76c01f
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_10.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_11.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_11.spvasm
new file mode 100644
index 0000000..c323a55
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_11.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_12.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_12.spvasm
new file mode 100644
index 0000000..05de526
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_12.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_13.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_13.spvasm
new file mode 100644
index 0000000..000be8b
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_13.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_14.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_14.spvasm
new file mode 100644
index 0000000..57456c1
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_14.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_15.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_15.spvasm
new file mode 100644
index 0000000..45cd46b
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_15.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_17.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_17.spvasm
new file mode 100644
index 0000000..a303192
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_17.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_18.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_18.spvasm
new file mode 100644
index 0000000..a024a20
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_18.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_19.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_19.spvasm
new file mode 100644
index 0000000..e5fb4ba
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_19.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_2.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_2.spvasm
new file mode 100644
index 0000000..1f4f760
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_2.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_20.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_20.spvasm
new file mode 100644
index 0000000..a65b985
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_20.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_21.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_21.spvasm
new file mode 100644
index 0000000..8f458fb
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_21.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_22.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_22.spvasm
new file mode 100644
index 0000000..866f472
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_22.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_23.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_23.spvasm
new file mode 100644
index 0000000..f61f40c
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_23.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_24.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_24.spvasm
new file mode 100644
index 0000000..5222d1d
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_24.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_25.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_25.spvasm
new file mode 100644
index 0000000..100209f
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_25.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_26.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_26.spvasm
new file mode 100644
index 0000000..f37bf91
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_26.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_28.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_28.spvasm
new file mode 100644
index 0000000..e38060c
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_28.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_29.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_29.spvasm
new file mode 100644
index 0000000..0165403
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_29.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_3.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_3.spvasm
new file mode 100644
index 0000000..450b798
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_3.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_30.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_30.spvasm
new file mode 100644
index 0000000..e8d5e03
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_30.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_31.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_31.spvasm
new file mode 100644
index 0000000..6977850
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_31.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_32.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_32.spvasm
new file mode 100644
index 0000000..4829c26
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_32.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_4.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_4.spvasm
new file mode 100644
index 0000000..a25e547
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_4.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_6.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_6.spvasm
new file mode 100644
index 0000000..c4ee6b6
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_6.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_7.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_7.spvasm
new file mode 100644
index 0000000..41acfe1
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_7.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_8.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_8.spvasm
new file mode 100644
index 0000000..75bb43e
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_8.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_9.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_9.spvasm
new file mode 100644
index 0000000..f286020
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_9.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_0.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_0.spvasm
new file mode 100644
index 0000000..a0040e1
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_0.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_1.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_1.spvasm
new file mode 100644
index 0000000..44aa899
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_1.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_10.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_10.spvasm
new file mode 100644
index 0000000..d3206ee
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_10.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_11.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_11.spvasm
new file mode 100644
index 0000000..6921757
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_11.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_12.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_12.spvasm
new file mode 100644
index 0000000..919562b
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_12.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_13.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_13.spvasm
new file mode 100644
index 0000000..ca8336d
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_13.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_14.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_14.spvasm
new file mode 100644
index 0000000..a7230a8
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_14.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_15.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_15.spvasm
new file mode 100644
index 0000000..6901d5c
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_15.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_17.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_17.spvasm
new file mode 100644
index 0000000..691fd04
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_17.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_18.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_18.spvasm
new file mode 100644
index 0000000..2958ad8
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_18.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_19.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_19.spvasm
new file mode 100644
index 0000000..62982b4
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_19.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_2.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_2.spvasm
new file mode 100644
index 0000000..a53f5dc
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_2.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_20.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_20.spvasm
new file mode 100644
index 0000000..88b8c45
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_20.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_21.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_21.spvasm
new file mode 100644
index 0000000..22404db
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_21.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_22.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_22.spvasm
new file mode 100644
index 0000000..99acfef
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_22.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_23.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_23.spvasm
new file mode 100644
index 0000000..6e23bed
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_23.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_24.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_24.spvasm
new file mode 100644
index 0000000..4e9411e
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_24.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_25.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_25.spvasm
new file mode 100644
index 0000000..81399ae
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_25.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_26.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_26.spvasm
new file mode 100644
index 0000000..25c8168
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_26.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_28.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_28.spvasm
new file mode 100644
index 0000000..6e5efc2
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_28.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_29.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_29.spvasm
new file mode 100644
index 0000000..bb67189
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_29.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_3.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_3.spvasm
new file mode 100644
index 0000000..b23904c
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_3.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_30.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_30.spvasm
new file mode 100644
index 0000000..a054203
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_30.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_31.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_31.spvasm
new file mode 100644
index 0000000..f5a53a5
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_31.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_32.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_32.spvasm
new file mode 100644
index 0000000..f2d4a8e
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_32.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_4.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_4.spvasm
new file mode 100644
index 0000000..f5ec33d
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_4.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_6.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_6.spvasm
new file mode 100644
index 0000000..4a355ed
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_6.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_7.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_7.spvasm
new file mode 100644
index 0000000..97c1346
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_7.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_8.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_8.spvasm
new file mode 100644
index 0000000..999dce1
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_8.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_9.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_9.spvasm
new file mode 100644
index 0000000..7e67eeb
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnLoadCopied_9.spvasm
@@ -0,0 +1,77 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %combined RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+
+     ; This is what we are checking in this test.
+     ; CHECK: OpDecorate %[[im:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[s:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation. The new loads get the same decorations that the
+     ; original load had.
+     ; CHECK: %[[im]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_0.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_0.spvasm
new file mode 100644
index 0000000..d5e61fa
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_0.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_1.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_1.spvasm
new file mode 100644
index 0000000..57fc15a
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_1.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_10.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_10.spvasm
new file mode 100644
index 0000000..6db7c5f
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_10.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_11.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_11.spvasm
new file mode 100644
index 0000000..4682a80
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_11.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_12.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_12.spvasm
new file mode 100644
index 0000000..40dd3e2
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_12.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_13.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_13.spvasm
new file mode 100644
index 0000000..ccc1880
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_13.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_14.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_14.spvasm
new file mode 100644
index 0000000..0de5938
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_14.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_15.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_15.spvasm
new file mode 100644
index 0000000..216d24e
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_15.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_17.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_17.spvasm
new file mode 100644
index 0000000..812b22f
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_17.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_18.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_18.spvasm
new file mode 100644
index 0000000..10a5a60
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_18.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_19.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_19.spvasm
new file mode 100644
index 0000000..a0ab820
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_19.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_2.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_2.spvasm
new file mode 100644
index 0000000..b5d1bfc
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_2.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_20.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_20.spvasm
new file mode 100644
index 0000000..c36fc49
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_20.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_21.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_21.spvasm
new file mode 100644
index 0000000..b019ffa
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_21.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %int Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_22.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_22.spvasm
new file mode 100644
index 0000000..5335535
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_22.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_23.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_23.spvasm
new file mode 100644
index 0000000..7cae0da
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_23.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_24.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_24.spvasm
new file mode 100644
index 0000000..f02a7b4
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_24.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_25.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_25.spvasm
new file mode 100644
index 0000000..1ef65af
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_25.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_26.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_26.spvasm
new file mode 100644
index 0000000..62eb1e2
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_26.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_28.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_28.spvasm
new file mode 100644
index 0000000..13d560a
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_28.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_29.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_29.spvasm
new file mode 100644
index 0000000..cec1784
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_29.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_3.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_3.spvasm
new file mode 100644
index 0000000..f954c6d
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_3.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_30.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_30.spvasm
new file mode 100644
index 0000000..7fab592
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_30.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_31.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_31.spvasm
new file mode 100644
index 0000000..cc881bc
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_31.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_32.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_32.spvasm
new file mode 100644
index 0000000..269a768
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_32.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %uint Cube 1 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_4.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_4.spvasm
new file mode 100644
index 0000000..7f242a3
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_4.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 0 1 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_6.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_6.spvasm
new file mode 100644
index 0000000..a5f2506
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_6.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 3D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_7.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_7.spvasm
new file mode 100644
index 0000000..55f39c9
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_7.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_8.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_8.spvasm
new file mode 100644
index 0000000..7d9ce92
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_8.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 1 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_9.spvasm b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_9.spvasm
new file mode 100644
index 0000000..ee7be5b
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/AllCombinedTypes_SplitCombinedImageSamplerPassTypeCaseTest_Combined_RemapLoad_RelaxedPrecisionOnVarCopied_9.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %100 RelaxedPrecision
+
+     ; CHECK: OpName
+     ; CHECK-NOT: OpDecorate %100
+     ; CHECK: OpDecorate %[[image_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] DescriptorSet 0
+     ; CHECK: OpDecorate %[[image_var]] Binding 0
+     ; CHECK: OpDecorate %[[sampler_var]] Binding 0
+     ; CHECK: OpDecorate %[[image_var:\d+]] RelaxedPrecision
+     ; CHECK: OpDecorate %[[sampler_var:\d+]] RelaxedPrecision
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK-NOT: %100 = OpVariable
+     ; CHECK-NOT: OpVariable _ptr_UniformConstant_11
+     ; CHECK-DAG: %[[sampler_var]] = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %[[image_var]] = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+     ; The load of the combined image+sampler is replaced by a two loads, then
+     ; a combination operation.
+     ; CHECK: %[[im:\d+]] = OpLoad %10 %[[image_var]]
+     ; CHECK: %[[s:\d+]] = OpLoad %[[sampler_ty]] %[[sampler_var]]
+     ; CHECK: %combined = OpSampledImage %11 %[[im]] %[[s]]
+
+               %bool = OpTypeBool ; location marker
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float Cube 0 1 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %100
+
+     ; Uses of the combined image sampler are preserved.
+     ; CHECK: OpCopyObject %11 %combined
+
+          %7 = OpCopyObject %11 %combined
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/EntryPointRemap_SplitCombinedImageSamplerPassEntryPointRemapTest_EntryPoint_Combined_Unused_0.spvasm b/test/tint/unittest/reader/combined_texture_sampler/EntryPointRemap_SplitCombinedImageSamplerPassEntryPointRemapTest_EntryPoint_Combined_Unused_0.spvasm
new file mode 100644
index 0000000..35ab348
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/EntryPointRemap_SplitCombinedImageSamplerPassEntryPointRemapTest_EntryPoint_Combined_Unused_0.spvasm
@@ -0,0 +1,58 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %in_var %out_var
+               OpExecutionMode %main OriginUpperLeft
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+  ; CHECK: OpEntryPoint Fragment %main "main" %in_var %out_var
+  ; These clauses ensure the expected interface is the whole interface.
+  ; CHECK-NOT: %{{\d+}}
+  ; CHECK-NOT: %in_var
+  ; CHECK-NOT: %out_var
+  ; CHECK-NOT: %combined_var
+  ; CHECK: OpExecutionMode %main OriginUpperLeft
+
+  ; The variable disappears.
+  ; CHECK-NOT: %combined_var =
+  ; CHECK: OpFunctionEnd
+                 OpName %combined_var "combined_var"
+                 OpName %in_var "in_var"
+                 OpName %out_var "out_var"
+                 OpDecorate %combined_var DescriptorSet 0
+                 OpDecorate %combined_var Binding 0
+                 OpDecorate %in_var BuiltIn FragCoord
+                 OpDecorate %out_var Location 0
+
+
+                 %bool = OpTypeBool
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+         %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
+           %11 = OpTypeSampledImage %10
+  %_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+       %in_ptr_v4f = OpTypePointer Input %v4float
+       %in_var = OpVariable %in_ptr_v4f Input
+      %out_ptr_v4f = OpTypePointer Output %v4float
+      %out_var = OpVariable %out_ptr_v4f Output
+
+  ; %combined_var is not used!
+  %combined_var = OpVariable %_ptr_UniformConstant_11 UniformConstant
+         %main = OpFunction %void None %voidfn
+       %main_0 = OpLabel
+                 OpReturn
+                 OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/EntryPointRemap_SplitCombinedImageSamplerPassEntryPointRemapTest_EntryPoint_Combined_UsedInShader_0.spvasm b/test/tint/unittest/reader/combined_texture_sampler/EntryPointRemap_SplitCombinedImageSamplerPassEntryPointRemapTest_EntryPoint_Combined_UsedInShader_0.spvasm
new file mode 100644
index 0000000..dd854f7
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/EntryPointRemap_SplitCombinedImageSamplerPassEntryPointRemapTest_EntryPoint_Combined_UsedInShader_0.spvasm
@@ -0,0 +1,68 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %in_var %out_var
+               OpExecutionMode %main OriginUpperLeft
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %combined "combined"
+               OpName %combined_var "combined_var"
+               OpName %in_var "in_var"
+               OpName %out_var "out_var"
+               OpDecorate %combined_var DescriptorSet 0
+               OpDecorate %combined_var Binding 0
+               OpDecorate %in_var BuiltIn FragCoord
+               OpDecorate %out_var Location 0
+
+; CHECK: OpEntryPoint Fragment %main "main" %in_var %out_var
+; These clauses ensure the expected interface is the whole interface.
+; CHECK-NOT: %{{\d+}}
+; CHECK-NOT: %in_var
+; CHECK-NOT: %out_var
+; CHECK-NOT: %combined_var
+; CHECK: OpExecutionMode %main OriginUpperLeft
+
+     ; Check the var names, tracing up through the types.
+     ; CHECK: %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+     ; CHECK-DAG: %combined_var_sampler = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %combined_var_image = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+               %bool = OpTypeBool
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+         %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+     %in_ptr_v4f = OpTypePointer Input %v4float
+     %in_var = OpVariable %in_ptr_v4f Input
+    %out_ptr_v4f = OpTypePointer Output %v4float
+    %out_var = OpVariable %out_ptr_v4f Output
+
+%combined_var = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+       ;CHECK:  %main_0 = OpLabel
+       ;CHECK: OpLoad
+
+     %main_0 = OpLabel
+   %combined = OpLoad %11 %combined_var
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_3.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_3.spvasm
new file mode 100644
index 0000000..dacafa8
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_3.spvasm
@@ -0,0 +1,55 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %_ptr_UniformConstant_sampler_ty "_ptr_UniformConstant_sampler_ty"
+       OpName %_ptr_UniformConstant_image_ty "_ptr_UniformConstant_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+       OpName %dest_ty "dest_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+ %_ptr_UniformConstant_image_ty = OpTypePointer UniformConstant %image_ty
+ %_ptr_UniformConstant_sampler_ty = OpTypePointer UniformConstant %sampler_ty
+
+        %100 = OpTypeFunction %float %sampled_image_ty
+    %dest_ty = OpTypeFunction %float %image_ty %sampler_ty
+
+  ; CHECK: OpTypeSampler
+  ; CHECK-NOT: %100 =
+  ; CHECK: %dest_ty = OpTypeFunction %float %image_ty %sampler_ty
+  ; CHECK-NOT: %100 =
+  ; CHECK: %main = OpFunction
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_4.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_4.spvasm
new file mode 100644
index 0000000..a0e0b21
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_4.spvasm
@@ -0,0 +1,55 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %_ptr_UniformConstant_sampler_ty "_ptr_UniformConstant_sampler_ty"
+       OpName %_ptr_UniformConstant_image_ty "_ptr_UniformConstant_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+       OpName %dest_ty "dest_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+ %_ptr_UniformConstant_image_ty = OpTypePointer UniformConstant %image_ty
+ %_ptr_UniformConstant_sampler_ty = OpTypePointer UniformConstant %sampler_ty
+
+        %100 = OpTypeFunction %float %uint %sampled_image_ty %float
+    %dest_ty = OpTypeFunction %float %uint %image_ty %sampler_ty %float
+
+  ; CHECK: OpTypeSampler
+  ; CHECK-NOT: %100 =
+  ; CHECK: %dest_ty = OpTypeFunction %float %uint %image_ty %sampler_ty %float
+  ; CHECK-NOT: %100 =
+  ; CHECK: %main = OpFunction
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_5.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_5.spvasm
new file mode 100644
index 0000000..895177c
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_5.spvasm
@@ -0,0 +1,55 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %_ptr_UniformConstant_sampler_ty "_ptr_UniformConstant_sampler_ty"
+       OpName %_ptr_UniformConstant_image_ty "_ptr_UniformConstant_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+       OpName %dest_ty "dest_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+ %_ptr_UniformConstant_image_ty = OpTypePointer UniformConstant %image_ty
+ %_ptr_UniformConstant_sampler_ty = OpTypePointer UniformConstant %sampler_ty
+
+        %100 = OpTypeFunction %float %ptr_sampled_image_ty
+    %dest_ty = OpTypeFunction %float %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty
+
+  ; CHECK: OpTypeSampler
+  ; CHECK-NOT: %100 =
+  ; CHECK: %dest_ty = OpTypeFunction %float %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty
+  ; CHECK-NOT: %100 =
+  ; CHECK: %main = OpFunction
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_6.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_6.spvasm
new file mode 100644
index 0000000..bdbbb3a
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_6.spvasm
@@ -0,0 +1,55 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %_ptr_UniformConstant_sampler_ty "_ptr_UniformConstant_sampler_ty"
+       OpName %_ptr_UniformConstant_image_ty "_ptr_UniformConstant_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+       OpName %dest_ty "dest_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+ %_ptr_UniformConstant_image_ty = OpTypePointer UniformConstant %image_ty
+ %_ptr_UniformConstant_sampler_ty = OpTypePointer UniformConstant %sampler_ty
+
+        %100 = OpTypeFunction %float %uint %ptr_sampled_image_ty %float
+    %dest_ty = OpTypeFunction %float %uint %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty %float
+
+  ; CHECK: OpTypeSampler
+  ; CHECK-NOT: %100 =
+  ; CHECK: %dest_ty = OpTypeFunction %float %uint %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty %float
+  ; CHECK-NOT: %100 =
+  ; CHECK: %main = OpFunction
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_7.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_7.spvasm
new file mode 100644
index 0000000..72f9b37
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_AvoidDuplicateType_7.spvasm
@@ -0,0 +1,55 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %_ptr_UniformConstant_sampler_ty "_ptr_UniformConstant_sampler_ty"
+       OpName %_ptr_UniformConstant_image_ty "_ptr_UniformConstant_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+       OpName %dest_ty "dest_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+ %_ptr_UniformConstant_image_ty = OpTypePointer UniformConstant %image_ty
+ %_ptr_UniformConstant_sampler_ty = OpTypePointer UniformConstant %sampler_ty
+
+        %100 = OpTypeFunction %float %uint %ptr_sampled_image_ty %ptr_sampled_image_ty %float
+    %dest_ty = OpTypeFunction %float %uint %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty %float
+
+  ; CHECK: OpTypeSampler
+  ; CHECK-NOT: %100 =
+  ; CHECK: %dest_ty = OpTypeFunction %float %uint %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty %float
+  ; CHECK-NOT: %100 =
+  ; CHECK: %main = OpFunction
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_0.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_0.spvasm
new file mode 100644
index 0000000..4b92259
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_0.spvasm
@@ -0,0 +1,46 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %f_ty "f_ty"
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+
+       %f_ty = OpTypeFunction %float
+
+  ; CHECK: %f_ty = OpTypeFunction %float
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_1.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_1.spvasm
new file mode 100644
index 0000000..01d8883
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_1.spvasm
@@ -0,0 +1,46 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %f_ty "f_ty"
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+
+       %f_ty = OpTypeFunction %float %image_ty
+
+  ; CHECK: %f_ty = OpTypeFunction %float %image_ty
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_2.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_2.spvasm
new file mode 100644
index 0000000..f07bf49
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_2.spvasm
@@ -0,0 +1,46 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %f_ty "f_ty"
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+
+       %f_ty = OpTypeFunction %float %sampler_ty
+
+  ; CHECK: %f_ty = OpTypeFunction %float %sampler_ty
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_3.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_3.spvasm
new file mode 100644
index 0000000..0a5997e
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_3.spvasm
@@ -0,0 +1,46 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %f_ty "f_ty"
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+
+       %f_ty = OpTypeFunction %float %sampled_image_ty
+
+  ; CHECK: %f_ty = OpTypeFunction %float %image_ty %sampler_ty
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_4.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_4.spvasm
new file mode 100644
index 0000000..adf93d6
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_4.spvasm
@@ -0,0 +1,46 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %f_ty "f_ty"
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+
+       %f_ty = OpTypeFunction %float %uint %sampled_image_ty %float
+
+  ; CHECK: %f_ty = OpTypeFunction %float %uint %image_ty %sampler_ty %float
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_5.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_5.spvasm
new file mode 100644
index 0000000..766ccc1
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_5.spvasm
@@ -0,0 +1,46 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %f_ty "f_ty"
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+
+       %f_ty = OpTypeFunction %float %ptr_sampled_image_ty
+
+  ; CHECK: %f_ty = OpTypeFunction %float %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_6.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_6.spvasm
new file mode 100644
index 0000000..91744cd
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_6.spvasm
@@ -0,0 +1,46 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %f_ty "f_ty"
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+
+       %f_ty = OpTypeFunction %float %uint %ptr_sampled_image_ty %float
+
+  ; CHECK: %f_ty = OpTypeFunction %float %uint %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty %float
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_7.spvasm b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_7.spvasm
new file mode 100644
index 0000000..32f5443
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/FunctionTypeRemap_SplitCombinedImageSamplerPassFunctionTypeTest_ReplaceCombinedImageSamplersOnly_7.spvasm
@@ -0,0 +1,46 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %f_ty "f_ty"
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %ptr_sampled_image_ty "sampled_image_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+ %ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
+
+       %f_ty = OpTypeFunction %float %uint %ptr_sampled_image_ty %ptr_sampled_image_ty %float
+
+  ; CHECK: %f_ty = OpTypeFunction %float %uint %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty %_ptr_UniformConstant_image_ty %_ptr_UniformConstant_sampler_ty %float
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_ConflictCascade_Resolves.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_ConflictCascade_Resolves.spvasm
new file mode 100644
index 0000000..68a1f24
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_ConflictCascade_Resolves.spvasm
@@ -0,0 +1,107 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %alpha "alpha"
+               OpEntryPoint GLCompute %beta "beta"
+               OpEntryPoint GLCompute %gamma "gamma"
+               OpEntryPoint GLCompute %delta "delta"
+               OpExecutionMode %alpha LocalSize 1 1 1
+               OpExecutionMode %beta LocalSize 1 1 1
+               OpExecutionMode %gamma LocalSize 1 1 1
+               OpExecutionMode %delta LocalSize 1 1 1
+               OpName %alpha "alpha"
+               OpName %beta "beta"
+               OpName %gamma "gamma"
+               OpName %delta "delta"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0  ; The sampler
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+               OpDecorate %102 DescriptorSet 0
+               OpDecorate %102 Binding 1
+               OpDecorate %103 DescriptorSet 0
+               OpDecorate %103 Binding 2
+               OpDecorate %104 DescriptorSet 0
+               OpDecorate %104 Binding 3
+
+      ; %100 is bumped once:
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 1
+
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 0
+
+      ; pushed back from bump of %100
+      ; CHECK: OpDecorate %102 DescriptorSet 0
+      ; CHECK: OpDecorate %102 Binding 2
+
+      ; pushed back from bump of %102
+      ; CHECK: OpDecorate %103 DescriptorSet 0
+      ; CHECK: OpDecorate %103 Binding 3
+
+      ; pushed back from bump of %103
+      ; CHECK: OpDecorate %104 DescriptorSet 0
+      ; CHECK: OpDecorate %104 Binding 4
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_s_ty UniformConstant  ; used in alpha, beta
+        %101 = OpVariable %p_i_ty UniformConstant  ; used in alpha
+        %102 = OpVariable %pu_st_ty Uniform        ; used in beta, gamma
+        %103 = OpVariable %pb_st_ty StorageBuffer  ; used in gamma, delta
+        %104 = OpVariable %p_si_ty UniformConstant ; used delta
+
+      %alpha = OpFunction %void None %voidfn
+       %1000 = OpLabel
+       %1001 = OpCopyObject %p_s_ty %100
+       %1002 = OpCopyObject %p_i_ty %101
+               OpReturn
+               OpFunctionEnd
+
+       %beta = OpFunction %void None %voidfn
+       %2000 = OpLabel
+       %2001 = OpCopyObject %p_s_ty %100
+       %2002 = OpCopyObject %pu_st_ty %102
+               OpReturn
+               OpFunctionEnd
+
+      %gamma = OpFunction %void None %voidfn
+       %3000 = OpLabel
+       %3001 = OpCopyObject %pu_st_ty %102
+       %3002 = OpCopyObject %pb_st_ty %103
+               OpReturn
+               OpFunctionEnd
+
+      %delta = OpFunction %void None %voidfn
+       %4000 = OpLabel
+       %4001 = OpCopyObject %pb_st_ty %103
+       %4002 = OpCopyObject %p_si_ty %104
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_ConflictCascade_RevisitEntryPoint.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_ConflictCascade_RevisitEntryPoint.spvasm
new file mode 100644
index 0000000..93c01d1
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_ConflictCascade_RevisitEntryPoint.spvasm
@@ -0,0 +1,89 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %alpha "alpha"
+               OpEntryPoint GLCompute %beta "beta"
+               OpExecutionMode %alpha LocalSize 1 1 1
+               OpExecutionMode %beta LocalSize 1 1 1
+               OpName %alpha "alpha"
+               OpName %beta "beta"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0 ; the sampler
+               OpDecorate %101 Binding 0
+               OpDecorate %102 DescriptorSet 0
+               OpDecorate %102 Binding 1
+               OpDecorate %103 DescriptorSet 0
+               OpDecorate %103 Binding 2
+               OpDecorate %104 DescriptorSet 0
+               OpDecorate %104 Binding 3
+               OpDecorate %105 DescriptorSet 0
+               OpDecorate %105 Binding 4
+
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 0
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 1
+      ; CHECK: OpDecorate %102 DescriptorSet 0
+      ; CHECK: OpDecorate %102 Binding 2
+      ; CHECK: OpDecorate %103 DescriptorSet 0
+      ; CHECK: OpDecorate %103 Binding 3
+      ; CHECK: OpDecorate %104 DescriptorSet 0
+      ; CHECK: OpDecorate %104 Binding 4
+      ; CHECK: OpDecorate %105 DescriptorSet 0
+      ; CHECK: OpDecorate %105 Binding 5
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_i_ty UniformConstant
+        %101 = OpVariable %p_s_ty UniformConstant
+        %102 = OpVariable %pu_st_ty Uniform
+        %103 = OpVariable %pb_st_ty StorageBuffer
+        %104 = OpVariable %p_si_ty UniformConstant
+        %105 = OpVariable %p_s_ty UniformConstant
+
+      %alpha = OpFunction %void None %voidfn
+       %1000 = OpLabel
+       %1001 = OpCopyObject %p_i_ty %100
+       %1002 = OpCopyObject %p_s_ty %101
+       %1003 = OpCopyObject %pb_st_ty %103
+       %1004 = OpCopyObject %p_si_ty %104
+       %1005 = OpCopyObject %p_s_ty %105
+               OpReturn
+               OpFunctionEnd
+
+       %beta = OpFunction %void None %voidfn
+       %2000 = OpLabel
+       %2001 = OpCopyObject %p_s_ty %101
+       %2002 = OpCopyObject %pu_st_ty %102
+       %2003 = OpCopyObject %pb_st_ty %103
+       %2004 = OpCopyObject %p_s_ty %105
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_DuplicatConflicts_ResolvesOnlyOnce.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_DuplicatConflicts_ResolvesOnlyOnce.spvasm
new file mode 100644
index 0000000..8f38350
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_DuplicatConflicts_ResolvesOnlyOnce.spvasm
@@ -0,0 +1,64 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %alpha "alpha"
+               OpEntryPoint GLCompute %beta "beta"
+               OpExecutionMode %alpha LocalSize 1 1 1
+               OpExecutionMode %beta LocalSize 1 1 1
+               OpName %alpha "alpha"
+               OpName %beta "beta"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 1
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 0
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_s_ty UniformConstant
+        %101 = OpVariable %p_i_ty UniformConstant
+
+      %alpha = OpFunction %void None %voidfn
+       %1000 = OpLabel
+       %1001 = OpCopyObject %p_s_ty %100
+       %1002 = OpCopyObject %p_i_ty %101
+               OpReturn
+               OpFunctionEnd
+
+       %beta = OpFunction %void None %voidfn
+       %2000 = OpLabel
+       %2001 = OpCopyObject %p_s_ty %100
+       %2002 = OpCopyObject %p_i_ty %101
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_IndependentConflicts_Resolves.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_IndependentConflicts_Resolves.spvasm
new file mode 100644
index 0000000..db74870
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_IndependentConflicts_Resolves.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %alpha "alpha"
+               OpEntryPoint GLCompute %beta "beta"
+               OpExecutionMode %alpha LocalSize 1 1 1
+               OpExecutionMode %beta LocalSize 1 1 1
+               OpName %alpha "alpha"
+               OpName %beta "beta"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+               OpDecorate %102 DescriptorSet 0
+               OpDecorate %102 Binding 0
+               OpDecorate %103 DescriptorSet 0
+               OpDecorate %103 Binding 0
+
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 1
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 0
+      ; CHECK: OpDecorate %102 DescriptorSet 0
+      ; CHECK: OpDecorate %102 Binding 0
+      ; CHECK: OpDecorate %103 DescriptorSet 0
+      ; CHECK: OpDecorate %103 Binding 1
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_s_ty UniformConstant
+        %101 = OpVariable %p_i_ty UniformConstant
+        %102 = OpVariable %p_i_ty UniformConstant
+        %103 = OpVariable %p_s_ty UniformConstant
+
+      %alpha = OpFunction %void None %voidfn
+       %1000 = OpLabel
+       %1001 = OpCopyObject %p_s_ty %100
+       %1002 = OpCopyObject %p_i_ty %101
+               OpReturn
+               OpFunctionEnd
+
+       %beta = OpFunction %void None %voidfn
+       %2000 = OpLabel
+       %2001 = OpCopyObject %p_i_ty %102
+       %2002 = OpCopyObject %p_s_ty %103
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_SameVarConflictsAcrossMultiEntryPoints_Resolves.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_SameVarConflictsAcrossMultiEntryPoints_Resolves.spvasm
new file mode 100644
index 0000000..8921ad4
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_MultiEntryPoint_SameVarConflictsAcrossMultiEntryPoints_Resolves.spvasm
@@ -0,0 +1,90 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %alpha "alpha"
+               OpEntryPoint GLCompute %beta "beta"
+               OpEntryPoint GLCompute %gamma "gamma"
+               OpExecutionMode %alpha LocalSize 1 1 1
+               OpExecutionMode %beta LocalSize 1 1 1
+               OpExecutionMode %gamma LocalSize 1 1 1
+               OpName %alpha "alpha"
+               OpName %beta "beta"
+               OpName %gamma "gamma"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0  ; The sampler
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+               OpDecorate %102 DescriptorSet 0
+               OpDecorate %102 Binding 1
+               OpDecorate %103 DescriptorSet 0
+               OpDecorate %103 Binding 2
+
+      ; bumped once
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 1
+
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 0
+
+      ; pushed back from bump of %100
+      ; CHECK: OpDecorate %102 DescriptorSet 0
+      ; CHECK: OpDecorate %102 Binding 2
+
+      ; does not need to be bumped
+      ; CHECK: OpDecorate %103 DescriptorSet 0
+      ; CHECK: OpDecorate %103 Binding 2
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_s_ty UniformConstant ; used in alpha, beta, gamma
+        %101 = OpVariable %p_i_ty UniformConstant ; used in alpha
+        %102 = OpVariable %pu_st_ty Uniform       ; used in beta
+        %103 = OpVariable %pb_st_ty StorageBuffer ; used in gamma
+
+      %alpha = OpFunction %void None %voidfn
+       %1000 = OpLabel
+       %1001 = OpCopyObject %p_s_ty %100
+       %1002 = OpCopyObject %p_i_ty %101
+               OpReturn
+               OpFunctionEnd
+
+       %beta = OpFunction %void None %voidfn
+       %2000 = OpLabel
+       %2001 = OpCopyObject %p_s_ty %100
+       %2002 = OpCopyObject %pu_st_ty %102
+               OpReturn
+               OpFunctionEnd
+
+      %gamma = OpFunction %void None %voidfn
+       %3000 = OpLabel
+       %3001 = OpCopyObject %p_s_ty %100
+       %3002 = OpCopyObject %pb_st_ty %103
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_NoBindings_NoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_NoBindings_NoChange.spvasm
new file mode 100644
index 0000000..44f414e
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_NoBindings_NoChange.spvasm
@@ -0,0 +1,36 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+       %main = OpFunction %void None %voidfn
+        %100 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_NoConflict_UnusedVars_NoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_NoConflict_UnusedVars_NoChange.spvasm
new file mode 100644
index 0000000..8435009
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_NoConflict_UnusedVars_NoChange.spvasm
@@ -0,0 +1,69 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+               OpDecorate %102 DescriptorSet 0
+               OpDecorate %102 Binding 0
+               OpDecorate %103 DescriptorSet 0
+               OpDecorate %103 Binding 0
+               OpDecorate %104 DescriptorSet 0
+               OpDecorate %104 Binding 0
+
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 0
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 0
+      ; CHECK: OpDecorate %102 DescriptorSet 0
+      ; CHECK: OpDecorate %102 Binding 0
+      ; CHECK: OpDecorate %103 DescriptorSet 0
+      ; CHECK: OpDecorate %103 Binding 0
+      ; CHECK: OpDecorate %104 DescriptorSet 0
+      ; CHECK: OpDecorate %104 Binding 0
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+ ; Unused variables
+
+        %100 = OpVariable %p_i_ty UniformConstant  ; image
+        %101 = OpVariable %p_s_ty UniformConstant  ; sampler
+        %102 = OpVariable %pu_st_ty Uniform        ; UBO
+        %103 = OpVariable %pb_st_ty StorageBuffer  ; SSBO
+        %104 = OpVariable %p_si_ty UniformConstant ; combined sampled image
+
+       %main = OpFunction %void None %voidfn
+         %10 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_NoConflict_UsedVars_NoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_NoConflict_UsedVars_NoChange.spvasm
new file mode 100644
index 0000000..210779a
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_NoConflict_UsedVars_NoChange.spvasm
@@ -0,0 +1,72 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 1
+               OpDecorate %102 DescriptorSet 0
+               OpDecorate %102 Binding 2
+               OpDecorate %103 DescriptorSet 0
+               OpDecorate %103 Binding 3
+               OpDecorate %110 DescriptorSet 1
+               OpDecorate %110 Binding 0
+
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 0
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 1
+      ; CHECK: OpDecorate %102 DescriptorSet 0
+      ; CHECK: OpDecorate %102 Binding 2
+      ; CHECK: OpDecorate %103 DescriptorSet 0
+      ; CHECK: OpDecorate %103 Binding 3
+      ; CHECK: OpDecorate %110 DescriptorSet 1
+      ; CHECK: OpDecorate %110 Binding 0
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_i_ty UniformConstant  ; image
+        %101 = OpVariable %p_s_ty UniformConstant  ; sampler
+        %102 = OpVariable %pu_st_ty Uniform        ; UBO
+        %103 = OpVariable %pb_st_ty StorageBuffer  ; SSBO
+        %110 = OpVariable %p_si_ty UniformConstant ; combined sampled image
+
+       %main = OpFunction %void None %voidfn
+         %10 = OpLabel
+         %11 = OpCopyObject %p_i_ty %100
+         %12 = OpCopyObject %p_s_ty %101
+         %13 = OpCopyObject %pu_st_ty %102
+         %14 = OpCopyObject %pb_st_ty %103
+         %15 = OpCopyObject %p_si_ty %110
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_Conflict_RippleStopsAtFirstHole.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_Conflict_RippleStopsAtFirstHole.spvasm
new file mode 100644
index 0000000..a23e8a6
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_Conflict_RippleStopsAtFirstHole.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+               OpDecorate %102 DescriptorSet 0
+               OpDecorate %102 Binding 1
+               ; Leave a hole at (0, 2)
+               OpDecorate %103 DescriptorSet 0
+               OpDecorate %103 Binding 3
+               OpDecorate %104 DescriptorSet 0
+               OpDecorate %104 Binding 4
+
+      ; There was a hole at binding 2.  The ripple stops there.
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 1
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 0
+      ; CHECK: OpDecorate %102 DescriptorSet 0
+      ; CHECK: OpDecorate %102 Binding 2
+      ; CHECK: OpDecorate %103 DescriptorSet 0
+      ; CHECK: OpDecorate %103 Binding 3
+      ; CHECK: OpDecorate %104 DescriptorSet 0
+      ; CHECK: OpDecorate %104 Binding 4
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_s_ty UniformConstant ; sampler comes first
+        %101 = OpVariable %p_i_ty UniformConstant
+        %102 = OpVariable %pu_st_ty Uniform
+        %103 = OpVariable %pb_st_ty StorageBuffer
+        %104 = OpVariable %p_si_ty UniformConstant
+
+       %main = OpFunction %void None %voidfn
+         %10 = OpLabel
+         %11 = OpCopyObject %p_s_ty %100
+         %12 = OpCopyObject %p_i_ty %101
+         %13 = OpCopyObject %pu_st_ty %102
+         %14 = OpCopyObject %pb_st_ty %103
+         %15 = OpCopyObject %p_si_ty %104
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_Conflict_Ripples.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_Conflict_Ripples.spvasm
new file mode 100644
index 0000000..2079d3f
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_Conflict_Ripples.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+               OpDecorate %102 DescriptorSet 0
+               OpDecorate %102 Binding 1
+               OpDecorate %103 DescriptorSet 0
+               OpDecorate %103 Binding 2
+               OpDecorate %104 DescriptorSet 0
+               OpDecorate %104 Binding 3
+
+      ; The sampler's binding number is incremented, and later
+      ; bindings move out of the way.
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 1
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 0
+      ; CHECK: OpDecorate %102 DescriptorSet 0
+      ; CHECK: OpDecorate %102 Binding 2
+      ; CHECK: OpDecorate %103 DescriptorSet 0
+      ; CHECK: OpDecorate %103 Binding 3
+      ; CHECK: OpDecorate %104 DescriptorSet 0
+      ; CHECK: OpDecorate %104 Binding 4
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_s_ty UniformConstant ; sampler comes first
+        %101 = OpVariable %p_i_ty UniformConstant
+        %102 = OpVariable %pu_st_ty Uniform
+        %103 = OpVariable %pb_st_ty StorageBuffer
+        %104 = OpVariable %p_si_ty UniformConstant
+
+       %main = OpFunction %void None %voidfn
+         %10 = OpLabel
+         %11 = OpCopyObject %p_s_ty %100
+         %12 = OpCopyObject %p_i_ty %101
+         %13 = OpCopyObject %pu_st_ty %102
+         %14 = OpCopyObject %pb_st_ty %103
+         %15 = OpCopyObject %p_si_ty %104
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_MultiConflict_ComplexCallGraph_Resolves.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_MultiConflict_ComplexCallGraph_Resolves.spvasm
new file mode 100644
index 0000000..00620f3
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_MultiConflict_ComplexCallGraph_Resolves.spvasm
@@ -0,0 +1,106 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+               OpDecorate %102 DescriptorSet 0
+               OpDecorate %102 Binding 1
+               OpDecorate %103 DescriptorSet 0
+               OpDecorate %103 Binding 1
+               OpDecorate %104 DescriptorSet 0
+               OpDecorate %104 Binding 2
+
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 1
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 0
+      ; CHECK: OpDecorate %102 DescriptorSet 0
+      ; CHECK: OpDecorate %102 Binding 2
+      ; CHECK: OpDecorate %103 DescriptorSet 0
+      ; CHECK: OpDecorate %103 Binding 3
+      ; CHECK: OpDecorate %104 DescriptorSet 0
+      ; CHECK: OpDecorate %104 Binding 4
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_s_ty UniformConstant ; used in %200
+        %101 = OpVariable %p_i_ty UniformConstant ; used in %300, %400
+        %102 = OpVariable %p_i_ty UniformConstant ; used in %500
+        %103 = OpVariable %p_s_ty UniformConstant ; used in %400 twice
+        %104 = OpVariable %pu_st_ty Uniform       ; used in %600
+
+        %200 = OpFunction %void None %voidfn
+        %201 = OpLabel
+        %202 = OpCopyObject %p_s_ty %100
+               OpReturn
+               OpFunctionEnd
+
+        %300 = OpFunction %void None %voidfn
+        %301 = OpLabel
+        %302 = OpCopyObject %p_i_ty %101
+               OpReturn
+               OpFunctionEnd
+
+        %400 = OpFunction %void None %voidfn
+        %401 = OpLabel
+        %402 = OpFunctionCall %void %200
+        %403 = OpCopyObject %p_s_ty %103
+        %404 = OpCopyObject %p_i_ty %101
+        %405 = OpCopyObject %p_s_ty %103
+        %406 = OpFunctionCall %void %300
+               OpReturn
+               OpFunctionEnd
+
+        %500 = OpFunction %void None %voidfn
+        %501 = OpLabel
+        %502 = OpFunctionCall %void %400
+        %503 = OpCopyObject %p_i_ty %102
+        %504 = OpFunctionCall %void %300
+               OpReturn
+               OpFunctionEnd
+
+        %600 = OpFunction %void None %voidfn
+        %601 = OpLabel
+        %602 = OpFunctionCall %void %300
+        %603 = OpFunctionCall %void %500
+        %604 = OpCopyObject %pu_st_ty %104
+               OpReturn
+               OpFunctionEnd
+
+       %main = OpFunction %void None %voidfn
+       %1000 = OpLabel
+       %1001 = OpFunctionCall %void %600
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_MultiConflict_Resolves.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_MultiConflict_Resolves.spvasm
new file mode 100644
index 0000000..fae0955
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_MultiConflict_Resolves.spvasm
@@ -0,0 +1,73 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+      ; Two conflicts: at Bindings 0, and 1
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+               OpDecorate %102 DescriptorSet 0
+               OpDecorate %102 Binding 1
+               OpDecorate %103 DescriptorSet 0
+               OpDecorate %103 Binding 1
+               OpDecorate %104 DescriptorSet 0
+               OpDecorate %104 Binding 2
+
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 1
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 0
+      ; CHECK: OpDecorate %102 DescriptorSet 0
+      ; CHECK: OpDecorate %102 Binding 2
+      ; CHECK: OpDecorate %103 DescriptorSet 0
+      ; CHECK: OpDecorate %103 Binding 3
+      ; CHECK: OpDecorate %104 DescriptorSet 0
+      ; CHECK: OpDecorate %104 Binding 4
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_s_ty UniformConstant ; sampler first
+        %101 = OpVariable %p_i_ty UniformConstant
+        %102 = OpVariable %p_i_ty UniformConstant
+        %103 = OpVariable %p_s_ty UniformConstant ; sampler second
+        %104 = OpVariable %pu_st_ty Uniform
+
+       %main = OpFunction %void None %voidfn
+         %10 = OpLabel
+         %11 = OpCopyObject %p_s_ty %100
+         %12 = OpCopyObject %p_i_ty %101
+         %13 = OpCopyObject %p_i_ty %102
+         %14 = OpCopyObject %p_s_ty %103
+         %15 = OpCopyObject %pu_st_ty %104
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_SamplerFirstConflict_Resolves.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_SamplerFirstConflict_Resolves.spvasm
new file mode 100644
index 0000000..f15866e
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_SamplerFirstConflict_Resolves.spvasm
@@ -0,0 +1,55 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+
+      ; The sampler's binding number is incremented, even when listed first.
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 1
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 0
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_s_ty UniformConstant ; sampler listed first
+        %101 = OpVariable %p_i_ty UniformConstant
+
+       %main = OpFunction %void None %voidfn
+         %10 = OpLabel
+         %11 = OpCopyObject %p_s_ty %100
+         %12 = OpCopyObject %p_i_ty %101
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_SamplerSecondConflict_Resolves.spvasm b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_SamplerSecondConflict_Resolves.spvasm
new file mode 100644
index 0000000..b4299aa
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/ResolveBindingConflictsTest_OneEntryPoint_SamplerSecondConflict_Resolves.spvasm
@@ -0,0 +1,55 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %voidfn "voidfn"
+               OpName %s_ty "s_ty"
+               OpName %i_ty "i_ty"
+               OpName %si_ty "si_ty"
+               OpName %p_s_ty "p_s_ty"
+               OpName %p_i_ty "p_i_ty"
+               OpName %p_si_ty "p_si_ty"
+               OpName %st_ty "st_ty"
+               OpName %pu_st_ty "pu_st_ty"
+               OpName %pb_st_ty "pb_st_ty"
+
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+               OpDecorate %101 DescriptorSet 0
+               OpDecorate %101 Binding 0
+
+      ; The sampler's binding number is incremented, even when listed second.
+      ; CHECK: OpDecorate %100 DescriptorSet 0
+      ; CHECK: OpDecorate %100 Binding 0
+      ; CHECK: OpDecorate %101 DescriptorSet 0
+      ; CHECK: OpDecorate %101 Binding 1
+
+               OpDecorate %st_ty Block
+               OpMemberDecorate %st_ty 0 Offset 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+       %s_ty = OpTypeSampler
+       %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %si_ty = OpTypeSampledImage %i_ty
+     %p_i_ty = OpTypePointer UniformConstant %i_ty
+     %p_s_ty = OpTypePointer UniformConstant %s_ty
+    %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %st_ty = OpTypeStruct %uint
+   %pu_st_ty = OpTypePointer Uniform %st_ty
+   %pb_st_ty = OpTypePointer StorageBuffer %st_ty
+
+
+        %100 = OpVariable %p_i_ty UniformConstant
+        %101 = OpVariable %p_s_ty UniformConstant ; sampler listed second
+
+       %main = OpFunction %void None %voidfn
+         %10 = OpLabel
+         %11 = OpCopyObject %p_i_ty %100
+         %12 = OpCopyObject %p_s_ty %101
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_Combined_NoSampler_CreatedBeforeSampledImage.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_Combined_NoSampler_CreatedBeforeSampledImage.spvasm
new file mode 100644
index 0000000..16a8f23
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_Combined_NoSampler_CreatedBeforeSampledImage.spvasm
@@ -0,0 +1,44 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+
+     ; A sampler type is created and placed at the start of types.
+     ; CHECK: OpDecorate %{{\d+}} Binding 0
+     ; CHECK: OpDecorate %{{\d+}} Binding 0
+     ; CHECK-NOT: TypeSampledImage
+     ; CHECK: TypeSampler
+     ; CHECK: TypeSampledImage
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+ %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+        %100 = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+          %6 = OpLoad %11 %100
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_Combined_SynthesizeVarNames.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_Combined_SynthesizeVarNames.spvasm
new file mode 100644
index 0000000..d393ae2
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_Combined_SynthesizeVarNames.spvasm
@@ -0,0 +1,65 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+               OpName %orig_var "orig_var"
+               OpDecorate %orig_var DescriptorSet 0
+               OpDecorate %orig_var Binding 0
+
+     ; The combined image variable is replaced by an image variable and a sampler variable.
+
+     ; CHECK: OpCapability
+     ; The original name is deleted
+     ; CHECK-NOT: OpName %orig_var "
+     ; CHECK: OpName %orig_var_image "orig_var_image"
+     ; CHECK: OpName %orig_var_sampler "orig_var_sampler"
+     ; CHECK-NOT: OpName %orig_var "
+
+     ; CHECK: OpDecorate %orig_var_image DescriptorSet 0
+     ; CHECK: OpDecorate %orig_var_sampler DescriptorSet 0
+     ; CHECK: OpDecorate %orig_var_image Binding 0
+     ; CHECK: OpDecorate %orig_var_sampler Binding 0
+
+     ; CHECK: %10 = OpTypeImage %
+     ; CHECK: %[[image_ptr_ty:\w+]] = OpTypePointer UniformConstant %10
+     ; CHECK: %[[sampler_ty:\d+]] = OpTypeSampler
+     ; CHECK: %[[sampler_ptr_ty:\w+]] = OpTypePointer UniformConstant %[[sampler_ty]]
+
+
+     ; CHECK-NOT: %orig_var = OpVariable
+     ; CHECK-DAG: %orig_var_sampler = OpVariable %[[sampler_ptr_ty]] UniformConstant
+     ; CHECK-DAG: %orig_var_image = OpVariable %[[image_ptr_ty]] UniformConstant
+     ; CHECK: = OpFunction
+
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+        %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %11 = OpTypeSampledImage %10
+%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
+
+   %orig_var = OpVariable %_ptr_UniformConstant_11 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+        %101 = OpLoad %11 %orig_var
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_PtrSampledImage.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_PtrSampledImage.spvasm
new file mode 100644
index 0000000..ca17746
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_PtrSampledImage.spvasm
@@ -0,0 +1,81 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %si_ty "si_ty"
+      OpName %p_si_ty "p_si_ty"
+      OpName %array_si_ty "array_si_ty"
+      OpName %rtarray_si_ty "rtarray_si_ty"
+      OpName %p_array_si_ty "p_array_si_ty"
+      OpName %p_rtarray_si_ty "p_rtarray_si_ty"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %v4float %uint %p_i_ty %p_s_ty %float
+      %f_ty = OpTypeFunction %v4float %uint %p_si_ty %float
+
+      ; CHECK: %f = OpFunction %v4float None %f_ty
+      ; CHECK-NEXT: OpFunctionParameter %uint
+      ; CHECK-NEXT: %[[pi:\w+]] = OpFunctionParameter %p_i_ty
+      ; CHECK-NEXT: %[[ps:\w+]] = OpFunctionParameter %p_s_ty
+      ; CHECK-NEXT: OpFunctionParameter %float
+      ; CHECK-NEXT: OpLabel
+      ; CHECK-NEXT: %[[i:\w+]] = OpLoad %i_ty %[[pi]]
+      ; CHECK-NEXT: %[[s:\w+]] = OpLoad %s_ty %[[ps]]
+      ; CHECK-NEXT: %[[si:\w+]] = OpSampledImage %si_ty %[[i]] %[[s]]
+      ; CHECK-NEXT: %200 = OpImageSampleExplicitLod %v4float %[[si]] %13 Lod %float_0
+      ; CHECK-NEXT: OpReturnValue %200
+
+      %f = OpFunction %v4float None %f_ty
+      %100 = OpFunctionParameter %uint
+      %101 = OpFunctionParameter %p_si_ty ; replace this
+      %110 = OpFunctionParameter %float
+      %120 = OpLabel
+      %121 = OpLoad %si_ty %101
+      %200 = OpImageSampleExplicitLod %v4float %121 %13 Lod %float_0
+      OpReturnValue %200
+      OpFunctionEnd
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_SampledImage_OpImage.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_SampledImage_OpImage.spvasm
new file mode 100644
index 0000000..d08ea72
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_SampledImage_OpImage.spvasm
@@ -0,0 +1,79 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %si_ty "si_ty"
+      OpName %p_si_ty "p_si_ty"
+      OpName %array_si_ty "array_si_ty"
+      OpName %rtarray_si_ty "rtarray_si_ty"
+      OpName %p_array_si_ty "p_array_si_ty"
+      OpName %p_rtarray_si_ty "p_rtarray_si_ty"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %uint %i_ty %s_ty %float
+      %f_ty = OpTypeFunction %void %uint %si_ty %float
+
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK: OpFunctionParameter %uint
+      ; CHECK-NEXT: %[[i:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[s:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: OpFunctionParameter %float
+      ; CHECK-NEXT: OpLabel
+      ; CHECK-NEXT: %[[si:\w+]] = OpSampledImage %si_ty %[[i]] %[[s]]
+      ; CHECK-NEXT: %200 = OpImage %i_ty %[[si]]
+      ; CHECK-NEXT: OpReturn
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %uint
+      %101 = OpFunctionParameter %si_ty ; replace this
+      %110 = OpFunctionParameter %float
+      %120 = OpLabel
+      %200 = OpImage %i_ty %101
+      OpReturn
+      OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_SampledImage_OpImageSample.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_SampledImage_OpImageSample.spvasm
new file mode 100644
index 0000000..9492368
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_SampledImage_OpImageSample.spvasm
@@ -0,0 +1,79 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %si_ty "si_ty"
+      OpName %p_si_ty "p_si_ty"
+      OpName %array_si_ty "array_si_ty"
+      OpName %rtarray_si_ty "rtarray_si_ty"
+      OpName %p_array_si_ty "p_array_si_ty"
+      OpName %p_rtarray_si_ty "p_rtarray_si_ty"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %v4float %uint %i_ty %s_ty %float
+      %f_ty = OpTypeFunction %v4float %uint %si_ty %float
+
+      ; CHECK: %f = OpFunction %v4float None %f_ty
+      ; CHECK: OpFunctionParameter %uint
+      ; CHECK-NEXT: %[[i:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[s:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: OpFunctionParameter %float
+      ; CHECK-NEXT: OpLabel
+      ; CHECK-NEXT: %[[si:\w+]] = OpSampledImage %si_ty %[[i]] %[[s]]
+      ; CHECK-NEXT: %200 = OpImageSampleExplicitLod %v4float %[[si]] %13 Lod %float_0
+      ; CHECK-NEXT: OpReturnValue %200
+
+      %f = OpFunction %v4float None %f_ty
+      %100 = OpFunctionParameter %uint
+      %101 = OpFunctionParameter %si_ty ; replace this
+      %110 = OpFunctionParameter %float
+      %120 = OpLabel
+      %200 = OpImageSampleExplicitLod %v4float %101 %13 Lod %float_0
+      OpReturnValue %200
+      OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_ScalarNoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_ScalarNoChange.spvasm
new file mode 100644
index 0000000..e7308c7
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionBody_ScalarNoChange.spvasm
@@ -0,0 +1,74 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %si_ty "si_ty"
+      OpName %p_si_ty "p_si_ty"
+      OpName %array_si_ty "array_si_ty"
+      OpName %rtarray_si_ty "rtarray_si_ty"
+      OpName %p_array_si_ty "p_array_si_ty"
+      OpName %p_rtarray_si_ty "p_rtarray_si_ty"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %float %i_ty %s_ty %p_i_ty %p_s_ty
+      %f_ty = OpTypeFunction %float %i_ty %s_ty %p_i_ty %p_s_ty
+
+      ; CHECK: %f = OpFunction %float None %f_ty
+      ; CHECK-NEXT: OpFunctionParameter %i_ty
+      ; CHECK-NEXT: OpFunctionParameter %s_ty
+      ; CHECK-NEXT: OpFunctionParameter %p_i_ty
+      ; CHECK-NEXT: OpFunctionParameter %p_s_ty
+      ; CHECK-NEXT: OpLabel
+      %f = OpFunction %float None %f_ty
+      %100 = OpFunctionParameter %i_ty
+      %101 = OpFunctionParameter %s_ty
+      %102 = OpFunctionParameter %p_i_ty
+      %103 = OpFunctionParameter %p_s_ty
+      %110 = OpLabel
+      OpReturnValue %float_0
+      OpFunctionEnd
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_Image_NoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_Image_NoChange.spvasm
new file mode 100644
index 0000000..37f57e7
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_Image_NoChange.spvasm
@@ -0,0 +1,81 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %i_ty
+      %f_ty = OpTypeFunction %void %i_ty
+      %caller_ty = OpTypeFunction %float %i_ty
+
+      ; The called function does not change
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %i_ty
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; The caller does not change
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %caller_arg = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: OpFunctionCall %void %f %caller_arg
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+  %caller_arg = OpFunctionParameter %i_ty
+%caller_entry = OpLabel
+ %caller_call = OpFunctionCall %void %f %caller_arg
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_NoImageOrSampler_NoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_NoImageOrSampler_NoChange.spvasm
new file mode 100644
index 0000000..3d67151
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_NoImageOrSampler_NoChange.spvasm
@@ -0,0 +1,90 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %uint %float
+      %f_ty = OpTypeFunction %void %uint %float
+      %caller_ty = OpTypeFunction %float  ; make it return non-void otherwise it's just like main
+
+      ; The called function does not change
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: = OpFunctionParameter %uint
+      ; CHECK-NEXT: = OpFunctionParameter %float
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %uint
+      %101 = OpFunctionParameter %float
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; The caller does not change
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: %caller_arg = OpCopyObject %uint %uint_0
+      ; CHECK-NEXT: OpFunctionCall %void %f %caller_arg %float_0
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+%caller_entry = OpLabel
+  %caller_arg = OpCopyObject %uint %uint_0
+ %caller_call = OpFunctionCall %void %f %caller_arg %float_0
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_PtrImage_NoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_PtrImage_NoChange.spvasm
new file mode 100644
index 0000000..6099b45
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_PtrImage_NoChange.spvasm
@@ -0,0 +1,81 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %p_i_ty
+      %f_ty = OpTypeFunction %void %p_i_ty
+      %caller_ty = OpTypeFunction %float %p_i_ty
+
+      ; The called function does not change
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: = OpFunctionParameter %p_i_ty
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %p_i_ty
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; The caller does not change
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %caller_arg = OpFunctionParameter %p_i_ty
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: OpFunctionCall %void %f %caller_arg
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+  %caller_arg = OpFunctionParameter %p_i_ty
+%caller_entry = OpLabel
+ %caller_call = OpFunctionCall %void %f %caller_arg
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_PtrSampledImage_Split.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_PtrSampledImage_Split.spvasm
new file mode 100644
index 0000000..4dff8fd
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_PtrSampledImage_Split.spvasm
@@ -0,0 +1,96 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %si_ty "si_ty"
+      OpName %p_si_ty "p_si_ty"
+      OpName %array_si_ty "array_si_ty"
+      OpName %rtarray_si_ty "rtarray_si_ty"
+      OpName %p_array_si_ty "p_array_si_ty"
+      OpName %p_rtarray_si_ty "p_rtarray_si_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %p_i_ty %p_s_ty
+      %f_ty = OpTypeFunction %void %p_si_ty
+      %caller_ty = OpTypeFunction %float %p_si_ty
+
+      ; Call function arg is split. We've checked these details in other tests.
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: %[[callee_i:\w+]] = OpFunctionParameter %p_i_ty
+      ; CHECK-NEXT: %[[callee_s:\w+]] = OpFunctionParameter %p_s_ty
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %p_si_ty
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %[[caller_i:\w+]] = OpFunctionParameter %p_i_ty
+      ; CHECK-NEXT: %[[caller_s:\w+]] = OpFunctionParameter %p_s_ty
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: %caller_call = OpFunctionCall %void %f %[[caller_i]] %[[caller_s]]
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+  %caller_arg = OpFunctionParameter %p_si_ty
+%caller_entry = OpLabel
+ %caller_call = OpFunctionCall %void %f %caller_arg
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_PtrSampler_NoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_PtrSampler_NoChange.spvasm
new file mode 100644
index 0000000..89a9842
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_PtrSampler_NoChange.spvasm
@@ -0,0 +1,81 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %p_s_ty
+      %f_ty = OpTypeFunction %void %p_s_ty
+      %caller_ty = OpTypeFunction %float %p_s_ty
+
+      ; The called function does not change
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: = OpFunctionParameter %p_s_ty
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %p_s_ty
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; The caller does not change
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %caller_arg = OpFunctionParameter %p_s_ty
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: OpFunctionCall %void %f %caller_arg
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+  %caller_arg = OpFunctionParameter %p_s_ty
+%caller_entry = OpLabel
+ %caller_call = OpFunctionCall %void %f %caller_arg
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageAndCopy_Split.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageAndCopy_Split.spvasm
new file mode 100644
index 0000000..0224f57
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageAndCopy_Split.spvasm
@@ -0,0 +1,101 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %si_ty "si_ty"
+      OpName %p_si_ty "p_si_ty"
+      OpName %array_si_ty "array_si_ty"
+      OpName %rtarray_si_ty "rtarray_si_ty"
+      OpName %p_array_si_ty "p_array_si_ty"
+      OpName %p_rtarray_si_ty "p_rtarray_si_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %i_ty %s_ty %i_ty %s_ty
+      %f_ty = OpTypeFunction %void %si_ty %si_ty
+      ; CHECK: %caller_ty = OpTypeFunction %float %i_ty %s_ty
+      %caller_ty = OpTypeFunction %float %si_ty
+
+      ; Call function arg is split. We've checked these details in other tests.
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: %[[callee_i_0:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[callee_s_0:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %[[callee_i_1:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[callee_s_1:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %si_ty
+      %101 = OpFunctionParameter %si_ty
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %[[caller_i:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[caller_s:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: %caller_call = OpFunctionCall %void %f %[[caller_i]] %[[caller_s]] %[[caller_i]] %[[caller_s]]
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+  %caller_arg = OpFunctionParameter %si_ty
+%caller_entry = OpLabel
+        %copy = OpCopyObject %si_ty %caller_arg
+ %caller_call = OpFunctionCall %void %f %caller_arg %copy
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageDuplicatedArg_Split.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageDuplicatedArg_Split.spvasm
new file mode 100644
index 0000000..affc5a1
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageDuplicatedArg_Split.spvasm
@@ -0,0 +1,99 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %si_ty "si_ty"
+      OpName %p_si_ty "p_si_ty"
+      OpName %array_si_ty "array_si_ty"
+      OpName %rtarray_si_ty "rtarray_si_ty"
+      OpName %p_array_si_ty "p_array_si_ty"
+      OpName %p_rtarray_si_ty "p_rtarray_si_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %i_ty %s_ty %i_ty %s_ty
+      %f_ty = OpTypeFunction %void %si_ty %si_ty
+      %caller_ty = OpTypeFunction %float %si_ty
+
+      ; Call function arg is split. We've checked these details in other tests.
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: %[[callee_i_0:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[callee_s_0:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %[[callee_i_1:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[callee_s_1:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %si_ty
+      %101 = OpFunctionParameter %si_ty
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %[[caller_i:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[caller_s:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: %caller_call = OpFunctionCall %void %f %[[caller_i]] %[[caller_s]] %[[caller_i]] %[[caller_s]]
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+  %caller_arg = OpFunctionParameter %si_ty
+%caller_entry = OpLabel
+ %caller_call = OpFunctionCall %void %f %caller_arg %caller_arg
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageSurrounded_Split.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageSurrounded_Split.spvasm
new file mode 100644
index 0000000..1cc136d
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageSurrounded_Split.spvasm
@@ -0,0 +1,105 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %si_ty "si_ty"
+      OpName %p_si_ty "p_si_ty"
+      OpName %array_si_ty "array_si_ty"
+      OpName %rtarray_si_ty "rtarray_si_ty"
+      OpName %p_array_si_ty "p_array_si_ty"
+      OpName %p_rtarray_si_ty "p_rtarray_si_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %float %i_ty %s_ty %uint
+      %f_ty = OpTypeFunction %void %float %si_ty %uint
+      ; CHECK: %caller_ty = OpTypeFunction %float %uint %i_ty %s_ty %float
+      %caller_ty = OpTypeFunction %float %uint %si_ty %float
+
+      ; Call function arg is split. We've checked these details in other tests.
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: %[[callee_f:\w+]] = OpFunctionParameter %float
+      ; CHECK-NEXT: %[[callee_i:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[callee_s:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %[[callee_u:\w+]] = OpFunctionParameter %uint
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+       %99 = OpFunctionParameter %float
+      %100 = OpFunctionParameter %si_ty
+      %101 = OpFunctionParameter %uint
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %[[u_param:\w+]] = OpFunctionParameter %uint
+      ; CHECK-NEXT: %[[caller_i:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[caller_s:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %[[f_param:\w+]] = OpFunctionParameter %float
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: %caller_call = OpFunctionCall %void %f %[[f_param]] %[[caller_i]] %[[caller_s]] %[[u_param]]
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+         %200 = OpFunctionParameter %uint
+  %caller_arg = OpFunctionParameter %si_ty
+         %201 = OpFunctionParameter %float
+%caller_entry = OpLabel
+ %caller_call = OpFunctionCall %void %f %201 %caller_arg %200
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageTwoDistinct_Split.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageTwoDistinct_Split.spvasm
new file mode 100644
index 0000000..96116aa
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImageTwoDistinct_Split.spvasm
@@ -0,0 +1,102 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %si_ty "si_ty"
+      OpName %p_si_ty "p_si_ty"
+      OpName %array_si_ty "array_si_ty"
+      OpName %rtarray_si_ty "rtarray_si_ty"
+      OpName %p_array_si_ty "p_array_si_ty"
+      OpName %p_rtarray_si_ty "p_rtarray_si_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %i_ty %s_ty %i_ty %s_ty
+      %f_ty = OpTypeFunction %void %si_ty %si_ty
+      %caller_ty = OpTypeFunction %float %si_ty %si_ty
+
+      ; Call function arg is split. We've checked these details in other tests.
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: %[[callee_i_0:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[callee_s_0:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %[[callee_i_1:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[callee_s_1:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %si_ty
+      %101 = OpFunctionParameter %si_ty
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %[[caller_i_0:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[caller_s_0:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %[[caller_i_1:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[caller_s_1:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: %caller_call = OpFunctionCall %void %f %[[caller_i_0]] %[[caller_s_0]] %[[caller_i_1]] %[[caller_s_1]]
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+  %caller_arg = OpFunctionParameter %si_ty
+         %201 = OpFunctionParameter %si_ty
+%caller_entry = OpLabel
+ %caller_call = OpFunctionCall %void %f %caller_arg %201
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImage_Split.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImage_Split.spvasm
new file mode 100644
index 0000000..fc04e96
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_SampledImage_Split.spvasm
@@ -0,0 +1,96 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %si_ty "si_ty"
+      OpName %p_si_ty "p_si_ty"
+      OpName %array_si_ty "array_si_ty"
+      OpName %rtarray_si_ty "rtarray_si_ty"
+      OpName %p_array_si_ty "p_array_si_ty"
+      OpName %p_rtarray_si_ty "p_rtarray_si_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+      %si_ty = OpTypeSampledImage %i_ty
+      %p_si_ty = OpTypePointer UniformConstant %si_ty
+      %array_si_ty = OpTypeArray %si_ty %uint_3
+      %p_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+      %rtarray_si_ty = OpTypeRuntimeArray %si_ty
+      %p_rtarray_si_ty = OpTypePointer UniformConstant %rtarray_si_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %i_ty %s_ty
+      %f_ty = OpTypeFunction %void %si_ty
+      %caller_ty = OpTypeFunction %float %si_ty
+
+      ; Call function arg is split. We've checked these details in other tests.
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: %[[callee_i:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[callee_s:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %si_ty
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %[[caller_i:\w+]] = OpFunctionParameter %i_ty
+      ; CHECK-NEXT: %[[caller_s:\w+]] = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: %caller_call = OpFunctionCall %void %f %[[caller_i]] %[[caller_s]]
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+  %caller_arg = OpFunctionParameter %si_ty
+%caller_entry = OpLabel
+ %caller_call = OpFunctionCall %void %f %caller_arg
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_Sampler_NoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_Sampler_NoChange.spvasm
new file mode 100644
index 0000000..e7f5b4e
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionCall_Sampler_NoChange.spvasm
@@ -0,0 +1,81 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+      OpName %f "f"
+      OpName %f_ty "f_ty"
+      OpName %i_ty "i_ty"
+      OpName %s_ty "s_ty"
+      OpName %p_i_ty "p_i_ty"
+      OpName %p_s_ty "p_s_ty"
+
+      OpName %caller_ty     "caller_ty"
+      OpName %caller        "caller"
+      OpName %caller_entry  "caller_entry"
+      OpName %caller_call   "caller_call"
+      OpName %caller_arg    "caller_arg"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+      %i_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+      %s_ty = OpTypeSampler
+      %p_i_ty = OpTypePointer UniformConstant %i_ty
+      %p_s_ty = OpTypePointer UniformConstant %s_ty
+
+
+      ; CHECK: %f_ty = OpTypeFunction %void %s_ty
+      %f_ty = OpTypeFunction %void %s_ty
+      %caller_ty = OpTypeFunction %float %s_ty
+
+      ; The called function does not change
+      ; CHECK: %f = OpFunction %void None %f_ty
+      ; CHECK-NEXT: = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: = OpLabel
+      ; CHECK-NEXT: OpReturn
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %f = OpFunction %void None %f_ty
+      %100 = OpFunctionParameter %s_ty
+      %110 = OpLabel
+      OpReturn
+      OpFunctionEnd
+
+      ; The caller does not change
+      ; CHECK: %caller = OpFunction %float None %caller_ty
+      ; CHECK-NEXT: %caller_arg = OpFunctionParameter %s_ty
+      ; CHECK-NEXT: %caller_entry = OpLabel
+      ; CHECK-NEXT: OpFunctionCall %void %f %caller_arg
+      ; CHECK-NEXT: OpReturnValue %float_0
+      ; CHECK-NEXT: OpFunctionEnd
+
+      %caller = OpFunction %float None %caller_ty
+  %caller_arg = OpFunctionParameter %s_ty
+%caller_entry = OpLabel
+ %caller_call = OpFunctionCall %void %f %caller_arg
+                OpReturnValue %float_0
+                OpFunctionEnd
+
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionType_ReplaceArrayArg.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionType_ReplaceArrayArg.spvasm
new file mode 100644
index 0000000..a56a114
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionType_ReplaceArrayArg.spvasm
@@ -0,0 +1,51 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %f_ty "f_ty"
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+       OpName %ptr_array_si_ty "ptr_array_si_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+   %array_si_ty = OpTypeArray %sampled_image_ty %uint_3
+ %ptr_array_si_ty = OpTypePointer UniformConstant %array_si_ty
+
+  ; CHECK: %[[array_i_ty:\w+]] = OpTypeArray %image_ty %uint_3
+  ; CHECK: %[[ptr_array_i_ty:\w+]] = OpTypePointer UniformConstant %[[array_i_ty]]
+  ; CHECK: %[[array_s_ty:\w+]] = OpTypeArray %sampler_ty %uint_3
+  ; CHECK: %[[ptr_array_s_ty:\w+]] = OpTypePointer UniformConstant %[[array_s_ty]]
+
+       %f_ty = OpTypeFunction %float %uint %ptr_array_si_ty %float
+  ; CHECK: %f_ty = OpTypeFunction %float %uint %[[ptr_array_i_ty]] %[[ptr_array_s_ty]] %float
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionType_ReplaceSampledImageArg.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionType_ReplaceSampledImageArg.spvasm
new file mode 100644
index 0000000..bcd1ec1
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_FunctionType_ReplaceSampledImageArg.spvasm
@@ -0,0 +1,43 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+
+       OpName %f_ty "f_ty"
+       OpName %sampler_ty "sampler_ty"
+       OpName %image_ty "image_ty"
+       OpName %sampled_image_ty "sampled_image_ty"
+
+        %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+
+ %sampler_ty = OpTypeSampler
+   %image_ty = OpTypeImage %float 2D 0 0 0 1 Unknown
+ %sampled_image_ty = OpTypeSampledImage %image_ty
+
+       %f_ty = OpTypeFunction %float %sampled_image_ty %float
+  ; CHECK: %f_ty = OpTypeFunction %float %image_ty %sampler_ty %float
+
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_ImageOnly_NoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_ImageOnly_NoChange.spvasm
new file mode 100644
index 0000000..a42e47f
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_ImageOnly_NoChange.spvasm
@@ -0,0 +1,34 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+         %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
+%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
+        %100 = OpVariable %_ptr_UniformConstant_10 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+          %6 = OpLoad %10 %100
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_PtrArraySampledImageOnly_DeletesPtrType.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_PtrArraySampledImageOnly_DeletesPtrType.spvasm
new file mode 100644
index 0000000..aa15ec1
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_PtrArraySampledImageOnly_DeletesPtrType.spvasm
@@ -0,0 +1,36 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+  ; CHECK: OpCapability Shader
+  ; CHECK-NOT: OpTypePointer UniformConstant
+  ; CHECK: OpFunction %void
+        %100 = OpTypeImage %float 2D 0 0 0 1 Unknown
+        %101 = OpTypeSampledImage %100
+        %103 = OpTypeArray %101 %uint_1
+        %104 = OpTypePointer UniformConstant %103
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_PtrRtArraySampledImageOnly_DeletesPtrType.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_PtrRtArraySampledImageOnly_DeletesPtrType.spvasm
new file mode 100644
index 0000000..4ea6247
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_PtrRtArraySampledImageOnly_DeletesPtrType.spvasm
@@ -0,0 +1,36 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+  ; CHECK: OpCapability Shader
+  ; CHECK-NOT: OpTypePointer UniformConstant
+  ; CHECK: OpFunction %void
+        %100 = OpTypeImage %float 2D 0 0 0 1 Unknown
+        %101 = OpTypeSampledImage %100
+        %103 = OpTypeRuntimeArray %101
+        %104 = OpTypePointer UniformConstant %103
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_PtrSampledImageOnly_DeletesPtrType.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_PtrSampledImageOnly_DeletesPtrType.spvasm
new file mode 100644
index 0000000..d19bfac
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_PtrSampledImageOnly_DeletesPtrType.spvasm
@@ -0,0 +1,35 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+  ; CHECK: OpCapability Shader
+  ; CHECK-NOT: OpTypePointer UniformConstant
+  ; CHECK: OpFunction %void
+        %100 = OpTypeImage %float 2D 0 0 0 1 Unknown
+        %101 = OpTypeSampledImage %100
+        %102 = OpTypePointer UniformConstant %101
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_SamplerOnly_NoChange.spvasm b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_SamplerOnly_NoChange.spvasm
new file mode 100644
index 0000000..27cb9eb
--- /dev/null
+++ b/test/tint/unittest/reader/combined_texture_sampler/SplitCombinedImageSamplerPassTest_SamplerOnly_NoChange.spvasm
@@ -0,0 +1,34 @@
+               OpCapability Shader
+               OpCapability RuntimeDescriptorArray
+               OpExtension "SPV_EXT_descriptor_indexing"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %main "main"
+               OpName %main_0 "main_0"
+               OpName %voidfn "voidfn"
+               OpDecorate %100 DescriptorSet 0
+               OpDecorate %100 Binding 0
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_3 = OpConstant %uint 3
+    %float_0 = OpConstant %float 0
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+    %v4float = OpTypeVector %float 4
+         %13 = OpConstantNull %v2float
+         %14 = OpConstantNull %v3float
+         %15 = OpConstantNull %v4float
+       %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+         %10 = OpTypeSampler
+%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
+        %100 = OpVariable %_ptr_UniformConstant_10 UniformConstant
+       %main = OpFunction %void None %voidfn
+     %main_0 = OpLabel
+          %6 = OpLoad %10 %100
+               OpReturn
+               OpFunctionEnd