[spirv] Fix use-after-move in Std140 transform

This is only observed when the index list to get the matrix is long
enough.

Change-Id: I8dded7ad2de2d067f7753742fa33a22de313e0d9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/192223
Auto-Submit: James Price <jrprice@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/tint/lang/core/ir/transform/std140.cc b/src/tint/lang/core/ir/transform/std140.cc
index a61b8bc..c21f490 100644
--- a/src/tint/lang/core/ir/transform/std140.cc
+++ b/src/tint/lang/core/ir/transform/std140.cc
@@ -239,9 +239,9 @@
     Value* RebuildMatrix(const core::type::Matrix* mat, Value* root, VectorRef<Value*> indices) {
         // Recombine each column vector from the struct and reconstruct the original matrix type.
         bool is_ptr = root->Type()->Is<core::type::Pointer>();
+        auto first_column = indices.Back()->As<Constant>()->Value()->ValueAs<uint32_t>();
         Vector<Value*, 4> column_indices(std::move(indices));
         Vector<Value*, 4> args;
-        auto first_column = indices.Back()->As<Constant>()->Value()->ValueAs<uint32_t>();
         for (uint32_t i = 0; i < mat->columns(); i++) {
             column_indices.Back() = b.Constant(u32(first_column + i));
             if (is_ptr) {
diff --git a/src/tint/lang/core/ir/transform/std140_test.cc b/src/tint/lang/core/ir/transform/std140_test.cc
index 28a67fa..f139e38 100644
--- a/src/tint/lang/core/ir/transform/std140_test.cc
+++ b/src/tint/lang/core/ir/transform/std140_test.cc
@@ -874,6 +874,99 @@
     EXPECT_EQ(expect, str());
 }
 
+TEST_F(IR_Std140Test, Mat3x2_Nested_AccessInstructionWithManyIndices_LoadMatrix) {
+    auto* mat = ty.mat3x2<f32>();
+    auto* inner = ty.Struct(mod.symbols.New("Inner"), {
+                                                          {mod.symbols.New("m"), ty.array(mat, 4)},
+                                                      });
+    auto* arr = ty.array(inner, 4u);
+    auto* outer = ty.Struct(mod.symbols.New("Outer"), {
+                                                          {mod.symbols.New("arr"), arr},
+                                                      });
+    outer->SetStructFlag(core::type::kBlock);
+
+    auto* buffer = b.Var("buffer", ty.ptr(uniform, outer));
+    buffer->SetBindingPoint(0, 0);
+    mod.root_block->Append(buffer);
+
+    auto* func = b.Function("foo", ty.void_());
+    b.Append(func->Block(), [&] {
+        auto* mat_ptr = b.Access(ty.ptr(uniform, mat), buffer, 0_u, 1_u, 0_u, 2_u);
+        b.Let("mat", b.Load(mat_ptr));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+Inner = struct @align(8) {
+  m:array<mat3x2<f32>, 4> @offset(0)
+}
+
+Outer = struct @align(8), @block {
+  arr:array<Inner, 4> @offset(0)
+}
+
+$B1: {  # root
+  %buffer:ptr<uniform, Outer, read> = var @binding_point(0, 0)
+}
+
+%foo = func():void {
+  $B2: {
+    %3:ptr<uniform, mat3x2<f32>, read> = access %buffer, 0u, 1u, 0u, 2u
+    %4:mat3x2<f32> = load %3
+    %mat:mat3x2<f32> = let %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+Inner = struct @align(8) {
+  m:array<mat3x2<f32>, 4> @offset(0)
+}
+
+Outer = struct @align(8), @block {
+  arr:array<Inner, 4> @offset(0)
+}
+
+mat3x2_f32_std140 = struct @align(8) {
+  col0:vec2<f32> @offset(0)
+  col1:vec2<f32> @offset(8)
+  col2:vec2<f32> @offset(16)
+}
+
+Inner_std140 = struct @align(8) {
+  m:array<mat3x2_f32_std140, 4> @offset(0)
+}
+
+Outer_std140 = struct @align(8), @block {
+  arr:array<Inner_std140, 4> @offset(0)
+}
+
+$B1: {  # root
+  %buffer:ptr<uniform, Outer_std140, read> = var @binding_point(0, 0)
+}
+
+%foo = func():void {
+  $B2: {
+    %3:ptr<uniform, vec2<f32>, read> = access %buffer, 0u, 1u, 0u, 2u, 0u
+    %4:vec2<f32> = load %3
+    %5:ptr<uniform, vec2<f32>, read> = access %buffer, 0u, 1u, 0u, 2u, 1u
+    %6:vec2<f32> = load %5
+    %7:ptr<uniform, vec2<f32>, read> = access %buffer, 0u, 1u, 0u, 2u, 2u
+    %8:vec2<f32> = load %7
+    %9:mat3x2<f32> = construct %4, %6, %8
+    %mat:mat3x2<f32> = let %9
+    ret
+  }
+}
+)";
+
+    Run(Std140);
+
+    EXPECT_EQ(expect, str());
+}
+
 TEST_F(IR_Std140Test, Mat3x2_Nested_ChainOfAccessInstructions) {
     auto* mat = ty.mat3x2<f32>();
     auto* inner = ty.Struct(mod.symbols.New("Inner"), {