[spirv-reader] Convert access results for atomics.

When converting an `Access` chain which is being turned into an atomic,
the result of the access also needs to be updated as those uses of the
access chain need to be atomics.

Fixed: 455844215
Change-Id: Ic183ae7774b780b48d216c8ab8b041ff74f1d734
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/269374
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: James Price <jrprice@google.com>
Auto-Submit: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/spirv/reader/lower/atomics.cc b/src/tint/lang/spirv/reader/lower/atomics.cc
index 5f825ba..dfa14ae 100644
--- a/src/tint/lang/spirv/reader/lower/atomics.cc
+++ b/src/tint/lang/spirv/reader/lower/atomics.cc
@@ -319,6 +319,7 @@
                     [&](core::ir::Access* a) {
                         CheckForStructForking(a);
                         values_to_convert_.Push(a->Object());
+                        values_to_fix_usages_.Push(a->Result());
                     },
                     [&](core::ir::Let* l) {
                         values_to_convert_.Push(l->Value());
diff --git a/src/tint/lang/spirv/reader/lower/atomics_test.cc b/src/tint/lang/spirv/reader/lower/atomics_test.cc
index 50d1c76..0592c2d 100644
--- a/src/tint/lang/spirv/reader/lower/atomics_test.cc
+++ b/src/tint/lang/spirv/reader/lower/atomics_test.cc
@@ -3255,5 +3255,80 @@
     ASSERT_EQ(expect, str());
 }
 
+TEST_F(SpirvReader_AtomicsTest, RewriteLoad_SameAccessChain) {
+    auto* f = b.ComputeFunction("main");
+    core::ir::Var* buffer = nullptr;
+    b.Append(mod.root_block,
+             [&] {  //
+                 buffer = b.Var("buffer", ty.ptr<storage, array<u32>, read_write>());
+                 buffer->SetBindingPoint(0u, 0u);
+             });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a = b.Access(ty.ptr<storage, u32, read_write>(), buffer, 1_i);
+        b.Let("x", b.Load(a));
+
+        auto* if_ = b.If(true);
+        b.Append(if_->True(), [&] {
+            b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicCompareExchange, a,
+                                           1_u, 0_u, 0_u, 0_u, 0_u);
+            b.ExitIf(if_);
+        });
+
+        b.Return(f);
+    });
+
+    auto* src = R"(
+$B1: {  # root
+  %buffer:ptr<storage, array<u32>, read_write> = var undef @binding_point(0, 0)
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<storage, u32, read_write> = access %buffer, 1i
+    %4:u32 = load %3
+    %x:u32 = let %4
+    if true [t: $B3] {  # if_1
+      $B3: {  # true
+        %6:u32 = spirv.atomic_compare_exchange %3, 1u, 0u, 0u, 0u, 0u
+        exit_if  # if_1
+      }
+    }
+    ret
+  }
+}
+)";
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+__atomic_compare_exchange_result_u32 = struct @align(4) {
+  old_value:u32 @offset(0)
+  exchanged:bool @offset(4)
+}
+
+$B1: {  # root
+  %buffer:ptr<storage, array<atomic<u32>>, read_write> = var undef @binding_point(0, 0)
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<storage, atomic<u32>, read_write> = access %buffer, 1i
+    %4:u32 = atomicLoad %3
+    %x:u32 = let %4
+    if true [t: $B3] {  # if_1
+      $B3: {  # true
+        %6:__atomic_compare_exchange_result_u32 = atomicCompareExchangeWeak %3, 0u, 0u
+        %7:u32 = access %6, 0u
+        exit_if  # if_1
+      }
+    }
+    ret
+  }
+}
+)";
+    ASSERT_EQ(expect, str());
+}
+
 }  // namespace
 }  // namespace tint::spirv::reader::lower
diff --git a/test/tint/bug/tint/455844215.spvasm b/test/tint/bug/tint/455844215.spvasm
new file mode 100644
index 0000000..fa0dfe1
--- /dev/null
+++ b/test/tint/bug/tint/455844215.spvasm
@@ -0,0 +1,53 @@
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 64 1 1
+
+               OpName %buffer_type "buffer_type"
+               OpName %buffer "buffer"
+               OpName %main "main"
+               OpDecorate %buffer DescriptorSet 0
+               OpDecorate %buffer Binding 0
+               OpDecorate %runtime_arr ArrayStride 4
+               OpMemberDecorate %buffer_type 0 Offset 0
+               OpDecorate %buffer_type BufferBlock
+
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+%runtime_arr = OpTypeRuntimeArray %uint
+       %void = OpTypeVoid
+         %15 = OpTypeFunction %void
+       %bool = OpTypeBool
+%buffer_type = OpTypeStruct %runtime_arr
+
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+       %true = OpConstantTrue %bool
+
+%ptr_buffer_type = OpTypePointer Uniform %buffer_type
+   %ptr_uint = OpTypePointer Uniform %uint
+     %buffer = OpVariable %ptr_buffer_type Uniform
+
+       %main = OpFunction %void None %15
+         %19 = OpLabel
+               ; Access chain into atomic
+         %22 = OpAccessChain %ptr_uint %buffer %int_0 %int_0
+               ; Load of the buffer value as a u32
+         %23 = OpLoad %uint %22
+
+               ; If
+               OpSelectionMerge %25 None
+               OpBranchConditional %true %26 %25
+
+               ; True block
+         %26 = OpLabel
+               ; Access atomic, attempts to makes %22 an atomic value
+         %27 = OpAtomicCompareExchange %uint %22 %uint_1 %uint_0 %uint_0 %uint_0 %uint_0
+               OpBranch %25
+
+               ; If merge/False block
+         %25 = OpLabel
+               OpReturn
+               OpFunctionEnd