tint/writer: Handle unnested, uniform matCx2 matrices

Shuffle the transform orders to ensure that these are embedded in a structure before running the Std140 transform.

Add more end-to-end tests for these.

As pointed out in tint:1673, arrays of matrices are not correctly decomposed by the Std140 transform.
This will be addressed by a later change.

Bug: tint:1673
Change-Id: I47c93e458ff48578922d576819792e8ed3a5723c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/102541
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Zhaoming Jiang <zhaoming.jiang@intel.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index 0771da9..5031329 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -221,10 +221,8 @@
     manager.Add<transform::CanonicalizeEntryPointIO>();
     manager.Add<transform::ExpandCompoundAssignment>();
     manager.Add<transform::PromoteSideEffectsToDecl>();
-    manager.Add<transform::Std140>();  // Must come after PromoteSideEffectsToDecl
     manager.Add<transform::PadStructs>();
     manager.Add<transform::UnwindDiscardFunctions>();
-    manager.Add<transform::SimplifyPointers>();
 
     manager.Add<transform::RemovePhonies>();
 
@@ -245,6 +243,13 @@
     manager.Add<transform::PromoteInitializersToLet>();
     manager.Add<transform::AddEmptyEntryPoint>();
     manager.Add<transform::AddBlockAttribute>();
+
+    // Std140 must come after PromoteSideEffectsToDecl and AddBlockAttribute
+    // Std140 must come before SimplifyPointers.
+    manager.Add<transform::Std140>();
+
+    manager.Add<transform::SimplifyPointers>();
+
     data.Add<transform::CanonicalizeEntryPointIO::Config>(
         transform::CanonicalizeEntryPointIO::ShaderStyle::kGlsl);
 
diff --git a/src/tint/writer/spirv/generator_impl.cc b/src/tint/writer/spirv/generator_impl.cc
index f303324..2a2c25c 100644
--- a/src/tint/writer/spirv/generator_impl.cc
+++ b/src/tint/writer/spirv/generator_impl.cc
@@ -77,19 +77,25 @@
     manager.Add<transform::RemoveUnreachableStatements>();
     manager.Add<transform::ExpandCompoundAssignment>();
     manager.Add<transform::PromoteSideEffectsToDecl>();
-    manager.Add<transform::Std140>();  // Must come after PromoteSideEffectsToDecl
     manager.Add<transform::UnwindDiscardFunctions>();
     manager.Add<transform::SimplifyPointers>();  // Required for arrayLength()
     manager.Add<transform::RemovePhonies>();
     manager.Add<transform::VectorizeScalarMatrixConstructors>();
     manager.Add<transform::VectorizeMatrixConversions>();
-    manager.Add<transform::ForLoopToLoop>();  // Must come after
-    manager.Add<transform::WhileToLoop>();    // ZeroInitWorkgroupMemory
+    manager.Add<transform::WhileToLoop>();  // ZeroInitWorkgroupMemory
     manager.Add<transform::CanonicalizeEntryPointIO>();
     manager.Add<transform::AddEmptyEntryPoint>();
     manager.Add<transform::AddBlockAttribute>();
+
+    // Std140 must come after PromoteSideEffectsToDecl, AddBlockAttribute
+    manager.Add<transform::Std140>();
+
+    // VarForDynamicIndex must come after Std140
     manager.Add<transform::VarForDynamicIndex>();
 
+    // ForLoopToLoop must come after Std140, ZeroInitWorkgroupMemory
+    manager.Add<transform::ForLoopToLoop>();
+
     data.Add<transform::CanonicalizeEntryPointIO::Config>(
         transform::CanonicalizeEntryPointIO::Config(
             transform::CanonicalizeEntryPointIO::ShaderStyle::kSpirv, 0xFFFFFFFF,
diff --git a/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.glsl b/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.glsl
index 067b82d..b992d24 100644
--- a/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.glsl
@@ -11,6 +11,8 @@
   ivec2 h;
   mat2x3 i;
   mat3x2 j;
+  uint pad;
+  uint pad_1;
   ivec4 k[4];
 };
 
@@ -32,10 +34,6 @@
   ivec4 k[4];
 };
 
-struct S {
-  Inner arr[8];
-};
-
 layout(binding = 0, std140) uniform S_std140_ubo {
   Inner_std140 arr[8];
 } s;
diff --git a/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.spvasm b/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.spvasm
index 42889ab..d2f0b8e 100644
--- a/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 86
+; Bound: 92
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
@@ -76,12 +76,13 @@
 %mat3v2float = OpTypeMatrix %v2float 3
          %21 = OpTypeFunction %mat3v2float %uint
      %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
      %uint_9 = OpConstant %uint 9
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
     %uint_10 = OpConstant %uint 10
     %uint_11 = OpConstant %uint 11
        %void = OpTypeVoid
-         %38 = OpTypeFunction %void %uint
+         %44 = OpTypeFunction %void %uint
 %_ptr_Uniform_v3int = OpTypePointer Uniform %v3int
      %uint_1 = OpConstant %uint 1
 %_ptr_Uniform_int = OpTypePointer Uniform %int
@@ -98,48 +99,49 @@
 %_ptr_Uniform_mat2v3float = OpTypePointer Uniform %mat2v3float
     %uint_12 = OpConstant %uint 12
 %_ptr_Uniform__arr_v4int_uint_4 = OpTypePointer Uniform %_arr_v4int_uint_4
-         %81 = OpTypeFunction %void
+         %87 = OpTypeFunction %void
 %load_s_arr_p0_j = OpFunction %mat3v2float None %21
          %p0 = OpFunctionParameter %uint
          %25 = OpLabel
-         %29 = OpAccessChain %_ptr_Uniform_v2float %s %uint_0 %p0 %uint_9
-         %30 = OpLoad %v2float %29
-         %32 = OpAccessChain %_ptr_Uniform_v2float %s %uint_0 %p0 %uint_10
-         %33 = OpLoad %v2float %32
-         %35 = OpAccessChain %_ptr_Uniform_v2float %s %uint_0 %p0 %uint_11
-         %36 = OpLoad %v2float %35
-         %37 = OpCompositeConstruct %mat3v2float %30 %33 %36
-               OpReturnValue %37
+         %29 = OpAccessChain %_ptr_Uniform_Inner_std140 %s %uint_0 %p0
+         %33 = OpAccessChain %_ptr_Uniform_v2float %29 %uint_9
+         %34 = OpLoad %v2float %33
+         %37 = OpAccessChain %_ptr_Uniform_v2float %29 %uint_10
+         %38 = OpLoad %v2float %37
+         %41 = OpAccessChain %_ptr_Uniform_v2float %29 %uint_11
+         %42 = OpLoad %v2float %41
+         %43 = OpCompositeConstruct %mat3v2float %34 %38 %42
+               OpReturnValue %43
                OpFunctionEnd
- %main_inner = OpFunction %void None %38
+ %main_inner = OpFunction %void None %44
         %idx = OpFunctionParameter %uint
-         %42 = OpLabel
-         %44 = OpAccessChain %_ptr_Uniform_v3int %s %uint_0 %idx %uint_0
-         %45 = OpLoad %v3int %44
-         %48 = OpAccessChain %_ptr_Uniform_int %s %uint_0 %idx %uint_1
-         %49 = OpLoad %int %48
-         %52 = OpAccessChain %_ptr_Uniform_v3uint %s %uint_0 %idx %uint_2
-         %53 = OpLoad %v3uint %52
-         %56 = OpAccessChain %_ptr_Uniform_uint %s %uint_0 %idx %uint_3
-         %57 = OpLoad %uint %56
-         %59 = OpAccessChain %_ptr_Uniform_v3float %s %uint_0 %idx %uint_4
-         %60 = OpLoad %v3float %59
-         %63 = OpAccessChain %_ptr_Uniform_float %s %uint_0 %idx %uint_5
-         %64 = OpLoad %float %63
-         %67 = OpAccessChain %_ptr_Uniform_v2int %s %uint_0 %idx %uint_6
-         %68 = OpLoad %v2int %67
-         %70 = OpAccessChain %_ptr_Uniform_v2int %s %uint_0 %idx %uint_7
-         %71 = OpLoad %v2int %70
-         %73 = OpAccessChain %_ptr_Uniform_mat2v3float %s %uint_0 %idx %uint_8
-         %74 = OpLoad %mat2v3float %73
-         %75 = OpFunctionCall %mat3v2float %load_s_arr_p0_j %idx
-         %79 = OpAccessChain %_ptr_Uniform__arr_v4int_uint_4 %s %uint_0 %idx %uint_12
-         %80 = OpLoad %_arr_v4int_uint_4 %79
+         %48 = OpLabel
+         %50 = OpAccessChain %_ptr_Uniform_v3int %s %uint_0 %idx %uint_0
+         %51 = OpLoad %v3int %50
+         %54 = OpAccessChain %_ptr_Uniform_int %s %uint_0 %idx %uint_1
+         %55 = OpLoad %int %54
+         %58 = OpAccessChain %_ptr_Uniform_v3uint %s %uint_0 %idx %uint_2
+         %59 = OpLoad %v3uint %58
+         %62 = OpAccessChain %_ptr_Uniform_uint %s %uint_0 %idx %uint_3
+         %63 = OpLoad %uint %62
+         %65 = OpAccessChain %_ptr_Uniform_v3float %s %uint_0 %idx %uint_4
+         %66 = OpLoad %v3float %65
+         %69 = OpAccessChain %_ptr_Uniform_float %s %uint_0 %idx %uint_5
+         %70 = OpLoad %float %69
+         %73 = OpAccessChain %_ptr_Uniform_v2int %s %uint_0 %idx %uint_6
+         %74 = OpLoad %v2int %73
+         %76 = OpAccessChain %_ptr_Uniform_v2int %s %uint_0 %idx %uint_7
+         %77 = OpLoad %v2int %76
+         %79 = OpAccessChain %_ptr_Uniform_mat2v3float %s %uint_0 %idx %uint_8
+         %80 = OpLoad %mat2v3float %79
+         %81 = OpFunctionCall %mat3v2float %load_s_arr_p0_j %idx
+         %85 = OpAccessChain %_ptr_Uniform__arr_v4int_uint_4 %s %uint_0 %idx %uint_12
+         %86 = OpLoad %_arr_v4int_uint_4 %85
                OpReturn
                OpFunctionEnd
-       %main = OpFunction %void None %81
-         %83 = OpLabel
-         %85 = OpLoad %uint %idx_1
-         %84 = OpFunctionCall %void %main_inner %85
+       %main = OpFunction %void None %87
+         %89 = OpLabel
+         %91 = OpLoad %uint %idx_1
+         %90 = OpFunctionCall %void %main_inner %91
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/static_index/read.wgsl.expected.glsl b/test/tint/buffer/uniform/static_index/read.wgsl.expected.glsl
index 1b07ab0..233bbf4 100644
--- a/test/tint/buffer/uniform/static_index/read.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/static_index/read.wgsl.expected.glsl
@@ -7,21 +7,6 @@
   uint pad_2;
 };
 
-struct S {
-  ivec3 a;
-  int b;
-  uvec3 c;
-  uint d;
-  vec3 e;
-  float f;
-  ivec2 g;
-  ivec2 h;
-  mat2x3 i;
-  mat3x2 j;
-  Inner k;
-  Inner l[4];
-};
-
 layout(binding = 0, std140) uniform S_std140_ubo {
   ivec3 a;
   int b;
diff --git a/test/tint/buffer/uniform/static_index/read.wgsl.expected.spvasm b/test/tint/buffer/uniform/static_index/read.wgsl.expected.spvasm
index 7134d5b..b93631f 100644
--- a/test/tint/buffer/uniform/static_index/read.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/static_index/read.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 78
+; Bound: 82
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
@@ -71,7 +71,7 @@
     %uint_10 = OpConstant %uint 10
     %uint_11 = OpConstant %uint 11
        %void = OpTypeVoid
-         %31 = OpTypeFunction %void
+         %35 = OpTypeFunction %void
      %uint_0 = OpConstant %uint 0
 %_ptr_Uniform_v3int = OpTypePointer Uniform %v3int
      %uint_1 = OpConstant %uint 1
@@ -94,39 +94,39 @@
 %_ptr_Uniform__arr_Inner_uint_4 = OpTypePointer Uniform %_arr_Inner_uint_4
    %load_s_j = OpFunction %mat3v2float None %16
          %19 = OpLabel
-         %22 = OpAccessChain %_ptr_Uniform_v2float %s %uint_9
-         %23 = OpLoad %v2float %22
-         %25 = OpAccessChain %_ptr_Uniform_v2float %s %uint_10
-         %26 = OpLoad %v2float %25
-         %28 = OpAccessChain %_ptr_Uniform_v2float %s %uint_11
+         %24 = OpAccessChain %_ptr_Uniform_v2float %s %uint_9
+         %25 = OpLoad %v2float %24
+         %28 = OpAccessChain %_ptr_Uniform_v2float %s %uint_10
          %29 = OpLoad %v2float %28
-         %30 = OpCompositeConstruct %mat3v2float %23 %26 %29
-               OpReturnValue %30
+         %32 = OpAccessChain %_ptr_Uniform_v2float %s %uint_11
+         %33 = OpLoad %v2float %32
+         %34 = OpCompositeConstruct %mat3v2float %25 %29 %33
+               OpReturnValue %34
                OpFunctionEnd
-       %main = OpFunction %void None %31
-         %34 = OpLabel
-         %37 = OpAccessChain %_ptr_Uniform_v3int %s %uint_0
-         %38 = OpLoad %v3int %37
-         %41 = OpAccessChain %_ptr_Uniform_int %s %uint_1
-         %42 = OpLoad %int %41
-         %45 = OpAccessChain %_ptr_Uniform_v3uint %s %uint_2
-         %46 = OpLoad %v3uint %45
-         %49 = OpAccessChain %_ptr_Uniform_uint %s %uint_3
-         %50 = OpLoad %uint %49
-         %52 = OpAccessChain %_ptr_Uniform_v3float %s %uint_4
-         %53 = OpLoad %v3float %52
-         %56 = OpAccessChain %_ptr_Uniform_float %s %uint_5
-         %57 = OpLoad %float %56
-         %60 = OpAccessChain %_ptr_Uniform_v2int %s %uint_6
-         %61 = OpLoad %v2int %60
-         %63 = OpAccessChain %_ptr_Uniform_v2int %s %uint_7
-         %64 = OpLoad %v2int %63
-         %67 = OpAccessChain %_ptr_Uniform_mat2v3float %s %uint_8
-         %68 = OpLoad %mat2v3float %67
-         %69 = OpFunctionCall %mat3v2float %load_s_j
-         %72 = OpAccessChain %_ptr_Uniform_Inner %s %uint_12
-         %73 = OpLoad %Inner %72
-         %76 = OpAccessChain %_ptr_Uniform__arr_Inner_uint_4 %s %uint_13
-         %77 = OpLoad %_arr_Inner_uint_4 %76
+       %main = OpFunction %void None %35
+         %38 = OpLabel
+         %41 = OpAccessChain %_ptr_Uniform_v3int %s %uint_0
+         %42 = OpLoad %v3int %41
+         %45 = OpAccessChain %_ptr_Uniform_int %s %uint_1
+         %46 = OpLoad %int %45
+         %49 = OpAccessChain %_ptr_Uniform_v3uint %s %uint_2
+         %50 = OpLoad %v3uint %49
+         %53 = OpAccessChain %_ptr_Uniform_uint %s %uint_3
+         %54 = OpLoad %uint %53
+         %56 = OpAccessChain %_ptr_Uniform_v3float %s %uint_4
+         %57 = OpLoad %v3float %56
+         %60 = OpAccessChain %_ptr_Uniform_float %s %uint_5
+         %61 = OpLoad %float %60
+         %64 = OpAccessChain %_ptr_Uniform_v2int %s %uint_6
+         %65 = OpLoad %v2int %64
+         %67 = OpAccessChain %_ptr_Uniform_v2int %s %uint_7
+         %68 = OpLoad %v2int %67
+         %71 = OpAccessChain %_ptr_Uniform_mat2v3float %s %uint_8
+         %72 = OpLoad %mat2v3float %71
+         %73 = OpFunctionCall %mat3v2float %load_s_j
+         %76 = OpAccessChain %_ptr_Uniform_Inner %s %uint_12
+         %77 = OpLoad %Inner %76
+         %80 = OpAccessChain %_ptr_Uniform__arr_Inner_uint_4 %s %uint_13
+         %81 = OpLoad %_arr_Inner_uint_4 %80
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl
new file mode 100644
index 0000000..241aa52
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl
@@ -0,0 +1,15 @@
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 4>;
+
+var<private> counter = 0;
+fn i() -> i32 { counter++; return counter; }
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_a       = &a;
+  let p_a_i     = &((*p_a)[i()]);
+  let p_a_i_i   = &((*p_a_i)[i()]);
+
+  let l_a       : array<mat2x2<f32>, 4> = *p_a;
+  let l_a_i     : mat2x2<f32>           = *p_a_i;
+  let l_a_i_i   : vec2<f32>             = *p_a_i_i;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..c66c062
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -0,0 +1,40 @@
+cbuffer cbuffer_a : register(b0, space0) {
+  uint4 a[4];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float2x2 tint_symbol_1(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_1(buffer, (offset + (i_1 * 16u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const int p_a_i_save = i();
+  const int p_a_i_i_save = i();
+  const float2x2 l_a[4] = tint_symbol(a, 0u);
+  const float2x2 l_a_i = tint_symbol_1(a, (16u * uint(p_a_i_save)));
+  const uint scalar_offset_2 = (((16u * uint(p_a_i_save)) + (8u * uint(p_a_i_i_save)))) / 4;
+  uint4 ubo_load_2 = a[scalar_offset_2 / 4];
+  const float2 l_a_i_i = asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..c66c062
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -0,0 +1,40 @@
+cbuffer cbuffer_a : register(b0, space0) {
+  uint4 a[4];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float2x2 tint_symbol_1(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_1(buffer, (offset + (i_1 * 16u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const int p_a_i_save = i();
+  const int p_a_i_i_save = i();
+  const float2x2 l_a[4] = tint_symbol(a, 0u);
+  const float2x2 l_a_i = tint_symbol_1(a, (16u * uint(p_a_i_save)));
+  const uint scalar_offset_2 = (((16u * uint(p_a_i_save)) + (8u * uint(p_a_i_i_save)))) / 4;
+  uint4 ubo_load_2 = a[scalar_offset_2 / 4];
+  const float2 l_a_i_i = asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..3b56852
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,27 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform a_block_ubo {
+  mat2 inner[4];
+} a;
+
+int counter = 0;
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+void f() {
+  int tint_symbol = i();
+  int p_a_i_save = tint_symbol;
+  int tint_symbol_1 = i();
+  int p_a_i_i_save = tint_symbol_1;
+  mat2 l_a[4] = a.inner;
+  mat2 l_a_i = a.inner[p_a_i_save];
+  vec2 l_a_i_i = a.inner[p_a_i_save][p_a_i_i_save];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl
new file mode 100644
index 0000000..fe8fe73
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl
@@ -0,0 +1,33 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+int i() {
+  thread int tint_symbol_2 = 0;
+  tint_symbol_2 = as_type<int>((as_type<uint>(tint_symbol_2) + as_type<uint>(1)));
+  return tint_symbol_2;
+}
+
+kernel void f(const constant tint_array<float2x2, 4>* tint_symbol_3 [[buffer(0)]]) {
+  int const tint_symbol = i();
+  int const p_a_i_save = tint_symbol;
+  int const tint_symbol_1 = i();
+  int const p_a_i_i_save = tint_symbol_1;
+  tint_array<float2x2, 4> const l_a = *(tint_symbol_3);
+  float2x2 const l_a_i = (*(tint_symbol_3))[p_a_i_save];
+  float2 const l_a_i_i = (*(tint_symbol_3))[p_a_i_save][p_a_i_i_save];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm
new file mode 100644
index 0000000..b9a3ee9
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 37
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %a_block "a_block"
+               OpMemberName %a_block 0 "inner"
+               OpName %a "a"
+               OpName %counter "counter"
+               OpName %i "i"
+               OpName %f "f"
+               OpDecorate %a_block Block
+               OpMemberDecorate %a_block 0 Offset 0
+               OpMemberDecorate %a_block 0 ColMajor
+               OpMemberDecorate %a_block 0 MatrixStride 8
+               OpDecorate %_arr_mat2v2float_uint_4 ArrayStride 16
+               OpDecorate %a NonWritable
+               OpDecorate %a DescriptorSet 0
+               OpDecorate %a Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat2v2float = OpTypeMatrix %v2float 2
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat2v2float_uint_4 = OpTypeArray %mat2v2float %uint_4
+    %a_block = OpTypeStruct %_arr_mat2v2float_uint_4
+%_ptr_Uniform_a_block = OpTypePointer Uniform %a_block
+          %a = OpVariable %_ptr_Uniform_a_block Uniform
+        %int = OpTypeInt 32 1
+         %11 = OpConstantNull %int
+%_ptr_Private_int = OpTypePointer Private %int
+    %counter = OpVariable %_ptr_Private_int Private %11
+         %14 = OpTypeFunction %int
+      %int_1 = OpConstant %int 1
+       %void = OpTypeVoid
+         %21 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform__arr_mat2v2float_uint_4 = OpTypePointer Uniform %_arr_mat2v2float_uint_4
+%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+          %i = OpFunction %int None %14
+         %16 = OpLabel
+         %17 = OpLoad %int %counter
+         %19 = OpIAdd %int %17 %int_1
+               OpStore %counter %19
+         %20 = OpLoad %int %counter
+               OpReturnValue %20
+               OpFunctionEnd
+          %f = OpFunction %void None %21
+         %24 = OpLabel
+         %25 = OpFunctionCall %int %i
+         %26 = OpFunctionCall %int %i
+         %29 = OpAccessChain %_ptr_Uniform__arr_mat2v2float_uint_4 %a %uint_0
+         %30 = OpLoad %_arr_mat2v2float_uint_4 %29
+         %32 = OpAccessChain %_ptr_Uniform_mat2v2float %a %uint_0 %25
+         %33 = OpLoad %mat2v2float %32
+         %35 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %25 %26
+         %36 = OpLoad %v2float %35
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl
new file mode 100644
index 0000000..fdad9a2
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl
@@ -0,0 +1,18 @@
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 4>;
+
+var<private> counter = 0;
+
+fn i() -> i32 {
+  counter++;
+  return counter;
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_a = &(a);
+  let p_a_i = &((*(p_a))[i()]);
+  let p_a_i_i = &((*(p_a_i))[i()]);
+  let l_a : array<mat2x2<f32>, 4> = *(p_a);
+  let l_a_i : mat2x2<f32> = *(p_a_i);
+  let l_a_i_i : vec2<f32> = *(p_a_i_i);
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl
new file mode 100644
index 0000000..24649bf
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl
@@ -0,0 +1,12 @@
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_a       = &a;
+  let p_a_2     = &((*p_a)[2]);
+  let p_a_2_1   = &((*p_a_2)[1]);
+
+  let l_a       : array<mat2x2<f32>, 4> = *p_a;
+  let l_a_i     : mat2x2<f32>           = *p_a_2;
+  let l_a_i_i   : vec2<f32>             = *p_a_2_1;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..95d27c0
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -0,0 +1,30 @@
+cbuffer cbuffer_a : register(b0, space0) {
+  uint4 a[4];
+};
+
+float2x2 tint_symbol_1(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 16u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x2 l_a[4] = tint_symbol(a, 0u);
+  const float2x2 l_a_i = tint_symbol_1(a, 32u);
+  const float2 l_a_i_i = asfloat(a[2].zw);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..95d27c0
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -0,0 +1,30 @@
+cbuffer cbuffer_a : register(b0, space0) {
+  uint4 a[4];
+};
+
+float2x2 tint_symbol_1(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 16u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x2 l_a[4] = tint_symbol(a, 0u);
+  const float2x2 l_a_i = tint_symbol_1(a, 32u);
+  const float2 l_a_i_i = asfloat(a[2].zw);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..a3d6e08
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,17 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform a_block_ubo {
+  mat2 inner[4];
+} a;
+
+void f() {
+  mat2 l_a[4] = a.inner;
+  mat2 l_a_i = a.inner[2];
+  vec2 l_a_i_i = a.inner[2][1];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.msl
new file mode 100644
index 0000000..190b395
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.msl
@@ -0,0 +1,23 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+kernel void f(const constant tint_array<float2x2, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<float2x2, 4> const l_a = *(tint_symbol);
+  float2x2 const l_a_i = (*(tint_symbol))[2];
+  float2 const l_a_i_i = (*(tint_symbol))[2][1];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.spvasm
new file mode 100644
index 0000000..0e6ccba
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.spvasm
@@ -0,0 +1,49 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 27
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %a_block "a_block"
+               OpMemberName %a_block 0 "inner"
+               OpName %a "a"
+               OpName %f "f"
+               OpDecorate %a_block Block
+               OpMemberDecorate %a_block 0 Offset 0
+               OpMemberDecorate %a_block 0 ColMajor
+               OpMemberDecorate %a_block 0 MatrixStride 8
+               OpDecorate %_arr_mat2v2float_uint_4 ArrayStride 16
+               OpDecorate %a NonWritable
+               OpDecorate %a DescriptorSet 0
+               OpDecorate %a Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat2v2float = OpTypeMatrix %v2float 2
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat2v2float_uint_4 = OpTypeArray %mat2v2float %uint_4
+    %a_block = OpTypeStruct %_arr_mat2v2float_uint_4
+%_ptr_Uniform_a_block = OpTypePointer Uniform %a_block
+          %a = OpVariable %_ptr_Uniform_a_block Uniform
+       %void = OpTypeVoid
+         %10 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform__arr_mat2v2float_uint_4 = OpTypePointer Uniform %_arr_mat2v2float_uint_4
+        %int = OpTypeInt 32 1
+      %int_2 = OpConstant %int 2
+%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+          %f = OpFunction %void None %10
+         %13 = OpLabel
+         %16 = OpAccessChain %_ptr_Uniform__arr_mat2v2float_uint_4 %a %uint_0
+         %17 = OpLoad %_arr_mat2v2float_uint_4 %16
+         %21 = OpAccessChain %_ptr_Uniform_mat2v2float %a %uint_0 %int_2
+         %22 = OpLoad %mat2v2float %21
+         %25 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %int_2 %int_1
+         %26 = OpLoad %v2float %25
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.wgsl
new file mode 100644
index 0000000..9c17d71
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/static_index_via_ptr.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_a = &(a);
+  let p_a_2 = &((*(p_a))[2]);
+  let p_a_2_1 = &((*(p_a_2))[1]);
+  let l_a : array<mat2x2<f32>, 4> = *(p_a);
+  let l_a_i : mat2x2<f32> = *(p_a_2);
+  let l_a_i_i : vec2<f32> = *(p_a_2_1);
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl
new file mode 100644
index 0000000..db6adf2
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl
@@ -0,0 +1,8 @@
+@group(0) @binding(0) var<uniform> u : array<mat2x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+    let t = transpose(u[2]);
+    let l = length(u[0][1].yx);
+    let a = abs(u[0][1].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..e8f4937
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.dxc.hlsl
@@ -0,0 +1,19 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[4];
+};
+
+float2x2 tint_symbol(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x2 t = transpose(tint_symbol(u, 32u));
+  const float l = length(asfloat(u[0].zw).yx);
+  const float a = abs(asfloat(u[0].zw).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..e8f4937
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.fxc.hlsl
@@ -0,0 +1,19 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[4];
+};
+
+float2x2 tint_symbol(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x2 t = transpose(tint_symbol(u, 32u));
+  const float l = length(asfloat(u[0].zw).yx);
+  const float a = abs(asfloat(u[0].zw).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.glsl
new file mode 100644
index 0000000..ffcbc7c
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.glsl
@@ -0,0 +1,17 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_ubo {
+  mat2 inner[4];
+} u;
+
+void f() {
+  mat2 t = transpose(u.inner[2]);
+  float l = length(u.inner[0][1].yx);
+  float a = abs(u.inner[0][1].yx.x);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.msl
new file mode 100644
index 0000000..5d165882
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.msl
@@ -0,0 +1,23 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+kernel void f(const constant tint_array<float2x2, 4>* tint_symbol [[buffer(0)]]) {
+  float2x2 const t = transpose((*(tint_symbol))[2]);
+  float const l = length(float2((*(tint_symbol))[0][1]).yx);
+  float const a = fabs(float2((*(tint_symbol))[0][1]).yx[0]);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.spvasm
new file mode 100644
index 0000000..399fe03
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+               OpCapability Shader
+         %22 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %u "u"
+               OpName %f "f"
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %_arr_mat2v2float_uint_4 ArrayStride 16
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat2v2float = OpTypeMatrix %v2float 2
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat2v2float_uint_4 = OpTypeArray %mat2v2float %uint_4
+    %u_block = OpTypeStruct %_arr_mat2v2float_uint_4
+%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
+          %u = OpVariable %_ptr_Uniform_u_block Uniform
+       %void = OpTypeVoid
+         %10 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+        %int = OpTypeInt 32 1
+      %int_2 = OpConstant %int 2
+%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
+         %23 = OpConstantNull %int
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+          %f = OpFunction %void None %10
+         %13 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform_mat2v2float %u %uint_0 %int_2
+         %20 = OpLoad %mat2v2float %19
+         %14 = OpTranspose %mat2v2float %20
+         %26 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %23 %int_1
+         %27 = OpLoad %v2float %26
+         %28 = OpVectorShuffle %v2float %27 %27 1 0
+         %21 = OpExtInst %float %22 Length %28
+         %30 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %23 %int_1
+         %31 = OpLoad %v2float %30
+         %32 = OpVectorShuffle %v2float %31 %31 1 0
+         %33 = OpCompositeExtract %float %32 0
+         %29 = OpExtInst %float %22 FAbs %33
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.wgsl
new file mode 100644
index 0000000..853b423
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_builtin.wgsl.expected.wgsl
@@ -0,0 +1,8 @@
+@group(0) @binding(0) var<uniform> u : array<mat2x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  let t = transpose(u[2]);
+  let l = length(u[0][1].yx);
+  let a = abs(u[0][1].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl
new file mode 100644
index 0000000..3bb9cb8
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl
@@ -0,0 +1,14 @@
+@group(0) @binding(0) var<uniform> u : array<mat2x2<f32>, 4>;
+
+fn a(a : array<mat2x2<f32>, 4>) {}
+fn b(m : mat2x2<f32>) {}
+fn c(v : vec2<f32>) {}
+fn d(f : f32) {}
+
+@compute @workgroup_size(1)
+fn f() {
+    a(u);
+    b(u[1]);
+    c(u[1][0].yx);
+    d(u[1][0].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..224ee60
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.dxc.hlsl
@@ -0,0 +1,43 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[4];
+};
+
+void a(float2x2 a_1[4]) {
+}
+
+void b(float2x2 m) {
+}
+
+void c(float2 v) {
+}
+
+void d(float f_1) {
+}
+
+float2x2 tint_symbol_1(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 16u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  a(tint_symbol(u, 0u));
+  b(tint_symbol_1(u, 16u));
+  c(asfloat(u[1].xy).yx);
+  d(asfloat(u[1].xy).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..224ee60
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.fxc.hlsl
@@ -0,0 +1,43 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[4];
+};
+
+void a(float2x2 a_1[4]) {
+}
+
+void b(float2x2 m) {
+}
+
+void c(float2 v) {
+}
+
+void d(float f_1) {
+}
+
+float2x2 tint_symbol_1(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 16u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  a(tint_symbol(u, 0u));
+  b(tint_symbol_1(u, 16u));
+  c(asfloat(u[1].xy).yx);
+  d(asfloat(u[1].xy).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.glsl
new file mode 100644
index 0000000..bc291fd
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.glsl
@@ -0,0 +1,30 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_ubo {
+  mat2 inner[4];
+} u;
+
+void a(mat2 a_1[4]) {
+}
+
+void b(mat2 m) {
+}
+
+void c(vec2 v) {
+}
+
+void d(float f_1) {
+}
+
+void f() {
+  a(u.inner);
+  b(u.inner[1]);
+  c(u.inner[1][0].yx);
+  d(u.inner[1][0].yx.x);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.msl
new file mode 100644
index 0000000..abc8d5d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.msl
@@ -0,0 +1,36 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+void a(tint_array<float2x2, 4> a_1) {
+}
+
+void b(float2x2 m) {
+}
+
+void c(float2 v) {
+}
+
+void d(float f_1) {
+}
+
+kernel void f(const constant tint_array<float2x2, 4>* tint_symbol [[buffer(0)]]) {
+  a(*(tint_symbol));
+  b((*(tint_symbol))[1]);
+  c(float2((*(tint_symbol))[1][0]).yx);
+  d(float2((*(tint_symbol))[1][0]).yx[0]);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.spvasm
new file mode 100644
index 0000000..8f407ac
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.spvasm
@@ -0,0 +1,90 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 52
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %u "u"
+               OpName %a "a"
+               OpName %a_1 "a_1"
+               OpName %b "b"
+               OpName %m "m"
+               OpName %c "c"
+               OpName %v "v"
+               OpName %d "d"
+               OpName %f_1 "f_1"
+               OpName %f "f"
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %_arr_mat2v2float_uint_4 ArrayStride 16
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat2v2float = OpTypeMatrix %v2float 2
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat2v2float_uint_4 = OpTypeArray %mat2v2float %uint_4
+    %u_block = OpTypeStruct %_arr_mat2v2float_uint_4
+%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
+          %u = OpVariable %_ptr_Uniform_u_block Uniform
+       %void = OpTypeVoid
+         %10 = OpTypeFunction %void %_arr_mat2v2float_uint_4
+         %15 = OpTypeFunction %void %mat2v2float
+         %19 = OpTypeFunction %void %v2float
+         %23 = OpTypeFunction %void %float
+         %27 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform__arr_mat2v2float_uint_4 = OpTypePointer Uniform %_arr_mat2v2float_uint_4
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
+         %42 = OpConstantNull %int
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+          %a = OpFunction %void None %10
+        %a_1 = OpFunctionParameter %_arr_mat2v2float_uint_4
+         %14 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %b = OpFunction %void None %15
+          %m = OpFunctionParameter %mat2v2float
+         %18 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %c = OpFunction %void None %19
+          %v = OpFunctionParameter %v2float
+         %22 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %d = OpFunction %void None %23
+        %f_1 = OpFunctionParameter %float
+         %26 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %27
+         %29 = OpLabel
+         %33 = OpAccessChain %_ptr_Uniform__arr_mat2v2float_uint_4 %u %uint_0
+         %34 = OpLoad %_arr_mat2v2float_uint_4 %33
+         %30 = OpFunctionCall %void %a %34
+         %39 = OpAccessChain %_ptr_Uniform_mat2v2float %u %uint_0 %int_1
+         %40 = OpLoad %mat2v2float %39
+         %35 = OpFunctionCall %void %b %40
+         %44 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %int_1 %42
+         %45 = OpLoad %v2float %44
+         %46 = OpVectorShuffle %v2float %45 %45 1 0
+         %41 = OpFunctionCall %void %c %46
+         %48 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %int_1 %42
+         %49 = OpLoad %v2float %48
+         %50 = OpVectorShuffle %v2float %49 %49 1 0
+         %51 = OpCompositeExtract %float %50 0
+         %47 = OpFunctionCall %void %d %51
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.wgsl
new file mode 100644
index 0000000..fd3bf0c
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_fn.wgsl.expected.wgsl
@@ -0,0 +1,21 @@
+@group(0) @binding(0) var<uniform> u : array<mat2x2<f32>, 4>;
+
+fn a(a : array<mat2x2<f32>, 4>) {
+}
+
+fn b(m : mat2x2<f32>) {
+}
+
+fn c(v : vec2<f32>) {
+}
+
+fn d(f : f32) {
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  a(u);
+  b(u[1]);
+  c(u[1][0].yx);
+  d(u[1][0].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl
new file mode 100644
index 0000000..8a421d8
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl
@@ -0,0 +1,16 @@
+struct S {
+  before : i32,
+  m : mat2x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat2x2<f32>, 4>;
+var<private> p : array<mat2x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+    p = u;
+    p[1] = u[2];
+    p[1][0] = u[0][1].yx;
+    p[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..1af9923
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.dxc.hlsl
@@ -0,0 +1,32 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[4];
+};
+static float2x2 p[4] = (float2x2[4])0;
+
+float2x2 tint_symbol_1(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 16u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  p = tint_symbol(u, 0u);
+  p[1] = tint_symbol_1(u, 32u);
+  p[1][0] = asfloat(u[0].zw).yx;
+  p[1][0].x = asfloat(u[0].z);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..1af9923
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.fxc.hlsl
@@ -0,0 +1,32 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[4];
+};
+static float2x2 p[4] = (float2x2[4])0;
+
+float2x2 tint_symbol_1(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 16u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  p = tint_symbol(u, 0u);
+  p[1] = tint_symbol_1(u, 32u);
+  p[1][0] = asfloat(u[0].zw).yx;
+  p[1][0].x = asfloat(u[0].z);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.glsl
new file mode 100644
index 0000000..59ec729
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.glsl
@@ -0,0 +1,25 @@
+#version 310 es
+
+struct S {
+  int before;
+  mat2 m;
+  int after;
+};
+
+layout(binding = 0, std140) uniform u_block_ubo {
+  mat2 inner[4];
+} u;
+
+mat2 p[4] = mat2[4](mat2(0.0f, 0.0f, 0.0f, 0.0f), mat2(0.0f, 0.0f, 0.0f, 0.0f), mat2(0.0f, 0.0f, 0.0f, 0.0f), mat2(0.0f, 0.0f, 0.0f, 0.0f));
+void f() {
+  p = u.inner;
+  p[1] = u.inner[2];
+  p[1][0] = u.inner[0][1].yx;
+  p[1][0].x = u.inner[0][1].x;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.msl
new file mode 100644
index 0000000..ec3ed6d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.msl
@@ -0,0 +1,31 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct S {
+  int before;
+  float2x2 m;
+  int after;
+};
+
+kernel void f(const constant tint_array<float2x2, 4>* tint_symbol_1 [[buffer(0)]]) {
+  thread tint_array<float2x2, 4> tint_symbol = {};
+  tint_symbol = *(tint_symbol_1);
+  tint_symbol[1] = (*(tint_symbol_1))[2];
+  tint_symbol[1][0] = float2((*(tint_symbol_1))[0][1]).yx;
+  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.spvasm
new file mode 100644
index 0000000..922f2c7
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.spvasm
@@ -0,0 +1,68 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 41
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %u "u"
+               OpName %p "p"
+               OpName %f "f"
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %_arr_mat2v2float_uint_4 ArrayStride 16
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat2v2float = OpTypeMatrix %v2float 2
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat2v2float_uint_4 = OpTypeArray %mat2v2float %uint_4
+    %u_block = OpTypeStruct %_arr_mat2v2float_uint_4
+%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
+          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%_ptr_Private__arr_mat2v2float_uint_4 = OpTypePointer Private %_arr_mat2v2float_uint_4
+         %12 = OpConstantNull %_arr_mat2v2float_uint_4
+          %p = OpVariable %_ptr_Private__arr_mat2v2float_uint_4 Private %12
+       %void = OpTypeVoid
+         %13 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform__arr_mat2v2float_uint_4 = OpTypePointer Uniform %_arr_mat2v2float_uint_4
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_Private_mat2v2float = OpTypePointer Private %mat2v2float
+      %int_2 = OpConstant %int 2
+%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
+         %29 = OpConstantNull %int
+%_ptr_Private_v2float = OpTypePointer Private %v2float
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%_ptr_Private_float = OpTypePointer Private %float
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+          %f = OpFunction %void None %13
+         %16 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform__arr_mat2v2float_uint_4 %u %uint_0
+         %20 = OpLoad %_arr_mat2v2float_uint_4 %19
+               OpStore %p %20
+         %24 = OpAccessChain %_ptr_Private_mat2v2float %p %int_1
+         %27 = OpAccessChain %_ptr_Uniform_mat2v2float %u %uint_0 %int_2
+         %28 = OpLoad %mat2v2float %27
+               OpStore %24 %28
+         %31 = OpAccessChain %_ptr_Private_v2float %p %int_1 %29
+         %33 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %29 %int_1
+         %34 = OpLoad %v2float %33
+         %35 = OpVectorShuffle %v2float %34 %34 1 0
+               OpStore %31 %35
+         %37 = OpAccessChain %_ptr_Private_float %p %int_1 %29 %uint_0
+         %39 = OpAccessChain %_ptr_Uniform_float %u %uint_0 %29 %int_1 %uint_0
+         %40 = OpLoad %float %39
+               OpStore %37 %40
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.wgsl
new file mode 100644
index 0000000..732f5d6
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_private.wgsl.expected.wgsl
@@ -0,0 +1,17 @@
+struct S {
+  before : i32,
+  m : mat2x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat2x2<f32>, 4>;
+
+var<private> p : array<mat2x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  p = u;
+  p[1] = u[2];
+  p[1][0] = u[0][1].yx;
+  p[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl
new file mode 100644
index 0000000..3a40144
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl
@@ -0,0 +1,16 @@
+struct S {
+  before : i32,
+  m : mat2x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat2x2<f32>, 4>;
+@group(0) @binding(1) var<storage, read_write> s : array<mat2x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+    s = u;
+    s[1] = u[2];
+    s[1][0] = u[0][1].yx;
+    s[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..3714023
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.dxc.hlsl
@@ -0,0 +1,46 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[4];
+};
+RWByteAddressBuffer s : register(u1, space0);
+
+void tint_symbol_1(RWByteAddressBuffer buffer, uint offset, float2x2 value) {
+  buffer.Store2((offset + 0u), asuint(value[0u]));
+  buffer.Store2((offset + 8u), asuint(value[1u]));
+}
+
+void tint_symbol(RWByteAddressBuffer buffer, uint offset, float2x2 value[4]) {
+  float2x2 array[4] = value;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      tint_symbol_1(buffer, (offset + (i * 16u)), array[i]);
+    }
+  }
+}
+
+float2x2 tint_symbol_4(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_3_ret[4];
+tint_symbol_3_ret tint_symbol_3(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_4(buffer, (offset + (i_1 * 16u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  tint_symbol(s, 0u, tint_symbol_3(u, 0u));
+  tint_symbol_1(s, 16u, tint_symbol_4(u, 32u));
+  s.Store2(16u, asuint(asfloat(u[0].zw).yx));
+  s.Store(16u, asuint(asfloat(u[0].z)));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..3714023
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.fxc.hlsl
@@ -0,0 +1,46 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[4];
+};
+RWByteAddressBuffer s : register(u1, space0);
+
+void tint_symbol_1(RWByteAddressBuffer buffer, uint offset, float2x2 value) {
+  buffer.Store2((offset + 0u), asuint(value[0u]));
+  buffer.Store2((offset + 8u), asuint(value[1u]));
+}
+
+void tint_symbol(RWByteAddressBuffer buffer, uint offset, float2x2 value[4]) {
+  float2x2 array[4] = value;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      tint_symbol_1(buffer, (offset + (i * 16u)), array[i]);
+    }
+  }
+}
+
+float2x2 tint_symbol_4(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_3_ret[4];
+tint_symbol_3_ret tint_symbol_3(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_4(buffer, (offset + (i_1 * 16u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  tint_symbol(s, 0u, tint_symbol_3(u, 0u));
+  tint_symbol_1(s, 16u, tint_symbol_4(u, 32u));
+  s.Store2(16u, asuint(asfloat(u[0].zw).yx));
+  s.Store(16u, asuint(asfloat(u[0].z)));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.glsl
new file mode 100644
index 0000000..2a920f8
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.glsl
@@ -0,0 +1,28 @@
+#version 310 es
+
+struct S {
+  int before;
+  mat2 m;
+  int after;
+};
+
+layout(binding = 0, std140) uniform u_block_ubo {
+  mat2 inner[4];
+} u;
+
+layout(binding = 1, std430) buffer u_block_ssbo {
+  mat2 inner[4];
+} s;
+
+void f() {
+  s.inner = u.inner;
+  s.inner[1] = u.inner[2];
+  s.inner[1][0] = u.inner[0][1].yx;
+  s.inner[1][0].x = u.inner[0][1].x;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.msl
new file mode 100644
index 0000000..892ef66
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.msl
@@ -0,0 +1,30 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct S {
+  int before;
+  float2x2 m;
+  int after;
+};
+
+kernel void f(device tint_array<float2x2, 4>* tint_symbol [[buffer(1)]], const constant tint_array<float2x2, 4>* tint_symbol_1 [[buffer(0)]]) {
+  *(tint_symbol) = *(tint_symbol_1);
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
+  (*(tint_symbol))[1][0] = float2((*(tint_symbol_1))[0][1]).yx;
+  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.spvasm
new file mode 100644
index 0000000..19eba56
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 42
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %u "u"
+               OpName %s "s"
+               OpName %f "f"
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %_arr_mat2v2float_uint_4 ArrayStride 16
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+               OpDecorate %s DescriptorSet 0
+               OpDecorate %s Binding 1
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat2v2float = OpTypeMatrix %v2float 2
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat2v2float_uint_4 = OpTypeArray %mat2v2float %uint_4
+    %u_block = OpTypeStruct %_arr_mat2v2float_uint_4
+%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
+          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%_ptr_StorageBuffer_u_block = OpTypePointer StorageBuffer %u_block
+          %s = OpVariable %_ptr_StorageBuffer_u_block StorageBuffer
+       %void = OpTypeVoid
+         %12 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer__arr_mat2v2float_uint_4 = OpTypePointer StorageBuffer %_arr_mat2v2float_uint_4
+%_ptr_Uniform__arr_mat2v2float_uint_4 = OpTypePointer Uniform %_arr_mat2v2float_uint_4
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_StorageBuffer_mat2v2float = OpTypePointer StorageBuffer %mat2v2float
+      %int_2 = OpConstant %int 2
+%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
+         %30 = OpConstantNull %int
+%_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+          %f = OpFunction %void None %12
+         %15 = OpLabel
+         %18 = OpAccessChain %_ptr_StorageBuffer__arr_mat2v2float_uint_4 %s %uint_0
+         %20 = OpAccessChain %_ptr_Uniform__arr_mat2v2float_uint_4 %u %uint_0
+         %21 = OpLoad %_arr_mat2v2float_uint_4 %20
+               OpStore %18 %21
+         %25 = OpAccessChain %_ptr_StorageBuffer_mat2v2float %s %uint_0 %int_1
+         %28 = OpAccessChain %_ptr_Uniform_mat2v2float %u %uint_0 %int_2
+         %29 = OpLoad %mat2v2float %28
+               OpStore %25 %29
+         %32 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1 %30
+         %34 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %30 %int_1
+         %35 = OpLoad %v2float %34
+         %36 = OpVectorShuffle %v2float %35 %35 1 0
+               OpStore %32 %36
+         %38 = OpAccessChain %_ptr_StorageBuffer_float %s %uint_0 %int_1 %30 %uint_0
+         %40 = OpAccessChain %_ptr_Uniform_float %u %uint_0 %30 %int_1 %uint_0
+         %41 = OpLoad %float %40
+               OpStore %38 %41
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.wgsl
new file mode 100644
index 0000000..1173503
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_storage.wgsl.expected.wgsl
@@ -0,0 +1,17 @@
+struct S {
+  before : i32,
+  m : mat2x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat2x2<f32>, 4>;
+
+@group(0) @binding(1) var<storage, read_write> s : array<mat2x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  s = u;
+  s[1] = u[2];
+  s[1][0] = u[0][1].yx;
+  s[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl
new file mode 100644
index 0000000..08ce8f6
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl
@@ -0,0 +1,16 @@
+struct S {
+  before : i32,
+  m : mat2x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat2x2<f32>, 4>;
+var<workgroup> w : array<mat2x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+    w = u;
+    w[1] = u[2];
+    w[1][0] = u[0][1].yx;
+    w[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..fa0cad4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.dxc.hlsl
@@ -0,0 +1,47 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[4];
+};
+groupshared float2x2 w[4];
+
+struct tint_symbol_1 {
+  uint local_invocation_index : SV_GroupIndex;
+};
+
+float2x2 tint_symbol_3(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_2_ret[4];
+tint_symbol_2_ret tint_symbol_2(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_3(buffer, (offset + (i_1 * 16u)));
+    }
+  }
+  return arr;
+}
+
+void f_inner(uint local_invocation_index) {
+  {
+    [loop] for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+      const uint i = idx;
+      w[i] = float2x2((0.0f).xx, (0.0f).xx);
+    }
+  }
+  GroupMemoryBarrierWithGroupSync();
+  w = tint_symbol_2(u, 0u);
+  w[1] = tint_symbol_3(u, 32u);
+  w[1][0] = asfloat(u[0].zw).yx;
+  w[1][0].x = asfloat(u[0].z);
+}
+
+[numthreads(1, 1, 1)]
+void f(tint_symbol_1 tint_symbol) {
+  f_inner(tint_symbol.local_invocation_index);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..fa0cad4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.fxc.hlsl
@@ -0,0 +1,47 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[4];
+};
+groupshared float2x2 w[4];
+
+struct tint_symbol_1 {
+  uint local_invocation_index : SV_GroupIndex;
+};
+
+float2x2 tint_symbol_3(uint4 buffer[4], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+typedef float2x2 tint_symbol_2_ret[4];
+tint_symbol_2_ret tint_symbol_2(uint4 buffer[4], uint offset) {
+  float2x2 arr[4] = (float2x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_3(buffer, (offset + (i_1 * 16u)));
+    }
+  }
+  return arr;
+}
+
+void f_inner(uint local_invocation_index) {
+  {
+    [loop] for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+      const uint i = idx;
+      w[i] = float2x2((0.0f).xx, (0.0f).xx);
+    }
+  }
+  GroupMemoryBarrierWithGroupSync();
+  w = tint_symbol_2(u, 0u);
+  w[1] = tint_symbol_3(u, 32u);
+  w[1][0] = asfloat(u[0].zw).yx;
+  w[1][0].x = asfloat(u[0].z);
+}
+
+[numthreads(1, 1, 1)]
+void f(tint_symbol_1 tint_symbol) {
+  f_inner(tint_symbol.local_invocation_index);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.glsl
new file mode 100644
index 0000000..8dcc07d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.glsl
@@ -0,0 +1,32 @@
+#version 310 es
+
+struct S {
+  int before;
+  mat2 m;
+  int after;
+};
+
+layout(binding = 0, std140) uniform u_block_ubo {
+  mat2 inner[4];
+} u;
+
+shared mat2 w[4];
+void f(uint local_invocation_index) {
+  {
+    for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+      uint i = idx;
+      w[i] = mat2(vec2(0.0f), vec2(0.0f));
+    }
+  }
+  barrier();
+  w = u.inner;
+  w[1] = u.inner[2];
+  w[1][0] = u.inner[0][1].yx;
+  w[1][0].x = u.inner[0][1].x;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f(gl_LocalInvocationIndex);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.msl
new file mode 100644
index 0000000..4f8574d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.msl
@@ -0,0 +1,44 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct tint_symbol_5 {
+  tint_array<float2x2, 4> w;
+};
+
+struct S {
+  int before;
+  float2x2 m;
+  int after;
+};
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<float2x2, 4>* const tint_symbol, const constant tint_array<float2x2, 4>* const tint_symbol_1) {
+  for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+    uint const i = idx;
+    (*(tint_symbol))[i] = float2x2(float2(0.0f), float2(0.0f));
+  }
+  threadgroup_barrier(mem_flags::mem_threadgroup);
+  *(tint_symbol) = *(tint_symbol_1);
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
+  (*(tint_symbol))[1][0] = float2((*(tint_symbol_1))[0][1]).yx;
+  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+}
+
+kernel void f(const constant tint_array<float2x2, 4>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+  threadgroup tint_array<float2x2, 4>* const tint_symbol_2 = &((*(tint_symbol_3)).w);
+  f_inner(local_invocation_index, tint_symbol_2, tint_symbol_4);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.spvasm
new file mode 100644
index 0000000..495667c
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.spvasm
@@ -0,0 +1,115 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 70
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f" %local_invocation_index_1
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %local_invocation_index_1 "local_invocation_index_1"
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %u "u"
+               OpName %w "w"
+               OpName %f_inner "f_inner"
+               OpName %local_invocation_index "local_invocation_index"
+               OpName %idx "idx"
+               OpName %f "f"
+               OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %_arr_mat2v2float_uint_4 ArrayStride 16
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+       %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat2v2float = OpTypeMatrix %v2float 2
+     %uint_4 = OpConstant %uint 4
+%_arr_mat2v2float_uint_4 = OpTypeArray %mat2v2float %uint_4
+    %u_block = OpTypeStruct %_arr_mat2v2float_uint_4
+%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
+          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%_ptr_Workgroup__arr_mat2v2float_uint_4 = OpTypePointer Workgroup %_arr_mat2v2float_uint_4
+          %w = OpVariable %_ptr_Workgroup__arr_mat2v2float_uint_4 Workgroup
+       %void = OpTypeVoid
+         %14 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+         %21 = OpConstantNull %uint
+       %bool = OpTypeBool
+%_ptr_Workgroup_mat2v2float = OpTypePointer Workgroup %mat2v2float
+         %35 = OpConstantNull %mat2v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+   %uint_264 = OpConstant %uint 264
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform__arr_mat2v2float_uint_4 = OpTypePointer Uniform %_arr_mat2v2float_uint_4
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+      %int_2 = OpConstant %int 2
+%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
+         %53 = OpConstantNull %int
+%_ptr_Workgroup_v2float = OpTypePointer Workgroup %v2float
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%_ptr_Workgroup_float = OpTypePointer Workgroup %float
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+         %65 = OpTypeFunction %void
+    %f_inner = OpFunction %void None %14
+%local_invocation_index = OpFunctionParameter %uint
+         %18 = OpLabel
+        %idx = OpVariable %_ptr_Function_uint Function %21
+               OpStore %idx %local_invocation_index
+               OpBranch %22
+         %22 = OpLabel
+               OpLoopMerge %23 %24 None
+               OpBranch %25
+         %25 = OpLabel
+         %27 = OpLoad %uint %idx
+         %28 = OpULessThan %bool %27 %uint_4
+         %26 = OpLogicalNot %bool %28
+               OpSelectionMerge %30 None
+               OpBranchConditional %26 %31 %30
+         %31 = OpLabel
+               OpBranch %23
+         %30 = OpLabel
+         %32 = OpLoad %uint %idx
+         %34 = OpAccessChain %_ptr_Workgroup_mat2v2float %w %32
+               OpStore %34 %35
+               OpBranch %24
+         %24 = OpLabel
+         %36 = OpLoad %uint %idx
+         %38 = OpIAdd %uint %36 %uint_1
+               OpStore %idx %38
+               OpBranch %22
+         %23 = OpLabel
+               OpControlBarrier %uint_2 %uint_2 %uint_264
+         %44 = OpAccessChain %_ptr_Uniform__arr_mat2v2float_uint_4 %u %uint_0
+         %45 = OpLoad %_arr_mat2v2float_uint_4 %44
+               OpStore %w %45
+         %48 = OpAccessChain %_ptr_Workgroup_mat2v2float %w %int_1
+         %51 = OpAccessChain %_ptr_Uniform_mat2v2float %u %uint_0 %int_2
+         %52 = OpLoad %mat2v2float %51
+               OpStore %48 %52
+         %55 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1 %53
+         %57 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %53 %int_1
+         %58 = OpLoad %v2float %57
+         %59 = OpVectorShuffle %v2float %58 %58 1 0
+               OpStore %55 %59
+         %61 = OpAccessChain %_ptr_Workgroup_float %w %int_1 %53 %uint_0
+         %63 = OpAccessChain %_ptr_Uniform_float %u %uint_0 %53 %int_1 %uint_0
+         %64 = OpLoad %float %63
+               OpStore %61 %64
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %65
+         %67 = OpLabel
+         %69 = OpLoad %uint %local_invocation_index_1
+         %68 = OpFunctionCall %void %f_inner %69
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.wgsl
new file mode 100644
index 0000000..fdb82d0
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat2x2/to_workgroup.wgsl.expected.wgsl
@@ -0,0 +1,17 @@
+struct S {
+  before : i32,
+  m : mat2x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat2x2<f32>, 4>;
+
+var<workgroup> w : array<mat2x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  w = u;
+  w[1] = u[2];
+  w[1][0] = u[0][1].yx;
+  w[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl
new file mode 100644
index 0000000..9e1a54d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl
@@ -0,0 +1,15 @@
+@group(0) @binding(0) var<uniform> a : array<mat4x2<f32>, 4>;
+
+var<private> counter = 0;
+fn i() -> i32 { counter++; return counter; }
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_a       = &a;
+  let p_a_i     = &((*p_a)[i()]);
+  let p_a_i_i   = &((*p_a_i)[i()]);
+
+  let l_a       : array<mat4x2<f32>, 4> = *p_a;
+  let l_a_i     : mat4x2<f32>           = *p_a_i;
+  let l_a_i_i   : vec2<f32>             = *p_a_i_i;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..6c19c10
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -0,0 +1,44 @@
+cbuffer cbuffer_a : register(b0, space0) {
+  uint4 a[8];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float4x2 tint_symbol_1(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_1(buffer, (offset + (i_1 * 32u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const int p_a_i_save = i();
+  const int p_a_i_i_save = i();
+  const float4x2 l_a[4] = tint_symbol(a, 0u);
+  const float4x2 l_a_i = tint_symbol_1(a, (32u * uint(p_a_i_save)));
+  const uint scalar_offset_4 = (((32u * uint(p_a_i_save)) + (8u * uint(p_a_i_i_save)))) / 4;
+  uint4 ubo_load_4 = a[scalar_offset_4 / 4];
+  const float2 l_a_i_i = asfloat(((scalar_offset_4 & 2) ? ubo_load_4.zw : ubo_load_4.xy));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..6c19c10
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -0,0 +1,44 @@
+cbuffer cbuffer_a : register(b0, space0) {
+  uint4 a[8];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float4x2 tint_symbol_1(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_1(buffer, (offset + (i_1 * 32u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const int p_a_i_save = i();
+  const int p_a_i_i_save = i();
+  const float4x2 l_a[4] = tint_symbol(a, 0u);
+  const float4x2 l_a_i = tint_symbol_1(a, (32u * uint(p_a_i_save)));
+  const uint scalar_offset_4 = (((32u * uint(p_a_i_save)) + (8u * uint(p_a_i_i_save)))) / 4;
+  uint4 ubo_load_4 = a[scalar_offset_4 / 4];
+  const float2 l_a_i_i = asfloat(((scalar_offset_4 & 2) ? ubo_load_4.zw : ubo_load_4.xy));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..a71a143
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,27 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform a_block_ubo {
+  mat4x2 inner[4];
+} a;
+
+int counter = 0;
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+void f() {
+  int tint_symbol = i();
+  int p_a_i_save = tint_symbol;
+  int tint_symbol_1 = i();
+  int p_a_i_i_save = tint_symbol_1;
+  mat4x2 l_a[4] = a.inner;
+  mat4x2 l_a_i = a.inner[p_a_i_save];
+  vec2 l_a_i_i = a.inner[p_a_i_save][p_a_i_i_save];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl
new file mode 100644
index 0000000..cffca67
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl
@@ -0,0 +1,33 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+int i() {
+  thread int tint_symbol_2 = 0;
+  tint_symbol_2 = as_type<int>((as_type<uint>(tint_symbol_2) + as_type<uint>(1)));
+  return tint_symbol_2;
+}
+
+kernel void f(const constant tint_array<float4x2, 4>* tint_symbol_3 [[buffer(0)]]) {
+  int const tint_symbol = i();
+  int const p_a_i_save = tint_symbol;
+  int const tint_symbol_1 = i();
+  int const p_a_i_i_save = tint_symbol_1;
+  tint_array<float4x2, 4> const l_a = *(tint_symbol_3);
+  float4x2 const l_a_i = (*(tint_symbol_3))[p_a_i_save];
+  float2 const l_a_i_i = (*(tint_symbol_3))[p_a_i_save][p_a_i_i_save];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm
new file mode 100644
index 0000000..11457bd
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 37
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %a_block "a_block"
+               OpMemberName %a_block 0 "inner"
+               OpName %a "a"
+               OpName %counter "counter"
+               OpName %i "i"
+               OpName %f "f"
+               OpDecorate %a_block Block
+               OpMemberDecorate %a_block 0 Offset 0
+               OpMemberDecorate %a_block 0 ColMajor
+               OpMemberDecorate %a_block 0 MatrixStride 8
+               OpDecorate %_arr_mat4v2float_uint_4 ArrayStride 32
+               OpDecorate %a NonWritable
+               OpDecorate %a DescriptorSet 0
+               OpDecorate %a Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat4v2float = OpTypeMatrix %v2float 4
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat4v2float_uint_4 = OpTypeArray %mat4v2float %uint_4
+    %a_block = OpTypeStruct %_arr_mat4v2float_uint_4
+%_ptr_Uniform_a_block = OpTypePointer Uniform %a_block
+          %a = OpVariable %_ptr_Uniform_a_block Uniform
+        %int = OpTypeInt 32 1
+         %11 = OpConstantNull %int
+%_ptr_Private_int = OpTypePointer Private %int
+    %counter = OpVariable %_ptr_Private_int Private %11
+         %14 = OpTypeFunction %int
+      %int_1 = OpConstant %int 1
+       %void = OpTypeVoid
+         %21 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform__arr_mat4v2float_uint_4 = OpTypePointer Uniform %_arr_mat4v2float_uint_4
+%_ptr_Uniform_mat4v2float = OpTypePointer Uniform %mat4v2float
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+          %i = OpFunction %int None %14
+         %16 = OpLabel
+         %17 = OpLoad %int %counter
+         %19 = OpIAdd %int %17 %int_1
+               OpStore %counter %19
+         %20 = OpLoad %int %counter
+               OpReturnValue %20
+               OpFunctionEnd
+          %f = OpFunction %void None %21
+         %24 = OpLabel
+         %25 = OpFunctionCall %int %i
+         %26 = OpFunctionCall %int %i
+         %29 = OpAccessChain %_ptr_Uniform__arr_mat4v2float_uint_4 %a %uint_0
+         %30 = OpLoad %_arr_mat4v2float_uint_4 %29
+         %32 = OpAccessChain %_ptr_Uniform_mat4v2float %a %uint_0 %25
+         %33 = OpLoad %mat4v2float %32
+         %35 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %25 %26
+         %36 = OpLoad %v2float %35
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl
new file mode 100644
index 0000000..ede7b60
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl
@@ -0,0 +1,18 @@
+@group(0) @binding(0) var<uniform> a : array<mat4x2<f32>, 4>;
+
+var<private> counter = 0;
+
+fn i() -> i32 {
+  counter++;
+  return counter;
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_a = &(a);
+  let p_a_i = &((*(p_a))[i()]);
+  let p_a_i_i = &((*(p_a_i))[i()]);
+  let l_a : array<mat4x2<f32>, 4> = *(p_a);
+  let l_a_i : mat4x2<f32> = *(p_a_i);
+  let l_a_i_i : vec2<f32> = *(p_a_i_i);
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl
new file mode 100644
index 0000000..c51141a
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl
@@ -0,0 +1,12 @@
+@group(0) @binding(0) var<uniform> a : array<mat4x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_a       = &a;
+  let p_a_2     = &((*p_a)[2]);
+  let p_a_2_1   = &((*p_a_2)[1]);
+
+  let l_a       : array<mat4x2<f32>, 4> = *p_a;
+  let l_a_i     : mat4x2<f32>           = *p_a_2;
+  let l_a_i_i   : vec2<f32>             = *p_a_2_1;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..5d255ce
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+cbuffer cbuffer_a : register(b0, space0) {
+  uint4 a[8];
+};
+
+float4x2 tint_symbol_1(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 32u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float4x2 l_a[4] = tint_symbol(a, 0u);
+  const float4x2 l_a_i = tint_symbol_1(a, 64u);
+  const float2 l_a_i_i = asfloat(a[4].zw);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..5d255ce
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+cbuffer cbuffer_a : register(b0, space0) {
+  uint4 a[8];
+};
+
+float4x2 tint_symbol_1(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 32u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float4x2 l_a[4] = tint_symbol(a, 0u);
+  const float4x2 l_a_i = tint_symbol_1(a, 64u);
+  const float2 l_a_i_i = asfloat(a[4].zw);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..ef740a1
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,17 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform a_block_ubo {
+  mat4x2 inner[4];
+} a;
+
+void f() {
+  mat4x2 l_a[4] = a.inner;
+  mat4x2 l_a_i = a.inner[2];
+  vec2 l_a_i_i = a.inner[2][1];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.msl
new file mode 100644
index 0000000..6de7aca
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.msl
@@ -0,0 +1,23 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+kernel void f(const constant tint_array<float4x2, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<float4x2, 4> const l_a = *(tint_symbol);
+  float4x2 const l_a_i = (*(tint_symbol))[2];
+  float2 const l_a_i_i = (*(tint_symbol))[2][1];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.spvasm
new file mode 100644
index 0000000..d69110b
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.spvasm
@@ -0,0 +1,49 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 27
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %a_block "a_block"
+               OpMemberName %a_block 0 "inner"
+               OpName %a "a"
+               OpName %f "f"
+               OpDecorate %a_block Block
+               OpMemberDecorate %a_block 0 Offset 0
+               OpMemberDecorate %a_block 0 ColMajor
+               OpMemberDecorate %a_block 0 MatrixStride 8
+               OpDecorate %_arr_mat4v2float_uint_4 ArrayStride 32
+               OpDecorate %a NonWritable
+               OpDecorate %a DescriptorSet 0
+               OpDecorate %a Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat4v2float = OpTypeMatrix %v2float 4
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat4v2float_uint_4 = OpTypeArray %mat4v2float %uint_4
+    %a_block = OpTypeStruct %_arr_mat4v2float_uint_4
+%_ptr_Uniform_a_block = OpTypePointer Uniform %a_block
+          %a = OpVariable %_ptr_Uniform_a_block Uniform
+       %void = OpTypeVoid
+         %10 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform__arr_mat4v2float_uint_4 = OpTypePointer Uniform %_arr_mat4v2float_uint_4
+        %int = OpTypeInt 32 1
+      %int_2 = OpConstant %int 2
+%_ptr_Uniform_mat4v2float = OpTypePointer Uniform %mat4v2float
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+          %f = OpFunction %void None %10
+         %13 = OpLabel
+         %16 = OpAccessChain %_ptr_Uniform__arr_mat4v2float_uint_4 %a %uint_0
+         %17 = OpLoad %_arr_mat4v2float_uint_4 %16
+         %21 = OpAccessChain %_ptr_Uniform_mat4v2float %a %uint_0 %int_2
+         %22 = OpLoad %mat4v2float %21
+         %25 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %int_2 %int_1
+         %26 = OpLoad %v2float %25
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.wgsl
new file mode 100644
index 0000000..800ccf6
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/static_index_via_ptr.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> a : array<mat4x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_a = &(a);
+  let p_a_2 = &((*(p_a))[2]);
+  let p_a_2_1 = &((*(p_a_2))[1]);
+  let l_a : array<mat4x2<f32>, 4> = *(p_a);
+  let l_a_i : mat4x2<f32> = *(p_a_2);
+  let l_a_i_i : vec2<f32> = *(p_a_2_1);
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl
new file mode 100644
index 0000000..9657c4a
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl
@@ -0,0 +1,14 @@
+@group(0) @binding(0) var<uniform> u : array<mat4x2<f32>, 4>;
+
+fn a(a : array<mat4x2<f32>, 4>) {}
+fn b(m : mat4x2<f32>) {}
+fn c(v : vec2<f32>) {}
+fn d(f : f32) {}
+
+@compute @workgroup_size(1)
+fn f() {
+    a(u);
+    b(u[1]);
+    c(u[1][0].yx);
+    d(u[1][0].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..9bb94e2
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.dxc.hlsl
@@ -0,0 +1,47 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[8];
+};
+
+void a(float4x2 a_1[4]) {
+}
+
+void b(float4x2 m) {
+}
+
+void c(float2 v) {
+}
+
+void d(float f_1) {
+}
+
+float4x2 tint_symbol_1(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 32u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  a(tint_symbol(u, 0u));
+  b(tint_symbol_1(u, 32u));
+  c(asfloat(u[2].xy).yx);
+  d(asfloat(u[2].xy).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..9bb94e2
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.fxc.hlsl
@@ -0,0 +1,47 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[8];
+};
+
+void a(float4x2 a_1[4]) {
+}
+
+void b(float4x2 m) {
+}
+
+void c(float2 v) {
+}
+
+void d(float f_1) {
+}
+
+float4x2 tint_symbol_1(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 32u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  a(tint_symbol(u, 0u));
+  b(tint_symbol_1(u, 32u));
+  c(asfloat(u[2].xy).yx);
+  d(asfloat(u[2].xy).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.glsl
new file mode 100644
index 0000000..850d586
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.glsl
@@ -0,0 +1,30 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_ubo {
+  mat4x2 inner[4];
+} u;
+
+void a(mat4x2 a_1[4]) {
+}
+
+void b(mat4x2 m) {
+}
+
+void c(vec2 v) {
+}
+
+void d(float f_1) {
+}
+
+void f() {
+  a(u.inner);
+  b(u.inner[1]);
+  c(u.inner[1][0].yx);
+  d(u.inner[1][0].yx.x);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.msl
new file mode 100644
index 0000000..4119424
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.msl
@@ -0,0 +1,36 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+void a(tint_array<float4x2, 4> a_1) {
+}
+
+void b(float4x2 m) {
+}
+
+void c(float2 v) {
+}
+
+void d(float f_1) {
+}
+
+kernel void f(const constant tint_array<float4x2, 4>* tint_symbol [[buffer(0)]]) {
+  a(*(tint_symbol));
+  b((*(tint_symbol))[1]);
+  c(float2((*(tint_symbol))[1][0]).yx);
+  d(float2((*(tint_symbol))[1][0]).yx[0]);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.spvasm
new file mode 100644
index 0000000..8ee216d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.spvasm
@@ -0,0 +1,90 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 52
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %u "u"
+               OpName %a "a"
+               OpName %a_1 "a_1"
+               OpName %b "b"
+               OpName %m "m"
+               OpName %c "c"
+               OpName %v "v"
+               OpName %d "d"
+               OpName %f_1 "f_1"
+               OpName %f "f"
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %_arr_mat4v2float_uint_4 ArrayStride 32
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat4v2float = OpTypeMatrix %v2float 4
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat4v2float_uint_4 = OpTypeArray %mat4v2float %uint_4
+    %u_block = OpTypeStruct %_arr_mat4v2float_uint_4
+%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
+          %u = OpVariable %_ptr_Uniform_u_block Uniform
+       %void = OpTypeVoid
+         %10 = OpTypeFunction %void %_arr_mat4v2float_uint_4
+         %15 = OpTypeFunction %void %mat4v2float
+         %19 = OpTypeFunction %void %v2float
+         %23 = OpTypeFunction %void %float
+         %27 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform__arr_mat4v2float_uint_4 = OpTypePointer Uniform %_arr_mat4v2float_uint_4
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_mat4v2float = OpTypePointer Uniform %mat4v2float
+         %42 = OpConstantNull %int
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+          %a = OpFunction %void None %10
+        %a_1 = OpFunctionParameter %_arr_mat4v2float_uint_4
+         %14 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %b = OpFunction %void None %15
+          %m = OpFunctionParameter %mat4v2float
+         %18 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %c = OpFunction %void None %19
+          %v = OpFunctionParameter %v2float
+         %22 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %d = OpFunction %void None %23
+        %f_1 = OpFunctionParameter %float
+         %26 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %27
+         %29 = OpLabel
+         %33 = OpAccessChain %_ptr_Uniform__arr_mat4v2float_uint_4 %u %uint_0
+         %34 = OpLoad %_arr_mat4v2float_uint_4 %33
+         %30 = OpFunctionCall %void %a %34
+         %39 = OpAccessChain %_ptr_Uniform_mat4v2float %u %uint_0 %int_1
+         %40 = OpLoad %mat4v2float %39
+         %35 = OpFunctionCall %void %b %40
+         %44 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %int_1 %42
+         %45 = OpLoad %v2float %44
+         %46 = OpVectorShuffle %v2float %45 %45 1 0
+         %41 = OpFunctionCall %void %c %46
+         %48 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %int_1 %42
+         %49 = OpLoad %v2float %48
+         %50 = OpVectorShuffle %v2float %49 %49 1 0
+         %51 = OpCompositeExtract %float %50 0
+         %47 = OpFunctionCall %void %d %51
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.wgsl
new file mode 100644
index 0000000..dfed713
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_fn.wgsl.expected.wgsl
@@ -0,0 +1,21 @@
+@group(0) @binding(0) var<uniform> u : array<mat4x2<f32>, 4>;
+
+fn a(a : array<mat4x2<f32>, 4>) {
+}
+
+fn b(m : mat4x2<f32>) {
+}
+
+fn c(v : vec2<f32>) {
+}
+
+fn d(f : f32) {
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  a(u);
+  b(u[1]);
+  c(u[1][0].yx);
+  d(u[1][0].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl
new file mode 100644
index 0000000..618416a
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl
@@ -0,0 +1,16 @@
+struct S {
+  before : i32,
+  m : mat4x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat4x2<f32>, 4>;
+var<private> p : array<mat4x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+    p = u;
+    p[1] = u[2];
+    p[1][0] = u[0][1].yx;
+    p[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..1be04d4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.dxc.hlsl
@@ -0,0 +1,36 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[8];
+};
+static float4x2 p[4] = (float4x2[4])0;
+
+float4x2 tint_symbol_1(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 32u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  p = tint_symbol(u, 0u);
+  p[1] = tint_symbol_1(u, 64u);
+  p[1][0] = asfloat(u[0].zw).yx;
+  p[1][0].x = asfloat(u[0].z);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..1be04d4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.fxc.hlsl
@@ -0,0 +1,36 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[8];
+};
+static float4x2 p[4] = (float4x2[4])0;
+
+float4x2 tint_symbol_1(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_ret[4];
+tint_symbol_ret tint_symbol(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = tint_symbol_1(buffer, (offset + (i * 32u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  p = tint_symbol(u, 0u);
+  p[1] = tint_symbol_1(u, 64u);
+  p[1][0] = asfloat(u[0].zw).yx;
+  p[1][0].x = asfloat(u[0].z);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.glsl
new file mode 100644
index 0000000..0b73e75
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.glsl
@@ -0,0 +1,25 @@
+#version 310 es
+
+struct S {
+  int before;
+  mat4x2 m;
+  int after;
+};
+
+layout(binding = 0, std140) uniform u_block_ubo {
+  mat4x2 inner[4];
+} u;
+
+mat4x2 p[4] = mat4x2[4](mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+void f() {
+  p = u.inner;
+  p[1] = u.inner[2];
+  p[1][0] = u.inner[0][1].yx;
+  p[1][0].x = u.inner[0][1].x;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.msl
new file mode 100644
index 0000000..cd97f91
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.msl
@@ -0,0 +1,31 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct S {
+  int before;
+  float4x2 m;
+  int after;
+};
+
+kernel void f(const constant tint_array<float4x2, 4>* tint_symbol_1 [[buffer(0)]]) {
+  thread tint_array<float4x2, 4> tint_symbol = {};
+  tint_symbol = *(tint_symbol_1);
+  tint_symbol[1] = (*(tint_symbol_1))[2];
+  tint_symbol[1][0] = float2((*(tint_symbol_1))[0][1]).yx;
+  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.spvasm
new file mode 100644
index 0000000..41ac892
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.spvasm
@@ -0,0 +1,68 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 41
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %u "u"
+               OpName %p "p"
+               OpName %f "f"
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %_arr_mat4v2float_uint_4 ArrayStride 32
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat4v2float = OpTypeMatrix %v2float 4
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat4v2float_uint_4 = OpTypeArray %mat4v2float %uint_4
+    %u_block = OpTypeStruct %_arr_mat4v2float_uint_4
+%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
+          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%_ptr_Private__arr_mat4v2float_uint_4 = OpTypePointer Private %_arr_mat4v2float_uint_4
+         %12 = OpConstantNull %_arr_mat4v2float_uint_4
+          %p = OpVariable %_ptr_Private__arr_mat4v2float_uint_4 Private %12
+       %void = OpTypeVoid
+         %13 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform__arr_mat4v2float_uint_4 = OpTypePointer Uniform %_arr_mat4v2float_uint_4
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_Private_mat4v2float = OpTypePointer Private %mat4v2float
+      %int_2 = OpConstant %int 2
+%_ptr_Uniform_mat4v2float = OpTypePointer Uniform %mat4v2float
+         %29 = OpConstantNull %int
+%_ptr_Private_v2float = OpTypePointer Private %v2float
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%_ptr_Private_float = OpTypePointer Private %float
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+          %f = OpFunction %void None %13
+         %16 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform__arr_mat4v2float_uint_4 %u %uint_0
+         %20 = OpLoad %_arr_mat4v2float_uint_4 %19
+               OpStore %p %20
+         %24 = OpAccessChain %_ptr_Private_mat4v2float %p %int_1
+         %27 = OpAccessChain %_ptr_Uniform_mat4v2float %u %uint_0 %int_2
+         %28 = OpLoad %mat4v2float %27
+               OpStore %24 %28
+         %31 = OpAccessChain %_ptr_Private_v2float %p %int_1 %29
+         %33 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %29 %int_1
+         %34 = OpLoad %v2float %33
+         %35 = OpVectorShuffle %v2float %34 %34 1 0
+               OpStore %31 %35
+         %37 = OpAccessChain %_ptr_Private_float %p %int_1 %29 %uint_0
+         %39 = OpAccessChain %_ptr_Uniform_float %u %uint_0 %29 %int_1 %uint_0
+         %40 = OpLoad %float %39
+               OpStore %37 %40
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.wgsl
new file mode 100644
index 0000000..04780dc
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_private.wgsl.expected.wgsl
@@ -0,0 +1,17 @@
+struct S {
+  before : i32,
+  m : mat4x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat4x2<f32>, 4>;
+
+var<private> p : array<mat4x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  p = u;
+  p[1] = u[2];
+  p[1][0] = u[0][1].yx;
+  p[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl
new file mode 100644
index 0000000..fcea4e7
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl
@@ -0,0 +1,16 @@
+struct S {
+  before : i32,
+  m : mat4x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat4x2<f32>, 4>;
+@group(0) @binding(1) var<storage, read_write> s : array<mat4x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+    s = u;
+    s[1] = u[2];
+    s[1][0] = u[0][1].yx;
+    s[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..bd2c38b
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.dxc.hlsl
@@ -0,0 +1,52 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[8];
+};
+RWByteAddressBuffer s : register(u1, space0);
+
+void tint_symbol_1(RWByteAddressBuffer buffer, uint offset, float4x2 value) {
+  buffer.Store2((offset + 0u), asuint(value[0u]));
+  buffer.Store2((offset + 8u), asuint(value[1u]));
+  buffer.Store2((offset + 16u), asuint(value[2u]));
+  buffer.Store2((offset + 24u), asuint(value[3u]));
+}
+
+void tint_symbol(RWByteAddressBuffer buffer, uint offset, float4x2 value[4]) {
+  float4x2 array[4] = value;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      tint_symbol_1(buffer, (offset + (i * 32u)), array[i]);
+    }
+  }
+}
+
+float4x2 tint_symbol_4(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_3_ret[4];
+tint_symbol_3_ret tint_symbol_3(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_4(buffer, (offset + (i_1 * 32u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  tint_symbol(s, 0u, tint_symbol_3(u, 0u));
+  tint_symbol_1(s, 32u, tint_symbol_4(u, 64u));
+  s.Store2(32u, asuint(asfloat(u[0].zw).yx));
+  s.Store(32u, asuint(asfloat(u[0].z)));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..bd2c38b
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.fxc.hlsl
@@ -0,0 +1,52 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[8];
+};
+RWByteAddressBuffer s : register(u1, space0);
+
+void tint_symbol_1(RWByteAddressBuffer buffer, uint offset, float4x2 value) {
+  buffer.Store2((offset + 0u), asuint(value[0u]));
+  buffer.Store2((offset + 8u), asuint(value[1u]));
+  buffer.Store2((offset + 16u), asuint(value[2u]));
+  buffer.Store2((offset + 24u), asuint(value[3u]));
+}
+
+void tint_symbol(RWByteAddressBuffer buffer, uint offset, float4x2 value[4]) {
+  float4x2 array[4] = value;
+  {
+    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      tint_symbol_1(buffer, (offset + (i * 32u)), array[i]);
+    }
+  }
+}
+
+float4x2 tint_symbol_4(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_3_ret[4];
+tint_symbol_3_ret tint_symbol_3(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_4(buffer, (offset + (i_1 * 32u)));
+    }
+  }
+  return arr;
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  tint_symbol(s, 0u, tint_symbol_3(u, 0u));
+  tint_symbol_1(s, 32u, tint_symbol_4(u, 64u));
+  s.Store2(32u, asuint(asfloat(u[0].zw).yx));
+  s.Store(32u, asuint(asfloat(u[0].z)));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.glsl
new file mode 100644
index 0000000..7eb1bf5
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.glsl
@@ -0,0 +1,28 @@
+#version 310 es
+
+struct S {
+  int before;
+  mat4x2 m;
+  int after;
+};
+
+layout(binding = 0, std140) uniform u_block_ubo {
+  mat4x2 inner[4];
+} u;
+
+layout(binding = 1, std430) buffer u_block_ssbo {
+  mat4x2 inner[4];
+} s;
+
+void f() {
+  s.inner = u.inner;
+  s.inner[1] = u.inner[2];
+  s.inner[1][0] = u.inner[0][1].yx;
+  s.inner[1][0].x = u.inner[0][1].x;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.msl
new file mode 100644
index 0000000..abded74
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.msl
@@ -0,0 +1,30 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct S {
+  int before;
+  float4x2 m;
+  int after;
+};
+
+kernel void f(device tint_array<float4x2, 4>* tint_symbol [[buffer(1)]], const constant tint_array<float4x2, 4>* tint_symbol_1 [[buffer(0)]]) {
+  *(tint_symbol) = *(tint_symbol_1);
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
+  (*(tint_symbol))[1][0] = float2((*(tint_symbol_1))[0][1]).yx;
+  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.spvasm
new file mode 100644
index 0000000..f922154
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 42
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %u "u"
+               OpName %s "s"
+               OpName %f "f"
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %_arr_mat4v2float_uint_4 ArrayStride 32
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+               OpDecorate %s DescriptorSet 0
+               OpDecorate %s Binding 1
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat4v2float = OpTypeMatrix %v2float 4
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_mat4v2float_uint_4 = OpTypeArray %mat4v2float %uint_4
+    %u_block = OpTypeStruct %_arr_mat4v2float_uint_4
+%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
+          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%_ptr_StorageBuffer_u_block = OpTypePointer StorageBuffer %u_block
+          %s = OpVariable %_ptr_StorageBuffer_u_block StorageBuffer
+       %void = OpTypeVoid
+         %12 = OpTypeFunction %void
+     %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer__arr_mat4v2float_uint_4 = OpTypePointer StorageBuffer %_arr_mat4v2float_uint_4
+%_ptr_Uniform__arr_mat4v2float_uint_4 = OpTypePointer Uniform %_arr_mat4v2float_uint_4
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_StorageBuffer_mat4v2float = OpTypePointer StorageBuffer %mat4v2float
+      %int_2 = OpConstant %int 2
+%_ptr_Uniform_mat4v2float = OpTypePointer Uniform %mat4v2float
+         %30 = OpConstantNull %int
+%_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+          %f = OpFunction %void None %12
+         %15 = OpLabel
+         %18 = OpAccessChain %_ptr_StorageBuffer__arr_mat4v2float_uint_4 %s %uint_0
+         %20 = OpAccessChain %_ptr_Uniform__arr_mat4v2float_uint_4 %u %uint_0
+         %21 = OpLoad %_arr_mat4v2float_uint_4 %20
+               OpStore %18 %21
+         %25 = OpAccessChain %_ptr_StorageBuffer_mat4v2float %s %uint_0 %int_1
+         %28 = OpAccessChain %_ptr_Uniform_mat4v2float %u %uint_0 %int_2
+         %29 = OpLoad %mat4v2float %28
+               OpStore %25 %29
+         %32 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1 %30
+         %34 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %30 %int_1
+         %35 = OpLoad %v2float %34
+         %36 = OpVectorShuffle %v2float %35 %35 1 0
+               OpStore %32 %36
+         %38 = OpAccessChain %_ptr_StorageBuffer_float %s %uint_0 %int_1 %30 %uint_0
+         %40 = OpAccessChain %_ptr_Uniform_float %u %uint_0 %30 %int_1 %uint_0
+         %41 = OpLoad %float %40
+               OpStore %38 %41
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.wgsl
new file mode 100644
index 0000000..d32f228
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_storage.wgsl.expected.wgsl
@@ -0,0 +1,17 @@
+struct S {
+  before : i32,
+  m : mat4x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat4x2<f32>, 4>;
+
+@group(0) @binding(1) var<storage, read_write> s : array<mat4x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  s = u;
+  s[1] = u[2];
+  s[1][0] = u[0][1].yx;
+  s[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl
new file mode 100644
index 0000000..b1368c8
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl
@@ -0,0 +1,16 @@
+struct S {
+  before : i32,
+  m : mat4x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat4x2<f32>, 4>;
+var<workgroup> w : array<mat4x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+    w = u;
+    w[1] = u[2];
+    w[1][0] = u[0][1].yx;
+    w[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..047cd82
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.dxc.hlsl
@@ -0,0 +1,51 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[8];
+};
+groupshared float4x2 w[4];
+
+struct tint_symbol_1 {
+  uint local_invocation_index : SV_GroupIndex;
+};
+
+float4x2 tint_symbol_3(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_2_ret[4];
+tint_symbol_2_ret tint_symbol_2(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_3(buffer, (offset + (i_1 * 32u)));
+    }
+  }
+  return arr;
+}
+
+void f_inner(uint local_invocation_index) {
+  {
+    [loop] for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+      const uint i = idx;
+      w[i] = float4x2((0.0f).xx, (0.0f).xx, (0.0f).xx, (0.0f).xx);
+    }
+  }
+  GroupMemoryBarrierWithGroupSync();
+  w = tint_symbol_2(u, 0u);
+  w[1] = tint_symbol_3(u, 64u);
+  w[1][0] = asfloat(u[0].zw).yx;
+  w[1][0].x = asfloat(u[0].z);
+}
+
+[numthreads(1, 1, 1)]
+void f(tint_symbol_1 tint_symbol) {
+  f_inner(tint_symbol.local_invocation_index);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..047cd82
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.fxc.hlsl
@@ -0,0 +1,51 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[8];
+};
+groupshared float4x2 w[4];
+
+struct tint_symbol_1 {
+  uint local_invocation_index : SV_GroupIndex;
+};
+
+float4x2 tint_symbol_3(uint4 buffer[8], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+typedef float4x2 tint_symbol_2_ret[4];
+tint_symbol_2_ret tint_symbol_2(uint4 buffer[8], uint offset) {
+  float4x2 arr[4] = (float4x2[4])0;
+  {
+    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
+      arr[i_1] = tint_symbol_3(buffer, (offset + (i_1 * 32u)));
+    }
+  }
+  return arr;
+}
+
+void f_inner(uint local_invocation_index) {
+  {
+    [loop] for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+      const uint i = idx;
+      w[i] = float4x2((0.0f).xx, (0.0f).xx, (0.0f).xx, (0.0f).xx);
+    }
+  }
+  GroupMemoryBarrierWithGroupSync();
+  w = tint_symbol_2(u, 0u);
+  w[1] = tint_symbol_3(u, 64u);
+  w[1][0] = asfloat(u[0].zw).yx;
+  w[1][0].x = asfloat(u[0].z);
+}
+
+[numthreads(1, 1, 1)]
+void f(tint_symbol_1 tint_symbol) {
+  f_inner(tint_symbol.local_invocation_index);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.glsl
new file mode 100644
index 0000000..6ca89c7
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.glsl
@@ -0,0 +1,32 @@
+#version 310 es
+
+struct S {
+  int before;
+  mat4x2 m;
+  int after;
+};
+
+layout(binding = 0, std140) uniform u_block_ubo {
+  mat4x2 inner[4];
+} u;
+
+shared mat4x2 w[4];
+void f(uint local_invocation_index) {
+  {
+    for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+      uint i = idx;
+      w[i] = mat4x2(vec2(0.0f), vec2(0.0f), vec2(0.0f), vec2(0.0f));
+    }
+  }
+  barrier();
+  w = u.inner;
+  w[1] = u.inner[2];
+  w[1][0] = u.inner[0][1].yx;
+  w[1][0].x = u.inner[0][1].x;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f(gl_LocalInvocationIndex);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.msl
new file mode 100644
index 0000000..e4001f3
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.msl
@@ -0,0 +1,44 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct tint_symbol_5 {
+  tint_array<float4x2, 4> w;
+};
+
+struct S {
+  int before;
+  float4x2 m;
+  int after;
+};
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<float4x2, 4>* const tint_symbol, const constant tint_array<float4x2, 4>* const tint_symbol_1) {
+  for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+    uint const i = idx;
+    (*(tint_symbol))[i] = float4x2(float2(0.0f), float2(0.0f), float2(0.0f), float2(0.0f));
+  }
+  threadgroup_barrier(mem_flags::mem_threadgroup);
+  *(tint_symbol) = *(tint_symbol_1);
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
+  (*(tint_symbol))[1][0] = float2((*(tint_symbol_1))[0][1]).yx;
+  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+}
+
+kernel void f(const constant tint_array<float4x2, 4>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+  threadgroup tint_array<float4x2, 4>* const tint_symbol_2 = &((*(tint_symbol_3)).w);
+  f_inner(local_invocation_index, tint_symbol_2, tint_symbol_4);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.spvasm
new file mode 100644
index 0000000..d38bf92
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.spvasm
@@ -0,0 +1,115 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 70
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f" %local_invocation_index_1
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %local_invocation_index_1 "local_invocation_index_1"
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %u "u"
+               OpName %w "w"
+               OpName %f_inner "f_inner"
+               OpName %local_invocation_index "local_invocation_index"
+               OpName %idx "idx"
+               OpName %f "f"
+               OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %_arr_mat4v2float_uint_4 ArrayStride 32
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+       %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat4v2float = OpTypeMatrix %v2float 4
+     %uint_4 = OpConstant %uint 4
+%_arr_mat4v2float_uint_4 = OpTypeArray %mat4v2float %uint_4
+    %u_block = OpTypeStruct %_arr_mat4v2float_uint_4
+%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
+          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%_ptr_Workgroup__arr_mat4v2float_uint_4 = OpTypePointer Workgroup %_arr_mat4v2float_uint_4
+          %w = OpVariable %_ptr_Workgroup__arr_mat4v2float_uint_4 Workgroup
+       %void = OpTypeVoid
+         %14 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+         %21 = OpConstantNull %uint
+       %bool = OpTypeBool
+%_ptr_Workgroup_mat4v2float = OpTypePointer Workgroup %mat4v2float
+         %35 = OpConstantNull %mat4v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+   %uint_264 = OpConstant %uint 264
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform__arr_mat4v2float_uint_4 = OpTypePointer Uniform %_arr_mat4v2float_uint_4
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+      %int_2 = OpConstant %int 2
+%_ptr_Uniform_mat4v2float = OpTypePointer Uniform %mat4v2float
+         %53 = OpConstantNull %int
+%_ptr_Workgroup_v2float = OpTypePointer Workgroup %v2float
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%_ptr_Workgroup_float = OpTypePointer Workgroup %float
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+         %65 = OpTypeFunction %void
+    %f_inner = OpFunction %void None %14
+%local_invocation_index = OpFunctionParameter %uint
+         %18 = OpLabel
+        %idx = OpVariable %_ptr_Function_uint Function %21
+               OpStore %idx %local_invocation_index
+               OpBranch %22
+         %22 = OpLabel
+               OpLoopMerge %23 %24 None
+               OpBranch %25
+         %25 = OpLabel
+         %27 = OpLoad %uint %idx
+         %28 = OpULessThan %bool %27 %uint_4
+         %26 = OpLogicalNot %bool %28
+               OpSelectionMerge %30 None
+               OpBranchConditional %26 %31 %30
+         %31 = OpLabel
+               OpBranch %23
+         %30 = OpLabel
+         %32 = OpLoad %uint %idx
+         %34 = OpAccessChain %_ptr_Workgroup_mat4v2float %w %32
+               OpStore %34 %35
+               OpBranch %24
+         %24 = OpLabel
+         %36 = OpLoad %uint %idx
+         %38 = OpIAdd %uint %36 %uint_1
+               OpStore %idx %38
+               OpBranch %22
+         %23 = OpLabel
+               OpControlBarrier %uint_2 %uint_2 %uint_264
+         %44 = OpAccessChain %_ptr_Uniform__arr_mat4v2float_uint_4 %u %uint_0
+         %45 = OpLoad %_arr_mat4v2float_uint_4 %44
+               OpStore %w %45
+         %48 = OpAccessChain %_ptr_Workgroup_mat4v2float %w %int_1
+         %51 = OpAccessChain %_ptr_Uniform_mat4v2float %u %uint_0 %int_2
+         %52 = OpLoad %mat4v2float %51
+               OpStore %48 %52
+         %55 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1 %53
+         %57 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %53 %int_1
+         %58 = OpLoad %v2float %57
+         %59 = OpVectorShuffle %v2float %58 %58 1 0
+               OpStore %55 %59
+         %61 = OpAccessChain %_ptr_Workgroup_float %w %int_1 %53 %uint_0
+         %63 = OpAccessChain %_ptr_Uniform_float %u %uint_0 %53 %int_1 %uint_0
+         %64 = OpLoad %float %63
+               OpStore %61 %64
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %65
+         %67 = OpLabel
+         %69 = OpLoad %uint %local_invocation_index_1
+         %68 = OpFunctionCall %void %f_inner %69
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.wgsl
new file mode 100644
index 0000000..9948855
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/array/mat4x2/to_workgroup.wgsl.expected.wgsl
@@ -0,0 +1,17 @@
+struct S {
+  before : i32,
+  m : mat4x2<f32>,
+  after : i32,
+}
+
+@group(0) @binding(0) var<uniform> u : array<mat4x2<f32>, 4>;
+
+var<workgroup> w : array<mat4x2<f32>, 4>;
+
+@compute @workgroup_size(1)
+fn f() {
+  w = u;
+  w[1] = u[2];
+  w[1][0] = u[0][1].yx;
+  w[1][0].x = u[0][1].x;
+}
diff --git a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
deleted file mode 100644
index d27e6df..0000000
--- a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
+++ /dev/null
@@ -1,63 +0,0 @@
-struct Inner {
-  float2x2 m;
-};
-struct Outer {
-  Inner a[4];
-};
-
-cbuffer cbuffer_a : register(b0, space0) {
-  uint4 a[16];
-};
-
-float2x2 tint_symbol_4(uint4 buffer[16], uint offset) {
-  const uint scalar_offset = ((offset + 0u)) / 4;
-  uint4 ubo_load = buffer[scalar_offset / 4];
-  const uint scalar_offset_1 = ((offset + 8u)) / 4;
-  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
-  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
-}
-
-Inner tint_symbol_3(uint4 buffer[16], uint offset) {
-  const Inner tint_symbol_7 = {tint_symbol_4(buffer, (offset + 0u))};
-  return tint_symbol_7;
-}
-
-typedef Inner tint_symbol_2_ret[4];
-tint_symbol_2_ret tint_symbol_2(uint4 buffer[16], uint offset) {
-  Inner arr[4] = (Inner[4])0;
-  {
-    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = tint_symbol_3(buffer, (offset + (i * 16u)));
-    }
-  }
-  return arr;
-}
-
-Outer tint_symbol_1(uint4 buffer[16], uint offset) {
-  const Outer tint_symbol_8 = {tint_symbol_2(buffer, (offset + 0u))};
-  return tint_symbol_8;
-}
-
-typedef Outer tint_symbol_ret[4];
-tint_symbol_ret tint_symbol(uint4 buffer[16], uint offset) {
-  Outer arr_1[4] = (Outer[4])0;
-  {
-    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
-      arr_1[i_1] = tint_symbol_1(buffer, (offset + (i_1 * 64u)));
-    }
-  }
-  return arr_1;
-}
-
-[numthreads(1, 1, 1)]
-void f() {
-  const int I = 1;
-  const Outer l_a[4] = tint_symbol(a, 0u);
-  const Outer l_a_3 = tint_symbol_1(a, 192u);
-  const Inner l_a_3_a[4] = tint_symbol_2(a, 192u);
-  const Inner l_a_3_a_2 = tint_symbol_3(a, 224u);
-  const float2x2 l_a_3_a_2_m = tint_symbol_4(a, 224u);
-  const float2 l_a_3_a_2_m_1 = asfloat(a[14].zw);
-  const float l_a_3_a_2_m_1_0 = asfloat(a[14].z);
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.spvasm
deleted file mode 100644
index 641ded1..0000000
--- a/test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.spvasm
+++ /dev/null
@@ -1,73 +0,0 @@
-; SPIR-V
-; Version: 1.3
-; Generator: Google Tint Compiler; 0
-; Bound: 41
-; Schema: 0
-               OpCapability Shader
-         %31 = OpExtInstImport "GLSL.std.450"
-               OpMemoryModel Logical GLSL450
-               OpEntryPoint GLCompute %f "f"
-               OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
-               OpName %S_std140 "S_std140"
-               OpMemberName %S_std140 0 "before"
-               OpMemberName %S_std140 1 "m_0"
-               OpMemberName %S_std140 2 "m_1"
-               OpMemberName %S_std140 3 "after"
-               OpName %u "u"
-               OpName %load_u_2_m "load_u_2_m"
-               OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
-               OpMemberDecorate %S_std140 0 Offset 0
-               OpMemberDecorate %S_std140 1 Offset 8
-               OpMemberDecorate %S_std140 2 Offset 16
-               OpMemberDecorate %S_std140 3 Offset 24
-               OpDecorate %_arr_S_std140_uint_4 ArrayStride 32
-               OpDecorate %u NonWritable
-               OpDecorate %u DescriptorSet 0
-               OpDecorate %u Binding 0
-        %int = OpTypeInt 32 1
-      %float = OpTypeFloat 32
-    %v2float = OpTypeVector %float 2
-   %S_std140 = OpTypeStruct %int %v2float %v2float %int
-       %uint = OpTypeInt 32 0
-     %uint_4 = OpConstant %uint 4
-%_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
-%mat2v2float = OpTypeMatrix %v2float 2
-         %11 = OpTypeFunction %mat2v2float
-     %uint_0 = OpConstant %uint 0
-     %uint_2 = OpConstant %uint 2
-     %uint_1 = OpConstant %uint 1
-%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
-       %void = OpTypeVoid
-         %24 = OpTypeFunction %void
-         %32 = OpConstantNull %uint
- %load_u_2_m = OpFunction %mat2v2float None %11
-         %14 = OpLabel
-         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %20 = OpLoad %v2float %19
-         %21 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %22 = OpLoad %v2float %21
-         %23 = OpCompositeConstruct %mat2v2float %20 %22
-               OpReturnValue %23
-               OpFunctionEnd
-          %f = OpFunction %void None %24
-         %27 = OpLabel
-         %29 = OpFunctionCall %mat2v2float %load_u_2_m
-         %28 = OpTranspose %mat2v2float %29
-         %33 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %32 %uint_2
-         %34 = OpLoad %v2float %33
-         %35 = OpVectorShuffle %v2float %34 %34 1 0
-         %30 = OpExtInst %float %31 Length %35
-         %37 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %32 %uint_2
-         %38 = OpLoad %v2float %37
-         %39 = OpVectorShuffle %v2float %38 %38 1 0
-         %40 = OpCompositeExtract %float %39 0
-         %36 = OpExtInst %float %31 FAbs %40
-               OpReturn
-               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.glsl
deleted file mode 100644
index f21f59b..0000000
--- a/test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.glsl
+++ /dev/null
@@ -1,53 +0,0 @@
-#version 310 es
-
-struct S {
-  int before;
-  mat2 m;
-  int after;
-};
-
-struct S_std140 {
-  int before;
-  uint pad;
-  vec2 m_0;
-  vec2 m_1;
-  int after;
-  uint pad_1;
-};
-
-layout(binding = 0, std140) uniform u_block_ubo {
-  S_std140 inner[4];
-} u;
-
-S p[4] = S[4](S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0));
-S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, mat2(val.m_0, val.m_1), val.after);
-  return tint_symbol;
-}
-
-S[4] conv_arr_4_S(S_std140 val[4]) {
-  S arr[4] = S[4](S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_S(val[i]);
-    }
-  }
-  return arr;
-}
-
-mat2 load_u_2_m() {
-  return mat2(u.inner[2u].m_0, u.inner[2u].m_1);
-}
-
-void f() {
-  p = conv_arr_4_S(u.inner);
-  p[1] = conv_S(u.inner[2u]);
-  p[3].m = load_u_2_m();
-  p[1].m[0] = u.inner[0u].m_1.yx;
-}
-
-layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
-void main() {
-  f();
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.glsl
deleted file mode 100644
index c85ce1a..0000000
--- a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.glsl
+++ /dev/null
@@ -1,144 +0,0 @@
-#version 310 es
-
-struct Inner {
-  mat3x2 m;
-};
-
-struct Inner_std140 {
-  vec2 m_0;
-  vec2 m_1;
-  vec2 m_2;
-  uint pad;
-  uint pad_1;
-  uint pad_2;
-  uint pad_3;
-  uint pad_4;
-  uint pad_5;
-  uint pad_6;
-  uint pad_7;
-  uint pad_8;
-  uint pad_9;
-};
-
-struct Outer {
-  Inner a[4];
-};
-
-struct Outer_std140 {
-  Inner_std140 a[4];
-};
-
-layout(binding = 0, std140) uniform a_block_ubo {
-  Outer_std140 inner[4];
-} a;
-
-int counter = 0;
-int i() {
-  counter = (counter + 1);
-  return counter;
-}
-
-Inner conv_Inner(Inner_std140 val) {
-  Inner tint_symbol_4 = Inner(mat3x2(val.m_0, val.m_1, val.m_2));
-  return tint_symbol_4;
-}
-
-Inner[4] conv_arr_4_Inner(Inner_std140 val[4]) {
-  Inner arr[4] = Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_Inner(val[i]);
-    }
-  }
-  return arr;
-}
-
-Outer conv_Outer(Outer_std140 val) {
-  Outer tint_symbol_5 = Outer(conv_arr_4_Inner(val.a));
-  return tint_symbol_5;
-}
-
-Outer[4] conv_arr_4_Outer(Outer_std140 val[4]) {
-  Outer arr[4] = Outer[4](Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)))));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_Outer(val[i]);
-    }
-  }
-  return arr;
-}
-
-mat3x2 load_a_p0_a_p1_m(uint p0, uint p1) {
-  uint s_save = p0;
-  uint s_save_1 = p1;
-  return mat3x2(a.inner[s_save].a[s_save_1].m_0, a.inner[s_save].a[s_save_1].m_1, a.inner[s_save].a[s_save_1].m_2);
-}
-
-vec2 load_a_p0_a_p1_m_p2(uint p0, uint p1, uint p2) {
-  switch(p2) {
-    case 0u: {
-      return a.inner[p0].a[p1].m_0;
-      break;
-    }
-    case 1u: {
-      return a.inner[p0].a[p1].m_1;
-      break;
-    }
-    case 2u: {
-      return a.inner[p0].a[p1].m_2;
-      break;
-    }
-    default: {
-      return vec2(0.0f);
-      break;
-    }
-  }
-}
-
-float load_a_p0_a_p1_m_p2_p3(uint p0, uint p1, uint p2, uint p3) {
-  switch(p2) {
-    case 0u: {
-      return a.inner[p0].a[p1].m_0[p3];
-      break;
-    }
-    case 1u: {
-      return a.inner[p0].a[p1].m_1[p3];
-      break;
-    }
-    case 2u: {
-      return a.inner[p0].a[p1].m_2[p3];
-      break;
-    }
-    default: {
-      return 0.0f;
-      break;
-    }
-  }
-}
-
-void f() {
-  int I = 1;
-  Outer p_a[4] = conv_arr_4_Outer(a.inner);
-  int tint_symbol = i();
-  Outer p_a_i = conv_Outer(a.inner[tint_symbol]);
-  Inner p_a_i_a[4] = conv_arr_4_Inner(a.inner[tint_symbol].a);
-  int tint_symbol_1 = i();
-  Inner p_a_i_a_i = conv_Inner(a.inner[tint_symbol].a[tint_symbol_1]);
-  mat3x2 p_a_i_a_i_m = load_a_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
-  int tint_symbol_2 = i();
-  vec2 p_a_i_a_i_m_i = load_a_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
-  Outer l_a[4] = conv_arr_4_Outer(a.inner);
-  Outer l_a_i = conv_Outer(a.inner[tint_symbol]);
-  Inner l_a_i_a[4] = conv_arr_4_Inner(a.inner[tint_symbol].a);
-  Inner l_a_i_a_i = conv_Inner(a.inner[tint_symbol].a[tint_symbol_1]);
-  mat3x2 l_a_i_a_i_m = load_a_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
-  vec2 l_a_i_a_i_m_i = load_a_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
-  int tint_symbol_3 = i();
-  float l_a_i_a_i_m_i_i = load_a_p0_a_p1_m_p2_p3(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2), uint(tint_symbol_3));
-}
-
-layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
-void main() {
-  f();
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
deleted file mode 100644
index 5c62062..0000000
--- a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
+++ /dev/null
@@ -1,65 +0,0 @@
-struct Inner {
-  float3x2 m;
-};
-struct Outer {
-  Inner a[4];
-};
-
-cbuffer cbuffer_a : register(b0, space0) {
-  uint4 a[64];
-};
-
-float3x2 tint_symbol_4(uint4 buffer[64], uint offset) {
-  const uint scalar_offset = ((offset + 0u)) / 4;
-  uint4 ubo_load = buffer[scalar_offset / 4];
-  const uint scalar_offset_1 = ((offset + 8u)) / 4;
-  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
-  const uint scalar_offset_2 = ((offset + 16u)) / 4;
-  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
-  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
-}
-
-Inner tint_symbol_3(uint4 buffer[64], uint offset) {
-  const Inner tint_symbol_7 = {tint_symbol_4(buffer, (offset + 0u))};
-  return tint_symbol_7;
-}
-
-typedef Inner tint_symbol_2_ret[4];
-tint_symbol_2_ret tint_symbol_2(uint4 buffer[64], uint offset) {
-  Inner arr[4] = (Inner[4])0;
-  {
-    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = tint_symbol_3(buffer, (offset + (i * 64u)));
-    }
-  }
-  return arr;
-}
-
-Outer tint_symbol_1(uint4 buffer[64], uint offset) {
-  const Outer tint_symbol_8 = {tint_symbol_2(buffer, (offset + 0u))};
-  return tint_symbol_8;
-}
-
-typedef Outer tint_symbol_ret[4];
-tint_symbol_ret tint_symbol(uint4 buffer[64], uint offset) {
-  Outer arr_1[4] = (Outer[4])0;
-  {
-    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
-      arr_1[i_1] = tint_symbol_1(buffer, (offset + (i_1 * 256u)));
-    }
-  }
-  return arr_1;
-}
-
-[numthreads(1, 1, 1)]
-void f() {
-  const int I = 1;
-  const Outer l_a[4] = tint_symbol(a, 0u);
-  const Outer l_a_3 = tint_symbol_1(a, 768u);
-  const Inner l_a_3_a[4] = tint_symbol_2(a, 768u);
-  const Inner l_a_3_a_2 = tint_symbol_3(a, 896u);
-  const float3x2 l_a_3_a_2_m = tint_symbol_4(a, 896u);
-  const float2 l_a_3_a_2_m_1 = asfloat(a[56].zw);
-  const float l_a_3_a_2_m_1_0 = asfloat(a[56].z);
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.glsl
deleted file mode 100644
index 85ff444..0000000
--- a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.glsl
+++ /dev/null
@@ -1,90 +0,0 @@
-#version 310 es
-
-struct Inner {
-  mat3x2 m;
-};
-
-struct Inner_std140 {
-  vec2 m_0;
-  vec2 m_1;
-  vec2 m_2;
-  uint pad;
-  uint pad_1;
-  uint pad_2;
-  uint pad_3;
-  uint pad_4;
-  uint pad_5;
-  uint pad_6;
-  uint pad_7;
-  uint pad_8;
-  uint pad_9;
-};
-
-struct Outer {
-  Inner a[4];
-};
-
-struct Outer_std140 {
-  Inner_std140 a[4];
-};
-
-layout(binding = 0, std140) uniform a_block_ubo {
-  Outer_std140 inner[4];
-} a;
-
-Inner conv_Inner(Inner_std140 val) {
-  Inner tint_symbol = Inner(mat3x2(val.m_0, val.m_1, val.m_2));
-  return tint_symbol;
-}
-
-Inner[4] conv_arr_4_Inner(Inner_std140 val[4]) {
-  Inner arr[4] = Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_Inner(val[i]);
-    }
-  }
-  return arr;
-}
-
-Outer conv_Outer(Outer_std140 val) {
-  Outer tint_symbol_1 = Outer(conv_arr_4_Inner(val.a));
-  return tint_symbol_1;
-}
-
-Outer[4] conv_arr_4_Outer(Outer_std140 val[4]) {
-  Outer arr[4] = Outer[4](Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)))));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_Outer(val[i]);
-    }
-  }
-  return arr;
-}
-
-mat3x2 load_a_3_a_2_m() {
-  return mat3x2(a.inner[3u].a[2u].m_0, a.inner[3u].a[2u].m_1, a.inner[3u].a[2u].m_2);
-}
-
-void f() {
-  int I = 1;
-  Outer p_a[4] = conv_arr_4_Outer(a.inner);
-  Outer p_a_3 = conv_Outer(a.inner[3u]);
-  Inner p_a_3_a[4] = conv_arr_4_Inner(a.inner[3u].a);
-  Inner p_a_3_a_2 = conv_Inner(a.inner[3u].a[2u]);
-  mat3x2 p_a_3_a_2_m = load_a_3_a_2_m();
-  vec2 p_a_3_a_2_m_1 = a.inner[3u].a[2u].m_1;
-  Outer l_a[4] = conv_arr_4_Outer(a.inner);
-  Outer l_a_3 = conv_Outer(a.inner[3u]);
-  Inner l_a_3_a[4] = conv_arr_4_Inner(a.inner[3u].a);
-  Inner l_a_3_a_2 = conv_Inner(a.inner[3u].a[2u]);
-  mat3x2 l_a_3_a_2_m = load_a_3_a_2_m();
-  vec2 l_a_3_a_2_m_1 = a.inner[3u].a[2u].m_1;
-  float l_a_3_a_2_m_1_0 = a.inner[3u].a[2u].m_1[0u];
-}
-
-layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
-void main() {
-  f();
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.spvasm
deleted file mode 100644
index df0b5fd..0000000
--- a/test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.spvasm
+++ /dev/null
@@ -1,80 +0,0 @@
-; SPIR-V
-; Version: 1.3
-; Generator: Google Tint Compiler; 0
-; Bound: 46
-; Schema: 0
-               OpCapability Shader
-         %36 = OpExtInstImport "GLSL.std.450"
-               OpMemoryModel Logical GLSL450
-               OpEntryPoint GLCompute %f "f"
-               OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
-               OpName %S_std140 "S_std140"
-               OpMemberName %S_std140 0 "before"
-               OpMemberName %S_std140 1 "m_0"
-               OpMemberName %S_std140 2 "m_1"
-               OpMemberName %S_std140 3 "m_2"
-               OpMemberName %S_std140 4 "after"
-               OpName %u "u"
-               OpName %load_u_2_m "load_u_2_m"
-               OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
-               OpMemberDecorate %S_std140 0 Offset 0
-               OpMemberDecorate %S_std140 1 Offset 8
-               OpMemberDecorate %S_std140 2 Offset 16
-               OpMemberDecorate %S_std140 3 Offset 24
-               OpMemberDecorate %S_std140 4 Offset 40
-               OpDecorate %_arr_S_std140_uint_4 ArrayStride 48
-               OpDecorate %u NonWritable
-               OpDecorate %u DescriptorSet 0
-               OpDecorate %u Binding 0
-        %int = OpTypeInt 32 1
-      %float = OpTypeFloat 32
-    %v2float = OpTypeVector %float 2
-   %S_std140 = OpTypeStruct %int %v2float %v2float %v2float %int
-       %uint = OpTypeInt 32 0
-     %uint_4 = OpConstant %uint 4
-%_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
-%mat3v2float = OpTypeMatrix %v2float 3
-         %11 = OpTypeFunction %mat3v2float
-     %uint_0 = OpConstant %uint 0
-     %uint_2 = OpConstant %uint 2
-     %uint_1 = OpConstant %uint 1
-%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
-     %uint_3 = OpConstant %uint 3
-       %void = OpTypeVoid
-         %27 = OpTypeFunction %void
-    %v3float = OpTypeVector %float 3
-%mat2v3float = OpTypeMatrix %v3float 2
-         %37 = OpConstantNull %uint
- %load_u_2_m = OpFunction %mat3v2float None %11
-         %14 = OpLabel
-         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %20 = OpLoad %v2float %19
-         %21 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %22 = OpLoad %v2float %21
-         %24 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_3
-         %25 = OpLoad %v2float %24
-         %26 = OpCompositeConstruct %mat3v2float %20 %22 %25
-               OpReturnValue %26
-               OpFunctionEnd
-          %f = OpFunction %void None %27
-         %30 = OpLabel
-         %34 = OpFunctionCall %mat3v2float %load_u_2_m
-         %31 = OpTranspose %mat2v3float %34
-         %38 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %37 %uint_2
-         %39 = OpLoad %v2float %38
-         %40 = OpVectorShuffle %v2float %39 %39 1 0
-         %35 = OpExtInst %float %36 Length %40
-         %42 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %37 %uint_2
-         %43 = OpLoad %v2float %42
-         %44 = OpVectorShuffle %v2float %43 %43 1 0
-         %45 = OpCompositeExtract %float %44 0
-         %41 = OpExtInst %float %36 FAbs %45
-               OpReturn
-               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.glsl
deleted file mode 100644
index cb73e87..0000000
--- a/test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.glsl
+++ /dev/null
@@ -1,79 +0,0 @@
-#version 310 es
-
-struct S {
-  int before;
-  mat3x2 m;
-  int after;
-};
-
-struct S_std140 {
-  int before;
-  uint pad;
-  vec2 m_0;
-  vec2 m_1;
-  vec2 m_2;
-  uint pad_1;
-  uint pad_2;
-  uint pad_3;
-  uint pad_4;
-  uint pad_5;
-  uint pad_6;
-  uint pad_7;
-  uint pad_8;
-  uint pad_9;
-  uint pad_10;
-  int after;
-  uint pad_11;
-};
-
-layout(binding = 0, std140) uniform u_block_ubo {
-  S_std140 inner[4];
-} u;
-
-void a(S a_1[4]) {
-}
-
-void b(S s) {
-}
-
-void c(mat3x2 m) {
-}
-
-void d(vec2 v) {
-}
-
-void e(float f_1) {
-}
-
-S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, mat3x2(val.m_0, val.m_1, val.m_2), val.after);
-  return tint_symbol;
-}
-
-S[4] conv_arr_4_S(S_std140 val[4]) {
-  S arr[4] = S[4](S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_S(val[i]);
-    }
-  }
-  return arr;
-}
-
-mat3x2 load_u_2_m() {
-  return mat3x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2);
-}
-
-void f() {
-  a(conv_arr_4_S(u.inner));
-  b(conv_S(u.inner[2u]));
-  c(load_u_2_m());
-  d(u.inner[0u].m_1.yx);
-  e(u.inner[0u].m_1.yx[0u]);
-}
-
-layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
-void main() {
-  f();
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.glsl
deleted file mode 100644
index afdcbcd..0000000
--- a/test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.glsl
+++ /dev/null
@@ -1,64 +0,0 @@
-#version 310 es
-
-struct S {
-  int before;
-  mat3x2 m;
-  int after;
-};
-
-struct S_std140 {
-  int before;
-  uint pad;
-  vec2 m_0;
-  vec2 m_1;
-  vec2 m_2;
-  uint pad_1;
-  uint pad_2;
-  uint pad_3;
-  uint pad_4;
-  uint pad_5;
-  uint pad_6;
-  uint pad_7;
-  uint pad_8;
-  uint pad_9;
-  uint pad_10;
-  int after;
-  uint pad_11;
-};
-
-layout(binding = 0, std140) uniform u_block_ubo {
-  S_std140 inner[4];
-} u;
-
-S p[4] = S[4](S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0));
-S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, mat3x2(val.m_0, val.m_1, val.m_2), val.after);
-  return tint_symbol;
-}
-
-S[4] conv_arr_4_S(S_std140 val[4]) {
-  S arr[4] = S[4](S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_S(val[i]);
-    }
-  }
-  return arr;
-}
-
-mat3x2 load_u_2_m() {
-  return mat3x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2);
-}
-
-void f() {
-  p = conv_arr_4_S(u.inner);
-  p[1] = conv_S(u.inner[2u]);
-  p[3].m = load_u_2_m();
-  p[1].m[0] = u.inner[0u].m_1.yx;
-}
-
-layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
-void main() {
-  f();
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.glsl
deleted file mode 100644
index 17e4deb..0000000
--- a/test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.glsl
+++ /dev/null
@@ -1,72 +0,0 @@
-#version 310 es
-
-struct S {
-  int before;
-  mat3x2 m;
-  int after;
-};
-
-struct S_std140 {
-  int before;
-  uint pad;
-  vec2 m_0;
-  vec2 m_1;
-  vec2 m_2;
-  uint pad_1;
-  uint pad_2;
-  uint pad_3;
-  uint pad_4;
-  uint pad_5;
-  uint pad_6;
-  uint pad_7;
-  uint pad_8;
-  uint pad_9;
-  uint pad_10;
-  int after;
-  uint pad_11;
-};
-
-layout(binding = 0, std140) uniform u_block_ubo {
-  S_std140 inner[4];
-} u;
-
-shared S w[4];
-S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, mat3x2(val.m_0, val.m_1, val.m_2), val.after);
-  return tint_symbol;
-}
-
-S[4] conv_arr_4_S(S_std140 val[4]) {
-  S arr[4] = S[4](S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_S(val[i]);
-    }
-  }
-  return arr;
-}
-
-mat3x2 load_u_2_m() {
-  return mat3x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2);
-}
-
-void f(uint local_invocation_index) {
-  {
-    for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
-      uint i = idx;
-      S tint_symbol_1 = S(0, mat3x2(vec2(0.0f), vec2(0.0f), vec2(0.0f)), 0);
-      w[i] = tint_symbol_1;
-    }
-  }
-  barrier();
-  w = conv_arr_4_S(u.inner);
-  w[1] = conv_S(u.inner[2u]);
-  w[3].m = load_u_2_m();
-  w[1].m[0] = u.inner[0u].m_1.yx;
-}
-
-layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
-void main() {
-  f(gl_LocalInvocationIndex);
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
deleted file mode 100644
index 597afef..0000000
--- a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
+++ /dev/null
@@ -1,67 +0,0 @@
-struct Inner {
-  float4x2 m;
-};
-struct Outer {
-  Inner a[4];
-};
-
-cbuffer cbuffer_a : register(b0, space0) {
-  uint4 a[32];
-};
-
-float4x2 tint_symbol_4(uint4 buffer[32], uint offset) {
-  const uint scalar_offset = ((offset + 0u)) / 4;
-  uint4 ubo_load = buffer[scalar_offset / 4];
-  const uint scalar_offset_1 = ((offset + 8u)) / 4;
-  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
-  const uint scalar_offset_2 = ((offset + 16u)) / 4;
-  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
-  const uint scalar_offset_3 = ((offset + 24u)) / 4;
-  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
-  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
-}
-
-Inner tint_symbol_3(uint4 buffer[32], uint offset) {
-  const Inner tint_symbol_7 = {tint_symbol_4(buffer, (offset + 0u))};
-  return tint_symbol_7;
-}
-
-typedef Inner tint_symbol_2_ret[4];
-tint_symbol_2_ret tint_symbol_2(uint4 buffer[32], uint offset) {
-  Inner arr[4] = (Inner[4])0;
-  {
-    [loop] for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = tint_symbol_3(buffer, (offset + (i * 32u)));
-    }
-  }
-  return arr;
-}
-
-Outer tint_symbol_1(uint4 buffer[32], uint offset) {
-  const Outer tint_symbol_8 = {tint_symbol_2(buffer, (offset + 0u))};
-  return tint_symbol_8;
-}
-
-typedef Outer tint_symbol_ret[4];
-tint_symbol_ret tint_symbol(uint4 buffer[32], uint offset) {
-  Outer arr_1[4] = (Outer[4])0;
-  {
-    [loop] for(uint i_1 = 0u; (i_1 < 4u); i_1 = (i_1 + 1u)) {
-      arr_1[i_1] = tint_symbol_1(buffer, (offset + (i_1 * 128u)));
-    }
-  }
-  return arr_1;
-}
-
-[numthreads(1, 1, 1)]
-void f() {
-  const int I = 1;
-  const Outer l_a[4] = tint_symbol(a, 0u);
-  const Outer l_a_3 = tint_symbol_1(a, 384u);
-  const Inner l_a_3_a[4] = tint_symbol_2(a, 384u);
-  const Inner l_a_3_a_2 = tint_symbol_3(a, 448u);
-  const float4x2 l_a_3_a_2_m = tint_symbol_4(a, 448u);
-  const float2 l_a_3_a_2_m_1 = asfloat(a[28].zw);
-  const float l_a_3_a_2_m_1_0 = asfloat(a[28].z);
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.spvasm
deleted file mode 100644
index a9f5647..0000000
--- a/test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.spvasm
+++ /dev/null
@@ -1,84 +0,0 @@
-; SPIR-V
-; Version: 1.3
-; Generator: Google Tint Compiler; 0
-; Bound: 48
-; Schema: 0
-               OpCapability Shader
-         %38 = OpExtInstImport "GLSL.std.450"
-               OpMemoryModel Logical GLSL450
-               OpEntryPoint GLCompute %f "f"
-               OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
-               OpName %S_std140 "S_std140"
-               OpMemberName %S_std140 0 "before"
-               OpMemberName %S_std140 1 "m_0"
-               OpMemberName %S_std140 2 "m_1"
-               OpMemberName %S_std140 3 "m_2"
-               OpMemberName %S_std140 4 "m_3"
-               OpMemberName %S_std140 5 "after"
-               OpName %u "u"
-               OpName %load_u_2_m "load_u_2_m"
-               OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
-               OpMemberDecorate %S_std140 0 Offset 0
-               OpMemberDecorate %S_std140 1 Offset 8
-               OpMemberDecorate %S_std140 2 Offset 16
-               OpMemberDecorate %S_std140 3 Offset 24
-               OpMemberDecorate %S_std140 4 Offset 32
-               OpMemberDecorate %S_std140 5 Offset 40
-               OpDecorate %_arr_S_std140_uint_4 ArrayStride 48
-               OpDecorate %u NonWritable
-               OpDecorate %u DescriptorSet 0
-               OpDecorate %u Binding 0
-        %int = OpTypeInt 32 1
-      %float = OpTypeFloat 32
-    %v2float = OpTypeVector %float 2
-   %S_std140 = OpTypeStruct %int %v2float %v2float %v2float %v2float %int
-       %uint = OpTypeInt 32 0
-     %uint_4 = OpConstant %uint 4
-%_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
-%mat4v2float = OpTypeMatrix %v2float 4
-         %11 = OpTypeFunction %mat4v2float
-     %uint_0 = OpConstant %uint 0
-     %uint_2 = OpConstant %uint 2
-     %uint_1 = OpConstant %uint 1
-%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
-     %uint_3 = OpConstant %uint 3
-       %void = OpTypeVoid
-         %29 = OpTypeFunction %void
-    %v4float = OpTypeVector %float 4
-%mat2v4float = OpTypeMatrix %v4float 2
-         %39 = OpConstantNull %uint
- %load_u_2_m = OpFunction %mat4v2float None %11
-         %14 = OpLabel
-         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %20 = OpLoad %v2float %19
-         %21 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %22 = OpLoad %v2float %21
-         %24 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_3
-         %25 = OpLoad %v2float %24
-         %26 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_4
-         %27 = OpLoad %v2float %26
-         %28 = OpCompositeConstruct %mat4v2float %20 %22 %25 %27
-               OpReturnValue %28
-               OpFunctionEnd
-          %f = OpFunction %void None %29
-         %32 = OpLabel
-         %36 = OpFunctionCall %mat4v2float %load_u_2_m
-         %33 = OpTranspose %mat2v4float %36
-         %40 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %39 %uint_2
-         %41 = OpLoad %v2float %40
-         %42 = OpVectorShuffle %v2float %41 %41 1 0
-         %37 = OpExtInst %float %38 Length %42
-         %44 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %39 %uint_2
-         %45 = OpLoad %v2float %44
-         %46 = OpVectorShuffle %v2float %45 %45 1 0
-         %47 = OpCompositeExtract %float %46 0
-         %43 = OpExtInst %float %38 FAbs %47
-               OpReturn
-               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.glsl
deleted file mode 100644
index 837c23e..0000000
--- a/test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.glsl
+++ /dev/null
@@ -1,70 +0,0 @@
-#version 310 es
-
-struct S {
-  int before;
-  mat4x2 m;
-  int after;
-};
-
-struct S_std140 {
-  int before;
-  uint pad;
-  vec2 m_0;
-  vec2 m_1;
-  vec2 m_2;
-  vec2 m_3;
-  int after;
-  uint pad_1;
-};
-
-layout(binding = 0, std140) uniform u_block_ubo {
-  S_std140 inner[4];
-} u;
-
-void a(S a_1[4]) {
-}
-
-void b(S s) {
-}
-
-void c(mat4x2 m) {
-}
-
-void d(vec2 v) {
-}
-
-void e(float f_1) {
-}
-
-S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, mat4x2(val.m_0, val.m_1, val.m_2, val.m_3), val.after);
-  return tint_symbol;
-}
-
-S[4] conv_arr_4_S(S_std140 val[4]) {
-  S arr[4] = S[4](S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_S(val[i]);
-    }
-  }
-  return arr;
-}
-
-mat4x2 load_u_2_m() {
-  return mat4x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2, u.inner[2u].m_3);
-}
-
-void f() {
-  a(conv_arr_4_S(u.inner));
-  b(conv_S(u.inner[2u]));
-  c(load_u_2_m());
-  d(u.inner[0u].m_1.yx);
-  e(u.inner[0u].m_1.yx[0u]);
-}
-
-layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
-void main() {
-  f();
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.glsl
deleted file mode 100644
index 235d81d..0000000
--- a/test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.glsl
+++ /dev/null
@@ -1,55 +0,0 @@
-#version 310 es
-
-struct S {
-  int before;
-  mat4x2 m;
-  int after;
-};
-
-struct S_std140 {
-  int before;
-  uint pad;
-  vec2 m_0;
-  vec2 m_1;
-  vec2 m_2;
-  vec2 m_3;
-  int after;
-  uint pad_1;
-};
-
-layout(binding = 0, std140) uniform u_block_ubo {
-  S_std140 inner[4];
-} u;
-
-S p[4] = S[4](S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0));
-S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, mat4x2(val.m_0, val.m_1, val.m_2, val.m_3), val.after);
-  return tint_symbol;
-}
-
-S[4] conv_arr_4_S(S_std140 val[4]) {
-  S arr[4] = S[4](S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_S(val[i]);
-    }
-  }
-  return arr;
-}
-
-mat4x2 load_u_2_m() {
-  return mat4x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2, u.inner[2u].m_3);
-}
-
-void f() {
-  p = conv_arr_4_S(u.inner);
-  p[1] = conv_S(u.inner[2u]);
-  p[3].m = load_u_2_m();
-  p[1].m[0] = u.inner[0u].m_1.yx;
-}
-
-layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
-void main() {
-  f();
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.glsl
deleted file mode 100644
index 1b2f51f..0000000
--- a/test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.glsl
+++ /dev/null
@@ -1,63 +0,0 @@
-#version 310 es
-
-struct S {
-  int before;
-  mat4x2 m;
-  int after;
-};
-
-struct S_std140 {
-  int before;
-  uint pad;
-  vec2 m_0;
-  vec2 m_1;
-  vec2 m_2;
-  vec2 m_3;
-  int after;
-  uint pad_1;
-};
-
-layout(binding = 0, std140) uniform u_block_ubo {
-  S_std140 inner[4];
-} u;
-
-shared S w[4];
-S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, mat4x2(val.m_0, val.m_1, val.m_2, val.m_3), val.after);
-  return tint_symbol;
-}
-
-S[4] conv_arr_4_S(S_std140 val[4]) {
-  S arr[4] = S[4](S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0));
-  {
-    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
-      arr[i] = conv_S(val[i]);
-    }
-  }
-  return arr;
-}
-
-mat4x2 load_u_2_m() {
-  return mat4x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2, u.inner[2u].m_3);
-}
-
-void f(uint local_invocation_index) {
-  {
-    for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
-      uint i = idx;
-      S tint_symbol_1 = S(0, mat4x2(vec2(0.0f), vec2(0.0f), vec2(0.0f), vec2(0.0f)), 0);
-      w[i] = tint_symbol_1;
-    }
-  }
-  barrier();
-  w = conv_arr_4_S(u.inner);
-  w[1] = conv_S(u.inner[2u]);
-  w[3].m = load_u_2_m();
-  w[1].m[0] = u.inner[0u].m_1.yx;
-}
-
-layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
-void main() {
-  f(gl_LocalInvocationIndex);
-  return;
-}
diff --git a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl
index 2d14c16..fc1258e 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl
@@ -13,8 +13,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
-
   let p_a           = &a;
   let p_a_i         = &((*p_a)[i()]);
   let p_a_i_a       = &((*p_a_i).a);
diff --git a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
similarity index 99%
rename from test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
index 7a2acd8..10f6093 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -57,7 +57,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const int p_a_i_save = i();
   const int p_a_i_a_i_save = i();
   const int p_a_i_a_i_m_i_save = i();
diff --git a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
similarity index 99%
rename from test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
index 7a2acd8..10f6093 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -57,7 +57,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const int p_a_i_save = i();
   const int p_a_i_a_i_save = i();
   const int p_a_i_a_i_m_i_save = i();
diff --git a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl
similarity index 75%
rename from test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl
index 70d9461..e27a647 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl
@@ -17,7 +17,7 @@
   Inner_std140 a[4];
 };
 
-layout(binding = 0, std140) uniform a_block_ubo {
+layout(binding = 0, std140) uniform a_block_std140_ubo {
   Outer_std140 inner[4];
 } a;
 
@@ -28,8 +28,7 @@
 }
 
 Inner conv_Inner(Inner_std140 val) {
-  Inner tint_symbol_4 = Inner(mat2(val.m_0, val.m_1));
-  return tint_symbol_4;
+  return Inner(mat2(val.m_0, val.m_1));
 }
 
 Inner[4] conv_arr_4_Inner(Inner_std140 val[4]) {
@@ -43,8 +42,7 @@
 }
 
 Outer conv_Outer(Outer_std140 val) {
-  Outer tint_symbol_5 = Outer(conv_arr_4_Inner(val.a));
-  return tint_symbol_5;
+  return Outer(conv_arr_4_Inner(val.a));
 }
 
 Outer[4] conv_arr_4_Outer(Outer_std140 val[4]) {
@@ -57,13 +55,13 @@
   return arr;
 }
 
-mat2 load_a_p0_a_p1_m(uint p0, uint p1) {
+mat2 load_a_inner_p0_a_p1_m(uint p0, uint p1) {
   uint s_save = p0;
   uint s_save_1 = p1;
   return mat2(a.inner[s_save].a[s_save_1].m_0, a.inner[s_save].a[s_save_1].m_1);
 }
 
-vec2 load_a_p0_a_p1_m_p2(uint p0, uint p1, uint p2) {
+vec2 load_a_inner_p0_a_p1_m_p2(uint p0, uint p1, uint p2) {
   switch(p2) {
     case 0u: {
       return a.inner[p0].a[p1].m_0;
@@ -80,7 +78,7 @@
   }
 }
 
-float load_a_p0_a_p1_m_p2_p3(uint p0, uint p1, uint p2, uint p3) {
+float load_a_inner_p0_a_p1_m_p2_p3(uint p0, uint p1, uint p2, uint p3) {
   switch(p2) {
     case 0u: {
       return a.inner[p0].a[p1].m_0[p3];
@@ -98,24 +96,23 @@
 }
 
 void f() {
-  int I = 1;
   Outer p_a[4] = conv_arr_4_Outer(a.inner);
   int tint_symbol = i();
   Outer p_a_i = conv_Outer(a.inner[tint_symbol]);
   Inner p_a_i_a[4] = conv_arr_4_Inner(a.inner[tint_symbol].a);
   int tint_symbol_1 = i();
   Inner p_a_i_a_i = conv_Inner(a.inner[tint_symbol].a[tint_symbol_1]);
-  mat2 p_a_i_a_i_m = load_a_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
+  mat2 p_a_i_a_i_m = load_a_inner_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
   int tint_symbol_2 = i();
-  vec2 p_a_i_a_i_m_i = load_a_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
+  vec2 p_a_i_a_i_m_i = load_a_inner_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
   Outer l_a[4] = conv_arr_4_Outer(a.inner);
   Outer l_a_i = conv_Outer(a.inner[tint_symbol]);
   Inner l_a_i_a[4] = conv_arr_4_Inner(a.inner[tint_symbol].a);
   Inner l_a_i_a_i = conv_Inner(a.inner[tint_symbol].a[tint_symbol_1]);
-  mat2 l_a_i_a_i_m = load_a_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
-  vec2 l_a_i_a_i_m_i = load_a_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
+  mat2 l_a_i_a_i_m = load_a_inner_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
+  vec2 l_a_i_a_i_m_i = load_a_inner_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
   int tint_symbol_3 = i();
-  float l_a_i_a_i_m_i_i = load_a_p0_a_p1_m_p2_p3(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2), uint(tint_symbol_3));
+  float l_a_i_a_i_m_i_i = load_a_inner_p0_a_p1_m_p2_p3(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2), uint(tint_symbol_3));
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl
index b362cb8..c1d8152 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl
@@ -29,7 +29,6 @@
 }
 
 kernel void f(const constant tint_array<Outer, 4>* tint_symbol_5 [[buffer(0)]]) {
-  int const I = 1;
   int const tint_symbol = i();
   int const p_a_i_save = tint_symbol;
   int const tint_symbol_1 = i();
diff --git a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm
similarity index 63%
rename from test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm
index 218f94c..7950eac 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 208
+; Bound: 193
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %a_block "a_block"
-               OpMemberName %a_block 0 "inner"
+               OpName %a_block_std140 "a_block_std140"
+               OpMemberName %a_block_std140 0 "inner"
                OpName %Outer_std140 "Outer_std140"
                OpMemberName %Outer_std140 0 "a"
                OpName %Inner_std140 "Inner_std140"
@@ -25,7 +25,7 @@
                OpName %val_0 "val"
                OpName %arr "arr"
                OpName %i_0 "i"
-               OpName %var_for_index "var_for_index"
+               OpName %var_for_index_1 "var_for_index_1"
                OpName %Outer "Outer"
                OpMemberName %Outer 0 "a"
                OpName %conv_Outer "conv_Outer"
@@ -34,22 +34,22 @@
                OpName %val_2 "val"
                OpName %arr_0 "arr"
                OpName %i_1 "i"
-               OpName %var_for_index_1 "var_for_index_1"
-               OpName %load_a_p0_a_p1_m "load_a_p0_a_p1_m"
+               OpName %var_for_index "var_for_index"
+               OpName %load_a_inner_p0_a_p1_m "load_a_inner_p0_a_p1_m"
                OpName %p0 "p0"
                OpName %p1 "p1"
-               OpName %load_a_p0_a_p1_m_p2 "load_a_p0_a_p1_m_p2"
+               OpName %load_a_inner_p0_a_p1_m_p2 "load_a_inner_p0_a_p1_m_p2"
                OpName %p0_0 "p0"
                OpName %p1_0 "p1"
                OpName %p2 "p2"
-               OpName %load_a_p0_a_p1_m_p2_p3 "load_a_p0_a_p1_m_p2_p3"
+               OpName %load_a_inner_p0_a_p1_m_p2_p3 "load_a_inner_p0_a_p1_m_p2_p3"
                OpName %p0_1 "p0"
                OpName %p1_1 "p1"
                OpName %p2_0 "p2"
                OpName %p3 "p3"
                OpName %f "f"
-               OpDecorate %a_block Block
-               OpMemberDecorate %a_block 0 Offset 0
+               OpDecorate %a_block_std140 Block
+               OpMemberDecorate %a_block_std140 0 Offset 0
                OpMemberDecorate %Outer_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 1 Offset 8
@@ -72,9 +72,9 @@
 %_arr_Inner_std140_uint_4 = OpTypeArray %Inner_std140 %uint_4
 %Outer_std140 = OpTypeStruct %_arr_Inner_std140_uint_4
 %_arr_Outer_std140_uint_4 = OpTypeArray %Outer_std140 %uint_4
-    %a_block = OpTypeStruct %_arr_Outer_std140_uint_4
-%_ptr_Uniform_a_block = OpTypePointer Uniform %a_block
-          %a = OpVariable %_ptr_Uniform_a_block Uniform
+%a_block_std140 = OpTypeStruct %_arr_Outer_std140_uint_4
+%_ptr_Uniform_a_block_std140 = OpTypePointer Uniform %a_block_std140
+          %a = OpVariable %_ptr_Uniform_a_block_std140 Uniform
         %int = OpTypeInt 32 1
          %13 = OpConstantNull %int
 %_ptr_Private_int = OpTypePointer Private %int
@@ -108,18 +108,18 @@
 %_ptr_Function_Outer_std140 = OpTypePointer Function %Outer_std140
         %109 = OpTypeFunction %mat2v2float %uint %uint
      %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
-        %121 = OpTypeFunction %v2float %uint %uint %uint
-        %135 = OpConstantNull %v2float
-        %136 = OpTypeFunction %float %uint %uint %uint %uint
+        %126 = OpTypeFunction %v2float %uint %uint %uint
+        %140 = OpConstantNull %v2float
+        %141 = OpTypeFunction %float %uint %uint %uint %uint
 %_ptr_Uniform_float = OpTypePointer Uniform %float
-        %152 = OpConstantNull %float
+        %157 = OpConstantNull %float
        %void = OpTypeVoid
-        %153 = OpTypeFunction %void
+        %158 = OpTypeFunction %void
 %_ptr_Uniform__arr_Outer_std140_uint_4 = OpTypePointer Uniform %_arr_Outer_std140_uint_4
 %_ptr_Uniform_Outer_std140 = OpTypePointer Uniform %Outer_std140
 %_ptr_Uniform__arr_Inner_std140_uint_4 = OpTypePointer Uniform %_arr_Inner_std140_uint_4
-%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
           %i = OpFunction %int None %16
          %18 = OpLabel
          %19 = OpLoad %int %counter
@@ -142,7 +142,7 @@
          %37 = OpLabel
         %arr = OpVariable %_ptr_Function__arr_Inner_uint_4 Function %40
         %i_0 = OpVariable %_ptr_Function_uint Function %43
-%var_for_index = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %56
+%var_for_index_1 = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %56
                OpBranch %44
          %44 = OpLabel
                OpLoopMerge %45 %46 None
@@ -156,11 +156,11 @@
          %53 = OpLabel
                OpBranch %45
          %52 = OpLabel
-               OpStore %var_for_index %val_0
+               OpStore %var_for_index_1 %val_0
          %57 = OpLoad %uint %i_0
          %59 = OpAccessChain %_ptr_Function_Inner %arr %57
          %61 = OpLoad %uint %i_0
-         %63 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index %61
+         %63 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index_1 %61
          %64 = OpLoad %Inner_std140 %63
          %60 = OpFunctionCall %Inner %conv_Inner %64
                OpStore %59 %60
@@ -187,7 +187,7 @@
          %81 = OpLabel
       %arr_0 = OpVariable %_ptr_Function__arr_Outer_uint_4 Function %84
         %i_1 = OpVariable %_ptr_Function_uint Function %43
-%var_for_index_1 = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %97
+%var_for_index = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %97
                OpBranch %86
          %86 = OpLabel
                OpLoopMerge %87 %88 None
@@ -201,11 +201,11 @@
          %94 = OpLabel
                OpBranch %87
          %93 = OpLabel
-               OpStore %var_for_index_1 %val_2
+               OpStore %var_for_index %val_2
          %98 = OpLoad %uint %i_1
         %100 = OpAccessChain %_ptr_Function_Outer %arr_0 %98
         %102 = OpLoad %uint %i_1
-        %104 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index_1 %102
+        %104 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index %102
         %105 = OpLoad %Outer_std140 %104
         %101 = OpFunctionCall %Outer %conv_Outer %105
                OpStore %100 %101
@@ -219,106 +219,88 @@
         %108 = OpLoad %_arr_Outer_uint_4 %arr_0
                OpReturnValue %108
                OpFunctionEnd
-%load_a_p0_a_p1_m = OpFunction %mat2v2float None %109
+%load_a_inner_p0_a_p1_m = OpFunction %mat2v2float None %109
          %p0 = OpFunctionParameter %uint
          %p1 = OpFunctionParameter %uint
         %113 = OpLabel
-        %116 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0 %uint_0 %p1 %uint_0
-        %117 = OpLoad %v2float %116
-        %118 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0 %uint_0 %p1 %uint_1
-        %119 = OpLoad %v2float %118
-        %120 = OpCompositeConstruct %mat2v2float %117 %119
-               OpReturnValue %120
+        %117 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %p0 %uint_0 %p1
+        %120 = OpAccessChain %_ptr_Uniform_v2float %117 %uint_0
+        %121 = OpLoad %v2float %120
+        %123 = OpAccessChain %_ptr_Uniform_v2float %117 %uint_1
+        %124 = OpLoad %v2float %123
+        %125 = OpCompositeConstruct %mat2v2float %121 %124
+               OpReturnValue %125
                OpFunctionEnd
-%load_a_p0_a_p1_m_p2 = OpFunction %v2float None %121
+%load_a_inner_p0_a_p1_m_p2 = OpFunction %v2float None %126
        %p0_0 = OpFunctionParameter %uint
        %p1_0 = OpFunctionParameter %uint
          %p2 = OpFunctionParameter %uint
-        %126 = OpLabel
-               OpSelectionMerge %127 None
-               OpSwitch %p2 %128 0 %129 1 %130
-        %129 = OpLabel
-        %131 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_0
-        %132 = OpLoad %v2float %131
-               OpReturnValue %132
-        %130 = OpLabel
-        %133 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_1
-        %134 = OpLoad %v2float %133
-               OpReturnValue %134
-        %128 = OpLabel
-               OpReturnValue %135
-        %127 = OpLabel
-               OpReturnValue %135
+        %131 = OpLabel
+               OpSelectionMerge %132 None
+               OpSwitch %p2 %133 0 %134 1 %135
+        %134 = OpLabel
+        %136 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_0
+        %137 = OpLoad %v2float %136
+               OpReturnValue %137
+        %135 = OpLabel
+        %138 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_1
+        %139 = OpLoad %v2float %138
+               OpReturnValue %139
+        %133 = OpLabel
+               OpReturnValue %140
+        %132 = OpLabel
+               OpReturnValue %140
                OpFunctionEnd
-%load_a_p0_a_p1_m_p2_p3 = OpFunction %float None %136
+%load_a_inner_p0_a_p1_m_p2_p3 = OpFunction %float None %141
        %p0_1 = OpFunctionParameter %uint
        %p1_1 = OpFunctionParameter %uint
        %p2_0 = OpFunctionParameter %uint
          %p3 = OpFunctionParameter %uint
-        %142 = OpLabel
-               OpSelectionMerge %143 None
-               OpSwitch %p2_0 %144 0 %145 1 %146
-        %145 = OpLabel
-        %148 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_0 %p3
-        %149 = OpLoad %float %148
-               OpReturnValue %149
-        %146 = OpLabel
-        %150 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_1 %p3
-        %151 = OpLoad %float %150
-               OpReturnValue %151
-        %144 = OpLabel
-               OpReturnValue %152
-        %143 = OpLabel
-               OpReturnValue %152
+        %147 = OpLabel
+               OpSelectionMerge %148 None
+               OpSwitch %p2_0 %149 0 %150 1 %151
+        %150 = OpLabel
+        %153 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_0 %p3
+        %154 = OpLoad %float %153
+               OpReturnValue %154
+        %151 = OpLabel
+        %155 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_1 %p3
+        %156 = OpLoad %float %155
+               OpReturnValue %156
+        %149 = OpLabel
+               OpReturnValue %157
+        %148 = OpLabel
+               OpReturnValue %157
                OpFunctionEnd
-          %f = OpFunction %void None %153
-        %156 = OpLabel
-        %159 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %160 = OpLoad %_arr_Outer_std140_uint_4 %159
-        %157 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %160
-        %161 = OpFunctionCall %int %i
-        %164 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %161
-        %165 = OpLoad %Outer_std140 %164
-        %162 = OpFunctionCall %Outer %conv_Outer %165
-        %168 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %161 %uint_0
-        %169 = OpLoad %_arr_Inner_std140_uint_4 %168
-        %166 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %169
-        %170 = OpFunctionCall %int %i
-        %173 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %161 %uint_0 %170
-        %174 = OpLoad %Inner_std140 %173
-        %171 = OpFunctionCall %Inner %conv_Inner %174
-        %176 = OpBitcast %uint %161
-        %177 = OpBitcast %uint %170
-        %175 = OpFunctionCall %mat2v2float %load_a_p0_a_p1_m %176 %177
-        %178 = OpFunctionCall %int %i
-        %180 = OpBitcast %uint %161
-        %181 = OpBitcast %uint %170
-        %182 = OpBitcast %uint %178
-        %179 = OpFunctionCall %v2float %load_a_p0_a_p1_m_p2 %180 %181 %182
-        %184 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %185 = OpLoad %_arr_Outer_std140_uint_4 %184
-        %183 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %185
-        %187 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %161
-        %188 = OpLoad %Outer_std140 %187
-        %186 = OpFunctionCall %Outer %conv_Outer %188
-        %190 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %161 %uint_0
-        %191 = OpLoad %_arr_Inner_std140_uint_4 %190
-        %189 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %191
-        %193 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %161 %uint_0 %170
-        %194 = OpLoad %Inner_std140 %193
-        %192 = OpFunctionCall %Inner %conv_Inner %194
-        %196 = OpBitcast %uint %161
-        %197 = OpBitcast %uint %170
-        %195 = OpFunctionCall %mat2v2float %load_a_p0_a_p1_m %196 %197
-        %199 = OpBitcast %uint %161
-        %200 = OpBitcast %uint %170
-        %201 = OpBitcast %uint %178
-        %198 = OpFunctionCall %v2float %load_a_p0_a_p1_m_p2 %199 %200 %201
-        %202 = OpFunctionCall %int %i
-        %204 = OpBitcast %uint %161
-        %205 = OpBitcast %uint %170
-        %206 = OpBitcast %uint %178
-        %207 = OpBitcast %uint %202
-        %203 = OpFunctionCall %float %load_a_p0_a_p1_m_p2_p3 %204 %205 %206 %207
+          %f = OpFunction %void None %158
+        %161 = OpLabel
+        %162 = OpFunctionCall %int %i
+        %163 = OpFunctionCall %int %i
+        %164 = OpFunctionCall %int %i
+        %167 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
+        %168 = OpLoad %_arr_Outer_std140_uint_4 %167
+        %165 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %168
+        %171 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %162
+        %172 = OpLoad %Outer_std140 %171
+        %169 = OpFunctionCall %Outer %conv_Outer %172
+        %175 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %162 %uint_0
+        %176 = OpLoad %_arr_Inner_std140_uint_4 %175
+        %173 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %176
+        %178 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %162 %uint_0 %163
+        %179 = OpLoad %Inner_std140 %178
+        %177 = OpFunctionCall %Inner %conv_Inner %179
+        %181 = OpBitcast %uint %162
+        %182 = OpBitcast %uint %163
+        %180 = OpFunctionCall %mat2v2float %load_a_inner_p0_a_p1_m %181 %182
+        %184 = OpBitcast %uint %162
+        %185 = OpBitcast %uint %163
+        %186 = OpBitcast %uint %164
+        %183 = OpFunctionCall %v2float %load_a_inner_p0_a_p1_m_p2 %184 %185 %186
+        %187 = OpFunctionCall %int %i
+        %189 = OpBitcast %uint %162
+        %190 = OpBitcast %uint %163
+        %191 = OpBitcast %uint %164
+        %192 = OpBitcast %uint %187
+        %188 = OpFunctionCall %float %load_a_inner_p0_a_p1_m_p2_p3 %189 %190 %191 %192
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl
index f998978..97d5141 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl
@@ -17,7 +17,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
   let p_a = &(a);
   let p_a_i = &((*(p_a))[i()]);
   let p_a_i_a = &((*(p_a_i)).a);
diff --git a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl
similarity index 97%
rename from test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl
index 1e620f4..0a790a9 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl
@@ -10,8 +10,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
-
   let p_a = &a;
   let p_a_3 = &((*p_a)[3]);
   let p_a_3_a = &((*p_a_3).a);
diff --git a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
index d27e6df..b569500 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -51,7 +51,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const Outer l_a[4] = tint_symbol(a, 0u);
   const Outer l_a_3 = tint_symbol_1(a, 192u);
   const Inner l_a_3_a[4] = tint_symbol_2(a, 192u);
diff --git a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
similarity index 98%
copy from test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
copy to test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
index d27e6df..b569500 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -51,7 +51,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const Outer l_a[4] = tint_symbol(a, 0u);
   const Outer l_a_3 = tint_symbol_1(a, 192u);
   const Inner l_a_3_a[4] = tint_symbol_2(a, 192u);
diff --git a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.glsl
similarity index 86%
rename from test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.glsl
index 6dccf2a..f00bbf5 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.glsl
@@ -17,13 +17,12 @@
   Inner_std140 a[4];
 };
 
-layout(binding = 0, std140) uniform a_block_ubo {
+layout(binding = 0, std140) uniform a_block_std140_ubo {
   Outer_std140 inner[4];
 } a;
 
 Inner conv_Inner(Inner_std140 val) {
-  Inner tint_symbol = Inner(mat2(val.m_0, val.m_1));
-  return tint_symbol;
+  return Inner(mat2(val.m_0, val.m_1));
 }
 
 Inner[4] conv_arr_4_Inner(Inner_std140 val[4]) {
@@ -37,8 +36,7 @@
 }
 
 Outer conv_Outer(Outer_std140 val) {
-  Outer tint_symbol_1 = Outer(conv_arr_4_Inner(val.a));
-  return tint_symbol_1;
+  return Outer(conv_arr_4_Inner(val.a));
 }
 
 Outer[4] conv_arr_4_Outer(Outer_std140 val[4]) {
@@ -51,23 +49,22 @@
   return arr;
 }
 
-mat2 load_a_3_a_2_m() {
+mat2 load_a_inner_3_a_2_m() {
   return mat2(a.inner[3u].a[2u].m_0, a.inner[3u].a[2u].m_1);
 }
 
 void f() {
-  int I = 1;
   Outer p_a[4] = conv_arr_4_Outer(a.inner);
   Outer p_a_3 = conv_Outer(a.inner[3u]);
   Inner p_a_3_a[4] = conv_arr_4_Inner(a.inner[3u].a);
   Inner p_a_3_a_2 = conv_Inner(a.inner[3u].a[2u]);
-  mat2 p_a_3_a_2_m = load_a_3_a_2_m();
+  mat2 p_a_3_a_2_m = load_a_inner_3_a_2_m();
   vec2 p_a_3_a_2_m_1 = a.inner[3u].a[2u].m_1;
   Outer l_a[4] = conv_arr_4_Outer(a.inner);
   Outer l_a_3 = conv_Outer(a.inner[3u]);
   Inner l_a_3_a[4] = conv_arr_4_Inner(a.inner[3u].a);
   Inner l_a_3_a_2 = conv_Inner(a.inner[3u].a[2u]);
-  mat2 l_a_3_a_2_m = load_a_3_a_2_m();
+  mat2 l_a_3_a_2_m = load_a_inner_3_a_2_m();
   vec2 l_a_3_a_2_m_1 = a.inner[3u].a[2u].m_1;
   float l_a_3_a_2_m_1_0 = a.inner[3u].a[2u].m_1[0u];
 }
diff --git a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.msl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.msl
index a731312..e0658ac 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.msl
@@ -23,7 +23,6 @@
 };
 
 kernel void f(const constant tint_array<Outer, 4>* tint_symbol [[buffer(0)]]) {
-  int const I = 1;
   tint_array<Outer, 4> const l_a = *(tint_symbol);
   Outer const l_a_3 = (*(tint_symbol))[3];
   tint_array<Inner, 4> const l_a_3_a = (*(tint_symbol))[3].a;
diff --git a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.spvasm
similarity index 71%
rename from test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.spvasm
index 92ff1cb..6a3a339 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 153
+; Bound: 140
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %a_block "a_block"
-               OpMemberName %a_block 0 "inner"
+               OpName %a_block_std140 "a_block_std140"
+               OpMemberName %a_block_std140 0 "inner"
                OpName %Outer_std140 "Outer_std140"
                OpMemberName %Outer_std140 0 "a"
                OpName %Inner_std140 "Inner_std140"
@@ -23,7 +23,7 @@
                OpName %val_0 "val"
                OpName %arr "arr"
                OpName %i "i"
-               OpName %var_for_index "var_for_index"
+               OpName %var_for_index_1 "var_for_index_1"
                OpName %Outer "Outer"
                OpMemberName %Outer 0 "a"
                OpName %conv_Outer "conv_Outer"
@@ -32,11 +32,11 @@
                OpName %val_2 "val"
                OpName %arr_0 "arr"
                OpName %i_0 "i"
-               OpName %var_for_index_1 "var_for_index_1"
-               OpName %load_a_3_a_2_m "load_a_3_a_2_m"
+               OpName %var_for_index "var_for_index"
+               OpName %load_a_inner_3_a_2_m "load_a_inner_3_a_2_m"
                OpName %f "f"
-               OpDecorate %a_block Block
-               OpMemberDecorate %a_block 0 Offset 0
+               OpDecorate %a_block_std140 Block
+               OpMemberDecorate %a_block_std140 0 Offset 0
                OpMemberDecorate %Outer_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 1 Offset 8
@@ -59,9 +59,9 @@
 %_arr_Inner_std140_uint_4 = OpTypeArray %Inner_std140 %uint_4
 %Outer_std140 = OpTypeStruct %_arr_Inner_std140_uint_4
 %_arr_Outer_std140_uint_4 = OpTypeArray %Outer_std140 %uint_4
-    %a_block = OpTypeStruct %_arr_Outer_std140_uint_4
-%_ptr_Uniform_a_block = OpTypePointer Uniform %a_block
-          %a = OpVariable %_ptr_Uniform_a_block Uniform
+%a_block_std140 = OpTypeStruct %_arr_Outer_std140_uint_4
+%_ptr_Uniform_a_block_std140 = OpTypePointer Uniform %a_block_std140
+          %a = OpVariable %_ptr_Uniform_a_block_std140 Uniform
 %mat2v2float = OpTypeMatrix %v2float 2
       %Inner = OpTypeStruct %mat2v2float
          %12 = OpTypeFunction %Inner %Inner_std140
@@ -91,15 +91,13 @@
      %uint_0 = OpConstant %uint 0
      %uint_3 = OpConstant %uint 3
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
        %void = OpTypeVoid
-        %110 = OpTypeFunction %void
-        %int = OpTypeInt 32 1
-      %int_1 = OpConstant %int 1
+        %115 = OpTypeFunction %void
 %_ptr_Uniform__arr_Outer_std140_uint_4 = OpTypePointer Uniform %_arr_Outer_std140_uint_4
 %_ptr_Uniform_Outer_std140 = OpTypePointer Uniform %Outer_std140
 %_ptr_Uniform__arr_Inner_std140_uint_4 = OpTypePointer Uniform %_arr_Inner_std140_uint_4
-%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
 %_ptr_Uniform_float = OpTypePointer Uniform %float
  %conv_Inner = OpFunction %Inner None %12
         %val = OpFunctionParameter %Inner_std140
@@ -115,7 +113,7 @@
          %26 = OpLabel
         %arr = OpVariable %_ptr_Function__arr_Inner_uint_4 Function %29
           %i = OpVariable %_ptr_Function_uint Function %32
-%var_for_index = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %45
+%var_for_index_1 = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %45
                OpBranch %33
          %33 = OpLabel
                OpLoopMerge %34 %35 None
@@ -129,11 +127,11 @@
          %42 = OpLabel
                OpBranch %34
          %41 = OpLabel
-               OpStore %var_for_index %val_0
+               OpStore %var_for_index_1 %val_0
          %46 = OpLoad %uint %i
          %48 = OpAccessChain %_ptr_Function_Inner %arr %46
          %50 = OpLoad %uint %i
-         %52 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index %50
+         %52 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index_1 %50
          %53 = OpLoad %Inner_std140 %52
          %49 = OpFunctionCall %Inner %conv_Inner %53
                OpStore %48 %49
@@ -160,7 +158,7 @@
          %70 = OpLabel
       %arr_0 = OpVariable %_ptr_Function__arr_Outer_uint_4 Function %73
         %i_0 = OpVariable %_ptr_Function_uint Function %32
-%var_for_index_1 = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %86
+%var_for_index = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %86
                OpBranch %75
          %75 = OpLabel
                OpLoopMerge %76 %77 None
@@ -174,11 +172,11 @@
          %83 = OpLabel
                OpBranch %76
          %82 = OpLabel
-               OpStore %var_for_index_1 %val_2
+               OpStore %var_for_index %val_2
          %87 = OpLoad %uint %i_0
          %89 = OpAccessChain %_ptr_Function_Outer %arr_0 %87
          %91 = OpLoad %uint %i_0
-         %93 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index_1 %91
+         %93 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index %91
          %94 = OpLoad %Outer_std140 %93
          %90 = OpFunctionCall %Outer %conv_Outer %94
                OpStore %89 %90
@@ -192,48 +190,34 @@
          %97 = OpLoad %_arr_Outer_uint_4 %arr_0
                OpReturnValue %97
                OpFunctionEnd
-%load_a_3_a_2_m = OpFunction %mat2v2float None %98
+%load_a_inner_3_a_2_m = OpFunction %mat2v2float None %98
         %100 = OpLabel
-        %105 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_0
-        %106 = OpLoad %v2float %105
-        %107 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
-        %108 = OpLoad %v2float %107
-        %109 = OpCompositeConstruct %mat2v2float %106 %108
-               OpReturnValue %109
+        %106 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
+        %109 = OpAccessChain %_ptr_Uniform_v2float %106 %uint_0
+        %110 = OpLoad %v2float %109
+        %112 = OpAccessChain %_ptr_Uniform_v2float %106 %uint_1
+        %113 = OpLoad %v2float %112
+        %114 = OpCompositeConstruct %mat2v2float %110 %113
+               OpReturnValue %114
                OpFunctionEnd
-          %f = OpFunction %void None %110
-        %113 = OpLabel
-        %118 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %119 = OpLoad %_arr_Outer_std140_uint_4 %118
-        %116 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %119
-        %122 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %uint_3
-        %123 = OpLoad %Outer_std140 %122
-        %120 = OpFunctionCall %Outer %conv_Outer %123
-        %126 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %uint_3 %uint_0
-        %127 = OpLoad %_arr_Inner_std140_uint_4 %126
-        %124 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %127
-        %130 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
-        %131 = OpLoad %Inner_std140 %130
-        %128 = OpFunctionCall %Inner %conv_Inner %131
-        %132 = OpFunctionCall %mat2v2float %load_a_3_a_2_m
-        %133 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
-        %134 = OpLoad %v2float %133
-        %136 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %137 = OpLoad %_arr_Outer_std140_uint_4 %136
-        %135 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %137
-        %139 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %uint_3
-        %140 = OpLoad %Outer_std140 %139
-        %138 = OpFunctionCall %Outer %conv_Outer %140
-        %142 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %uint_3 %uint_0
-        %143 = OpLoad %_arr_Inner_std140_uint_4 %142
-        %141 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %143
-        %145 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
-        %146 = OpLoad %Inner_std140 %145
-        %144 = OpFunctionCall %Inner %conv_Inner %146
-        %147 = OpFunctionCall %mat2v2float %load_a_3_a_2_m
-        %148 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
-        %149 = OpLoad %v2float %148
-        %151 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1 %32
-        %152 = OpLoad %float %151
+          %f = OpFunction %void None %115
+        %118 = OpLabel
+        %121 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
+        %122 = OpLoad %_arr_Outer_std140_uint_4 %121
+        %119 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %122
+        %125 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %uint_3
+        %126 = OpLoad %Outer_std140 %125
+        %123 = OpFunctionCall %Outer %conv_Outer %126
+        %129 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %uint_3 %uint_0
+        %130 = OpLoad %_arr_Inner_std140_uint_4 %129
+        %127 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %130
+        %132 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
+        %133 = OpLoad %Inner_std140 %132
+        %131 = OpFunctionCall %Inner %conv_Inner %133
+        %134 = OpFunctionCall %mat2v2float %load_a_inner_3_a_2_m
+        %135 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
+        %136 = OpLoad %v2float %135
+        %138 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1 %32
+        %139 = OpLoad %float %138
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.wgsl
similarity index 97%
rename from test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.wgsl
index 67b881f..2e24f26 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/static_index_via_ptr.wgsl.expected.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/static_index_via_ptr.wgsl.expected.wgsl
@@ -10,7 +10,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
   let p_a = &(a);
   let p_a_3 = &((*(p_a))[3]);
   let p_a_3_a = &((*(p_a_3)).a);
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.glsl
similarity index 74%
rename from test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.glsl
index d6c96b0..ee2a35b 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.glsl
@@ -2,8 +2,10 @@
 
 struct S {
   int before;
+  uint pad;
   mat2 m;
   int after;
+  uint pad_1;
 };
 
 struct S_std140 {
@@ -15,16 +17,16 @@
   uint pad_1;
 };
 
-layout(binding = 0, std140) uniform u_block_ubo {
+layout(binding = 0, std140) uniform u_block_std140_ubo {
   S_std140 inner[4];
 } u;
 
-mat2 load_u_2_m() {
+mat2 load_u_inner_2_m() {
   return mat2(u.inner[2u].m_0, u.inner[2u].m_1);
 }
 
 void f() {
-  mat2 t = transpose(load_u_2_m());
+  mat2 t = transpose(load_u_inner_2_m());
   float l = length(u.inner[0u].m_1.yx);
   float a = abs(u.inner[0u].m_1.yx[0u]);
 }
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.spvasm
new file mode 100644
index 0000000..e4863ac
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.spvasm
@@ -0,0 +1,75 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+               OpCapability Shader
+         %36 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
+               OpName %S_std140 "S_std140"
+               OpMemberName %S_std140 0 "before"
+               OpMemberName %S_std140 1 "m_0"
+               OpMemberName %S_std140 2 "m_1"
+               OpMemberName %S_std140 3 "after"
+               OpName %u "u"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %S_std140 0 Offset 0
+               OpMemberDecorate %S_std140 1 Offset 8
+               OpMemberDecorate %S_std140 2 Offset 16
+               OpMemberDecorate %S_std140 3 Offset 24
+               OpDecorate %_arr_S_std140_uint_4 ArrayStride 32
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+        %int = OpTypeInt 32 1
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+   %S_std140 = OpTypeStruct %int %v2float %v2float %int
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat2v2float = OpTypeMatrix %v2float 2
+         %11 = OpTypeFunction %mat2v2float
+     %uint_0 = OpConstant %uint 0
+     %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
+     %uint_1 = OpConstant %uint 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+       %void = OpTypeVoid
+         %29 = OpTypeFunction %void
+         %37 = OpConstantNull %uint
+%load_u_inner_2_m = OpFunction %mat2v2float None %11
+         %14 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %23 = OpAccessChain %_ptr_Uniform_v2float %19 %uint_1
+         %24 = OpLoad %v2float %23
+         %26 = OpAccessChain %_ptr_Uniform_v2float %19 %uint_2
+         %27 = OpLoad %v2float %26
+         %28 = OpCompositeConstruct %mat2v2float %24 %27
+               OpReturnValue %28
+               OpFunctionEnd
+          %f = OpFunction %void None %29
+         %32 = OpLabel
+         %34 = OpFunctionCall %mat2v2float %load_u_inner_2_m
+         %33 = OpTranspose %mat2v2float %34
+         %38 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %37 %uint_2
+         %39 = OpLoad %v2float %38
+         %40 = OpVectorShuffle %v2float %39 %39 1 0
+         %35 = OpExtInst %float %36 Length %40
+         %42 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %37 %uint_2
+         %43 = OpLoad %v2float %42
+         %44 = OpVectorShuffle %v2float %43 %43 1 0
+         %45 = OpCompositeExtract %float %44 0
+         %41 = OpExtInst %float %36 FAbs %45
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_builtin.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_builtin.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.glsl
similarity index 63%
rename from test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.glsl
index 1d5f133..452c603 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.glsl
@@ -2,8 +2,10 @@
 
 struct S {
   int before;
+  uint pad;
   mat2 m;
   int after;
+  uint pad_1;
 };
 
 struct S_std140 {
@@ -15,7 +17,7 @@
   uint pad_1;
 };
 
-layout(binding = 0, std140) uniform u_block_ubo {
+layout(binding = 0, std140) uniform u_block_std140_ubo {
   S_std140 inner[4];
 } u;
 
@@ -35,12 +37,11 @@
 }
 
 S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, mat2(val.m_0, val.m_1), val.after);
-  return tint_symbol;
+  return S(val.before, val.pad, mat2(val.m_0, val.m_1), val.after, val.pad_1);
 }
 
 S[4] conv_arr_4_S(S_std140 val[4]) {
-  S arr[4] = S[4](S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0));
+  S arr[4] = S[4](S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u));
   {
     for(uint i = 0u; (i < 4u); i = (i + 1u)) {
       arr[i] = conv_S(val[i]);
@@ -49,14 +50,14 @@
   return arr;
 }
 
-mat2 load_u_2_m() {
+mat2 load_u_inner_2_m() {
   return mat2(u.inner[2u].m_0, u.inner[2u].m_1);
 }
 
 void f() {
   a(conv_arr_4_S(u.inner));
   b(conv_S(u.inner[2u]));
-  c(load_u_2_m());
+  c(load_u_inner_2_m());
   d(u.inner[0u].m_1.yx);
   e(u.inner[0u].m_1.yx[0u]);
 }
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.spvasm
similarity index 78%
rename from test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.spvasm
index 52b17ad..627852b 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 115
+; Bound: 119
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -36,10 +36,10 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -61,9 +61,9 @@
        %uint = OpTypeInt 32 0
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
        %void = OpTypeVoid
 %mat2v2float = OpTypeMatrix %v2float 2
           %S = OpTypeStruct %int %mat2v2float %int
@@ -88,10 +88,10 @@
          %80 = OpTypeFunction %mat2v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
-%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
-         %91 = OpTypeFunction %void
-%_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
 %_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+         %96 = OpTypeFunction %void
+%_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
           %a = OpFunction %void None %11
         %a_1 = OpFunctionParameter %_arr_S_uint_4
          %18 = OpLabel
@@ -165,35 +165,36 @@
          %79 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %79
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat2v2float None %80
+%load_u_inner_2_m = OpFunction %mat2v2float None %80
          %82 = OpLabel
-         %86 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %87 = OpLoad %v2float %86
-         %88 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %89 = OpLoad %v2float %88
-         %90 = OpCompositeConstruct %mat2v2float %87 %89
-               OpReturnValue %90
+         %87 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %90 = OpAccessChain %_ptr_Uniform_v2float %87 %uint_1
+         %91 = OpLoad %v2float %90
+         %93 = OpAccessChain %_ptr_Uniform_v2float %87 %uint_2
+         %94 = OpLoad %v2float %93
+         %95 = OpCompositeConstruct %mat2v2float %91 %94
+               OpReturnValue %95
                OpFunctionEnd
-          %f = OpFunction %void None %91
-         %93 = OpLabel
-         %97 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-         %98 = OpLoad %_arr_S_std140_uint_4 %97
-         %95 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %98
-         %94 = OpFunctionCall %void %a %95
-        %102 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-        %103 = OpLoad %S_std140 %102
-        %100 = OpFunctionCall %S %conv_S %103
-         %99 = OpFunctionCall %void %b %100
-        %105 = OpFunctionCall %mat2v2float %load_u_2_m
-        %104 = OpFunctionCall %void %c %105
-        %107 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %54 %uint_2
-        %108 = OpLoad %v2float %107
-        %109 = OpVectorShuffle %v2float %108 %108 1 0
-        %106 = OpFunctionCall %void %d %109
+          %f = OpFunction %void None %96
+         %98 = OpLabel
+        %102 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+        %103 = OpLoad %_arr_S_std140_uint_4 %102
+        %100 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %103
+         %99 = OpFunctionCall %void %a %100
+        %106 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+        %107 = OpLoad %S_std140 %106
+        %105 = OpFunctionCall %S %conv_S %107
+        %104 = OpFunctionCall %void %b %105
+        %109 = OpFunctionCall %mat2v2float %load_u_inner_2_m
+        %108 = OpFunctionCall %void %c %109
         %111 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %54 %uint_2
         %112 = OpLoad %v2float %111
         %113 = OpVectorShuffle %v2float %112 %112 1 0
-        %114 = OpCompositeExtract %float %113 0
-        %110 = OpFunctionCall %void %e %114
+        %110 = OpFunctionCall %void %d %113
+        %115 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %54 %uint_2
+        %116 = OpLoad %v2float %115
+        %117 = OpVectorShuffle %v2float %116 %116 1 0
+        %118 = OpCompositeExtract %float %117 0
+        %114 = OpFunctionCall %void %e %118
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_fn.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_fn.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.glsl
new file mode 100644
index 0000000..ce7f2ce
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.glsl
@@ -0,0 +1,54 @@
+#version 310 es
+
+struct S {
+  int before;
+  uint pad;
+  mat2 m;
+  int after;
+  uint pad_1;
+};
+
+struct S_std140 {
+  int before;
+  uint pad;
+  vec2 m_0;
+  vec2 m_1;
+  int after;
+  uint pad_1;
+};
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  S_std140 inner[4];
+} u;
+
+S p[4] = S[4](S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u));
+S conv_S(S_std140 val) {
+  return S(val.before, val.pad, mat2(val.m_0, val.m_1), val.after, val.pad_1);
+}
+
+S[4] conv_arr_4_S(S_std140 val[4]) {
+  S arr[4] = S[4](S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u));
+  {
+    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = conv_S(val[i]);
+    }
+  }
+  return arr;
+}
+
+mat2 load_u_inner_2_m() {
+  return mat2(u.inner[2u].m_0, u.inner[2u].m_1);
+}
+
+void f() {
+  p = conv_arr_4_S(u.inner);
+  p[1] = conv_S(u.inner[2u]);
+  p[3].m = load_u_inner_2_m();
+  p[1].m[0] = u.inner[0u].m_1.yx;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.spvasm
similarity index 74%
rename from test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.spvasm
index ecca4ee..118e476 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 97
+; Bound: 101
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -27,10 +27,10 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -52,9 +52,9 @@
        %uint = OpTypeInt 32 0
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat2v2float = OpTypeMatrix %v2float 2
           %S = OpTypeStruct %int %mat2v2float %int
 %_arr_S_uint_4 = OpTypeArray %S %uint_4
@@ -75,16 +75,16 @@
          %61 = OpTypeFunction %mat2v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
        %void = OpTypeVoid
-         %72 = OpTypeFunction %void
+         %77 = OpTypeFunction %void
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
       %int_1 = OpConstant %int 1
 %_ptr_Private_S = OpTypePointer Private %S
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
       %int_3 = OpConstant %int 3
 %_ptr_Private_mat2v2float = OpTypePointer Private %mat2v2float
-         %91 = OpConstantNull %int
+         %95 = OpConstantNull %int
 %_ptr_Private_v2float = OpTypePointer Private %v2float
      %conv_S = OpFunction %S None %17
         %val = OpFunctionParameter %S_std140
@@ -134,33 +134,34 @@
          %60 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %60
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat2v2float None %61
+%load_u_inner_2_m = OpFunction %mat2v2float None %61
          %63 = OpLabel
-         %67 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %68 = OpLoad %v2float %67
-         %69 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %70 = OpLoad %v2float %69
-         %71 = OpCompositeConstruct %mat2v2float %68 %70
-               OpReturnValue %71
+         %68 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %71 = OpAccessChain %_ptr_Uniform_v2float %68 %uint_1
+         %72 = OpLoad %v2float %71
+         %74 = OpAccessChain %_ptr_Uniform_v2float %68 %uint_2
+         %75 = OpLoad %v2float %74
+         %76 = OpCompositeConstruct %mat2v2float %72 %75
+               OpReturnValue %76
                OpFunctionEnd
-          %f = OpFunction %void None %72
-         %75 = OpLabel
-         %78 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-         %79 = OpLoad %_arr_S_std140_uint_4 %78
-         %76 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %79
-               OpStore %p %76
-         %82 = OpAccessChain %_ptr_Private_S %p %int_1
-         %85 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-         %86 = OpLoad %S_std140 %85
-         %83 = OpFunctionCall %S %conv_S %86
-               OpStore %82 %83
-         %89 = OpAccessChain %_ptr_Private_mat2v2float %p %int_3 %uint_1
-         %90 = OpFunctionCall %mat2v2float %load_u_2_m
-               OpStore %89 %90
-         %93 = OpAccessChain %_ptr_Private_v2float %p %int_1 %uint_1 %91
-         %94 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %35 %uint_2
-         %95 = OpLoad %v2float %94
-         %96 = OpVectorShuffle %v2float %95 %95 1 0
-               OpStore %93 %96
+          %f = OpFunction %void None %77
+         %80 = OpLabel
+         %83 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+         %84 = OpLoad %_arr_S_std140_uint_4 %83
+         %81 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %84
+               OpStore %p %81
+         %87 = OpAccessChain %_ptr_Private_S %p %int_1
+         %89 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %90 = OpLoad %S_std140 %89
+         %88 = OpFunctionCall %S %conv_S %90
+               OpStore %87 %88
+         %93 = OpAccessChain %_ptr_Private_mat2v2float %p %int_3 %uint_1
+         %94 = OpFunctionCall %mat2v2float %load_u_inner_2_m
+               OpStore %93 %94
+         %97 = OpAccessChain %_ptr_Private_v2float %p %int_1 %uint_1 %95
+         %98 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %35 %uint_2
+         %99 = OpLoad %v2float %98
+        %100 = OpVectorShuffle %v2float %99 %99 1 0
+               OpStore %97 %100
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_private.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_private.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.glsl
similarity index 75%
rename from test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.glsl
index b6b2c36..0fdf832 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.glsl
@@ -10,24 +10,23 @@
 
 struct S_std140 {
   int before;
-  uint pad_2;
+  uint pad;
   vec2 m_0;
   vec2 m_1;
   int after;
-  uint pad_3;
+  uint pad_1;
 };
 
-layout(binding = 0, std140) uniform u_block_ubo {
+layout(binding = 0, std140) uniform u_block_std140_ubo {
   S_std140 inner[4];
 } u;
 
-layout(binding = 1, std430) buffer s_block_ssbo {
+layout(binding = 1, std430) buffer u_block_ssbo {
   S inner[4];
 } s;
 
 S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, 0u, mat2(val.m_0, val.m_1), val.after, 0u);
-  return tint_symbol;
+  return S(val.before, val.pad, mat2(val.m_0, val.m_1), val.after, val.pad_1);
 }
 
 S[4] conv_arr_4_S(S_std140 val[4]) {
@@ -40,14 +39,14 @@
   return arr;
 }
 
-mat2 load_u_2_m() {
+mat2 load_u_inner_2_m() {
   return mat2(u.inner[2u].m_0, u.inner[2u].m_1);
 }
 
 void f() {
   s.inner = conv_arr_4_S(u.inner);
   s.inner[1] = conv_S(u.inner[2u]);
-  s.inner[3].m = load_u_2_m();
+  s.inner[3].m = load_u_inner_2_m();
   s.inner[1].m[0] = u.inner[0u].m_1.yx;
 }
 
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.spvasm
similarity index 72%
rename from test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.spvasm
index 03f28a7..8769096 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.spvasm
@@ -1,22 +1,22 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 100
+; Bound: 104
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
                OpMemberName %S_std140 2 "m_1"
                OpMemberName %S_std140 3 "after"
                OpName %u "u"
-               OpName %s_block "s_block"
-               OpMemberName %s_block 0 "inner"
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
                OpName %S "S"
                OpMemberName %S 0 "before"
                OpMemberName %S 1 "m"
@@ -29,10 +29,10 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -41,8 +41,8 @@
                OpDecorate %u NonWritable
                OpDecorate %u DescriptorSet 0
                OpDecorate %u Binding 0
-               OpDecorate %s_block Block
-               OpMemberDecorate %s_block 0 Offset 0
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
                OpMemberDecorate %S 0 Offset 0
                OpMemberDecorate %S 1 Offset 8
                OpMemberDecorate %S 1 ColMajor
@@ -58,15 +58,15 @@
        %uint = OpTypeInt 32 0
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat2v2float = OpTypeMatrix %v2float 2
           %S = OpTypeStruct %int %mat2v2float %int
 %_arr_S_uint_4 = OpTypeArray %S %uint_4
-    %s_block = OpTypeStruct %_arr_S_uint_4
-%_ptr_StorageBuffer_s_block = OpTypePointer StorageBuffer %s_block
-          %s = OpVariable %_ptr_StorageBuffer_s_block StorageBuffer
+    %u_block = OpTypeStruct %_arr_S_uint_4
+%_ptr_StorageBuffer_u_block = OpTypePointer StorageBuffer %u_block
+          %s = OpVariable %_ptr_StorageBuffer_u_block StorageBuffer
          %17 = OpTypeFunction %S %S_std140
          %27 = OpTypeFunction %_arr_S_uint_4 %_arr_S_std140_uint_4
 %_ptr_Function__arr_S_uint_4 = OpTypePointer Function %_arr_S_uint_4
@@ -82,17 +82,17 @@
          %62 = OpTypeFunction %mat2v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
        %void = OpTypeVoid
-         %73 = OpTypeFunction %void
+         %78 = OpTypeFunction %void
 %_ptr_StorageBuffer__arr_S_uint_4 = OpTypePointer StorageBuffer %_arr_S_uint_4
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
       %int_1 = OpConstant %int 1
 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
       %int_3 = OpConstant %int 3
 %_ptr_StorageBuffer_mat2v2float = OpTypePointer StorageBuffer %mat2v2float
-         %94 = OpConstantNull %int
+         %98 = OpConstantNull %int
 %_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
      %conv_S = OpFunction %S None %17
         %val = OpFunctionParameter %S_std140
@@ -142,34 +142,35 @@
          %61 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %61
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat2v2float None %62
+%load_u_inner_2_m = OpFunction %mat2v2float None %62
          %64 = OpLabel
-         %68 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %69 = OpLoad %v2float %68
-         %70 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %71 = OpLoad %v2float %70
-         %72 = OpCompositeConstruct %mat2v2float %69 %71
-               OpReturnValue %72
+         %69 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %72 = OpAccessChain %_ptr_Uniform_v2float %69 %uint_1
+         %73 = OpLoad %v2float %72
+         %75 = OpAccessChain %_ptr_Uniform_v2float %69 %uint_2
+         %76 = OpLoad %v2float %75
+         %77 = OpCompositeConstruct %mat2v2float %73 %76
+               OpReturnValue %77
                OpFunctionEnd
-          %f = OpFunction %void None %73
-         %76 = OpLabel
-         %78 = OpAccessChain %_ptr_StorageBuffer__arr_S_uint_4 %s %uint_0
-         %81 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-         %82 = OpLoad %_arr_S_std140_uint_4 %81
-         %79 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %82
-               OpStore %78 %79
-         %85 = OpAccessChain %_ptr_StorageBuffer_S %s %uint_0 %int_1
-         %88 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-         %89 = OpLoad %S_std140 %88
-         %86 = OpFunctionCall %S %conv_S %89
-               OpStore %85 %86
-         %92 = OpAccessChain %_ptr_StorageBuffer_mat2v2float %s %uint_0 %int_3 %uint_1
-         %93 = OpFunctionCall %mat2v2float %load_u_2_m
-               OpStore %92 %93
-         %96 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1 %uint_1 %94
-         %97 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %36 %uint_2
-         %98 = OpLoad %v2float %97
-         %99 = OpVectorShuffle %v2float %98 %98 1 0
-               OpStore %96 %99
+          %f = OpFunction %void None %78
+         %81 = OpLabel
+         %83 = OpAccessChain %_ptr_StorageBuffer__arr_S_uint_4 %s %uint_0
+         %86 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+         %87 = OpLoad %_arr_S_std140_uint_4 %86
+         %84 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %87
+               OpStore %83 %84
+         %90 = OpAccessChain %_ptr_StorageBuffer_S %s %uint_0 %int_1
+         %92 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %93 = OpLoad %S_std140 %92
+         %91 = OpFunctionCall %S %conv_S %93
+               OpStore %90 %91
+         %96 = OpAccessChain %_ptr_StorageBuffer_mat2v2float %s %uint_0 %int_3 %uint_1
+         %97 = OpFunctionCall %mat2v2float %load_u_inner_2_m
+               OpStore %96 %97
+        %100 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1 %uint_1 %98
+        %101 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %36 %uint_2
+        %102 = OpLoad %v2float %101
+        %103 = OpVectorShuffle %v2float %102 %102 1 0
+               OpStore %100 %103
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_storage.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_storage.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.glsl
similarity index 61%
rename from test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.glsl
index b75753c..9204f46 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.glsl
@@ -2,8 +2,10 @@
 
 struct S {
   int before;
+  uint pad;
   mat2 m;
   int after;
+  uint pad_1;
 };
 
 struct S_std140 {
@@ -15,18 +17,17 @@
   uint pad_1;
 };
 
-layout(binding = 0, std140) uniform u_block_ubo {
+layout(binding = 0, std140) uniform u_block_std140_ubo {
   S_std140 inner[4];
 } u;
 
 shared S w[4];
 S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, mat2(val.m_0, val.m_1), val.after);
-  return tint_symbol;
+  return S(val.before, val.pad, mat2(val.m_0, val.m_1), val.after, val.pad_1);
 }
 
 S[4] conv_arr_4_S(S_std140 val[4]) {
-  S arr[4] = S[4](S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0), S(0, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0));
+  S arr[4] = S[4](S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat2(0.0f, 0.0f, 0.0f, 0.0f), 0, 0u));
   {
     for(uint i = 0u; (i < 4u); i = (i + 1u)) {
       arr[i] = conv_S(val[i]);
@@ -35,7 +36,7 @@
   return arr;
 }
 
-mat2 load_u_2_m() {
+mat2 load_u_inner_2_m() {
   return mat2(u.inner[2u].m_0, u.inner[2u].m_1);
 }
 
@@ -43,14 +44,14 @@
   {
     for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
       uint i = idx;
-      S tint_symbol_1 = S(0, mat2(vec2(0.0f), vec2(0.0f)), 0);
-      w[i] = tint_symbol_1;
+      S tint_symbol = S(0, 0u, mat2(vec2(0.0f), vec2(0.0f)), 0, 0u);
+      w[i] = tint_symbol;
     }
   }
   barrier();
   w = conv_arr_4_S(u.inner);
   w[1] = conv_S(u.inner[2u]);
-  w[3].m = load_u_2_m();
+  w[3].m = load_u_inner_2_m();
   w[1].m[0] = u.inner[0u].m_1.yx;
 }
 
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.spvasm
similarity index 68%
rename from test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.spvasm
index 305e172..5e253f9 100644
--- a/test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.spvasm
@@ -1,15 +1,15 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 122
+; Bound: 126
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f" %local_invocation_index_1
                OpExecutionMode %f LocalSize 1 1 1
                OpName %local_invocation_index_1 "local_invocation_index_1"
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -28,14 +28,14 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f_inner "f_inner"
                OpName %local_invocation_index "local_invocation_index"
                OpName %idx "idx"
                OpName %f "f"
                OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -59,9 +59,9 @@
    %S_std140 = OpTypeStruct %int %v2float %v2float %int
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat2v2float = OpTypeMatrix %v2float 2
           %S = OpTypeStruct %int %mat2v2float %int
 %_arr_S_uint_4 = OpTypeArray %S %uint_4
@@ -82,20 +82,20 @@
          %63 = OpTypeFunction %mat2v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
        %void = OpTypeVoid
-         %74 = OpTypeFunction %void %uint
+         %79 = OpTypeFunction %void %uint
 %_ptr_Workgroup_S = OpTypePointer Workgroup %S
-         %92 = OpConstantNull %S
+         %97 = OpConstantNull %S
    %uint_264 = OpConstant %uint 264
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
       %int_1 = OpConstant %int 1
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
       %int_3 = OpConstant %int 3
 %_ptr_Workgroup_mat2v2float = OpTypePointer Workgroup %mat2v2float
-        %111 = OpConstantNull %int
+        %115 = OpConstantNull %int
 %_ptr_Workgroup_v2float = OpTypePointer Workgroup %v2float
-        %117 = OpTypeFunction %void
+        %121 = OpTypeFunction %void
      %conv_S = OpFunction %S None %18
         %val = OpFunctionParameter %S_std140
          %21 = OpLabel
@@ -144,66 +144,67 @@
          %62 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %62
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat2v2float None %63
+%load_u_inner_2_m = OpFunction %mat2v2float None %63
          %65 = OpLabel
-         %69 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %70 = OpLoad %v2float %69
-         %71 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %72 = OpLoad %v2float %71
-         %73 = OpCompositeConstruct %mat2v2float %70 %72
-               OpReturnValue %73
+         %70 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %73 = OpAccessChain %_ptr_Uniform_v2float %70 %uint_1
+         %74 = OpLoad %v2float %73
+         %76 = OpAccessChain %_ptr_Uniform_v2float %70 %uint_2
+         %77 = OpLoad %v2float %76
+         %78 = OpCompositeConstruct %mat2v2float %74 %77
+               OpReturnValue %78
                OpFunctionEnd
-    %f_inner = OpFunction %void None %74
+    %f_inner = OpFunction %void None %79
 %local_invocation_index = OpFunctionParameter %uint
-         %78 = OpLabel
+         %83 = OpLabel
         %idx = OpVariable %_ptr_Function_uint Function %37
                OpStore %idx %local_invocation_index
-               OpBranch %80
-         %80 = OpLabel
-               OpLoopMerge %81 %82 None
-               OpBranch %83
-         %83 = OpLabel
-         %85 = OpLoad %uint %idx
-         %86 = OpULessThan %bool %85 %uint_4
-         %84 = OpLogicalNot %bool %86
-               OpSelectionMerge %87 None
-               OpBranchConditional %84 %88 %87
+               OpBranch %85
+         %85 = OpLabel
+               OpLoopMerge %86 %87 None
+               OpBranch %88
          %88 = OpLabel
-               OpBranch %81
+         %90 = OpLoad %uint %idx
+         %91 = OpULessThan %bool %90 %uint_4
+         %89 = OpLogicalNot %bool %91
+               OpSelectionMerge %92 None
+               OpBranchConditional %89 %93 %92
+         %93 = OpLabel
+               OpBranch %86
+         %92 = OpLabel
+         %94 = OpLoad %uint %idx
+         %96 = OpAccessChain %_ptr_Workgroup_S %w %94
+               OpStore %96 %97
+               OpBranch %87
          %87 = OpLabel
-         %89 = OpLoad %uint %idx
-         %91 = OpAccessChain %_ptr_Workgroup_S %w %89
-               OpStore %91 %92
-               OpBranch %82
-         %82 = OpLabel
-         %93 = OpLoad %uint %idx
-         %94 = OpIAdd %uint %93 %uint_1
-               OpStore %idx %94
-               OpBranch %80
-         %81 = OpLabel
+         %98 = OpLoad %uint %idx
+         %99 = OpIAdd %uint %98 %uint_1
+               OpStore %idx %99
+               OpBranch %85
+         %86 = OpLabel
                OpControlBarrier %uint_2 %uint_2 %uint_264
-         %99 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-        %100 = OpLoad %_arr_S_std140_uint_4 %99
-         %97 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %100
-               OpStore %w %97
-        %102 = OpAccessChain %_ptr_Workgroup_S %w %int_1
-        %105 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-        %106 = OpLoad %S_std140 %105
-        %103 = OpFunctionCall %S %conv_S %106
-               OpStore %102 %103
-        %109 = OpAccessChain %_ptr_Workgroup_mat2v2float %w %int_3 %uint_1
-        %110 = OpFunctionCall %mat2v2float %load_u_2_m
-               OpStore %109 %110
-        %113 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1 %uint_1 %111
-        %114 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %37 %uint_2
-        %115 = OpLoad %v2float %114
-        %116 = OpVectorShuffle %v2float %115 %115 1 0
-               OpStore %113 %116
+        %104 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+        %105 = OpLoad %_arr_S_std140_uint_4 %104
+        %102 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %105
+               OpStore %w %102
+        %107 = OpAccessChain %_ptr_Workgroup_S %w %int_1
+        %109 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+        %110 = OpLoad %S_std140 %109
+        %108 = OpFunctionCall %S %conv_S %110
+               OpStore %107 %108
+        %113 = OpAccessChain %_ptr_Workgroup_mat2v2float %w %int_3 %uint_1
+        %114 = OpFunctionCall %mat2v2float %load_u_inner_2_m
+               OpStore %113 %114
+        %117 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1 %uint_1 %115
+        %118 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %37 %uint_2
+        %119 = OpLoad %v2float %118
+        %120 = OpVectorShuffle %v2float %119 %119 1 0
+               OpStore %117 %120
                OpReturn
                OpFunctionEnd
-          %f = OpFunction %void None %117
-        %119 = OpLabel
-        %121 = OpLoad %uint %local_invocation_index_1
-        %120 = OpFunctionCall %void %f_inner %121
+          %f = OpFunction %void None %121
+        %123 = OpLabel
+        %125 = OpLoad %uint %local_invocation_index_1
+        %124 = OpFunctionCall %void %f_inner %125
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat2x2/to_workgroup.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat2x2/to_workgroup.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl
index 86bae97..92c91a8 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl
@@ -13,8 +13,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
-
   let p_a           = &a;
   let p_a_i         = &((*p_a)[i()]);
   let p_a_i_a       = &((*p_a_i).a);
diff --git a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
similarity index 99%
rename from test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
index 014b25d..c1513d2 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -59,7 +59,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const int p_a_i_save = i();
   const int p_a_i_a_i_save = i();
   const int p_a_i_a_i_m_i_save = i();
diff --git a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
similarity index 99%
rename from test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
index 014b25d..c1513d2 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -59,7 +59,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const int p_a_i_save = i();
   const int p_a_i_a_i_save = i();
   const int p_a_i_a_i_m_i_save = i();
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..accf517
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,151 @@
+#version 310 es
+
+struct Inner {
+  mat3x2 m;
+  uint pad;
+  uint pad_1;
+  uint pad_2;
+  uint pad_3;
+  uint pad_4;
+  uint pad_5;
+  uint pad_6;
+  uint pad_7;
+  uint pad_8;
+  uint pad_9;
+};
+
+struct Inner_std140 {
+  vec2 m_0;
+  vec2 m_1;
+  vec2 m_2;
+  uint pad;
+  uint pad_1;
+  uint pad_2;
+  uint pad_3;
+  uint pad_4;
+  uint pad_5;
+  uint pad_6;
+  uint pad_7;
+  uint pad_8;
+  uint pad_9;
+};
+
+struct Outer {
+  Inner a[4];
+};
+
+struct Outer_std140 {
+  Inner_std140 a[4];
+};
+
+layout(binding = 0, std140) uniform a_block_std140_ubo {
+  Outer_std140 inner[4];
+} a;
+
+int counter = 0;
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+Inner conv_Inner(Inner_std140 val) {
+  return Inner(mat3x2(val.m_0, val.m_1, val.m_2), val.pad, val.pad_1, val.pad_2, val.pad_3, val.pad_4, val.pad_5, val.pad_6, val.pad_7, val.pad_8, val.pad_9);
+}
+
+Inner[4] conv_arr_4_Inner(Inner_std140 val[4]) {
+  Inner arr[4] = Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u));
+  {
+    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = conv_Inner(val[i]);
+    }
+  }
+  return arr;
+}
+
+Outer conv_Outer(Outer_std140 val) {
+  return Outer(conv_arr_4_Inner(val.a));
+}
+
+Outer[4] conv_arr_4_Outer(Outer_std140 val[4]) {
+  Outer arr[4] = Outer[4](Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u))));
+  {
+    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = conv_Outer(val[i]);
+    }
+  }
+  return arr;
+}
+
+mat3x2 load_a_inner_p0_a_p1_m(uint p0, uint p1) {
+  uint s_save = p0;
+  uint s_save_1 = p1;
+  return mat3x2(a.inner[s_save].a[s_save_1].m_0, a.inner[s_save].a[s_save_1].m_1, a.inner[s_save].a[s_save_1].m_2);
+}
+
+vec2 load_a_inner_p0_a_p1_m_p2(uint p0, uint p1, uint p2) {
+  switch(p2) {
+    case 0u: {
+      return a.inner[p0].a[p1].m_0;
+      break;
+    }
+    case 1u: {
+      return a.inner[p0].a[p1].m_1;
+      break;
+    }
+    case 2u: {
+      return a.inner[p0].a[p1].m_2;
+      break;
+    }
+    default: {
+      return vec2(0.0f);
+      break;
+    }
+  }
+}
+
+float load_a_inner_p0_a_p1_m_p2_p3(uint p0, uint p1, uint p2, uint p3) {
+  switch(p2) {
+    case 0u: {
+      return a.inner[p0].a[p1].m_0[p3];
+      break;
+    }
+    case 1u: {
+      return a.inner[p0].a[p1].m_1[p3];
+      break;
+    }
+    case 2u: {
+      return a.inner[p0].a[p1].m_2[p3];
+      break;
+    }
+    default: {
+      return 0.0f;
+      break;
+    }
+  }
+}
+
+void f() {
+  Outer p_a[4] = conv_arr_4_Outer(a.inner);
+  int tint_symbol = i();
+  Outer p_a_i = conv_Outer(a.inner[tint_symbol]);
+  Inner p_a_i_a[4] = conv_arr_4_Inner(a.inner[tint_symbol].a);
+  int tint_symbol_1 = i();
+  Inner p_a_i_a_i = conv_Inner(a.inner[tint_symbol].a[tint_symbol_1]);
+  mat3x2 p_a_i_a_i_m = load_a_inner_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
+  int tint_symbol_2 = i();
+  vec2 p_a_i_a_i_m_i = load_a_inner_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
+  Outer l_a[4] = conv_arr_4_Outer(a.inner);
+  Outer l_a_i = conv_Outer(a.inner[tint_symbol]);
+  Inner l_a_i_a[4] = conv_arr_4_Inner(a.inner[tint_symbol].a);
+  Inner l_a_i_a_i = conv_Inner(a.inner[tint_symbol].a[tint_symbol_1]);
+  mat3x2 l_a_i_a_i_m = load_a_inner_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
+  vec2 l_a_i_a_i_m_i = load_a_inner_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
+  int tint_symbol_3 = i();
+  float l_a_i_a_i_m_i_i = load_a_inner_p0_a_p1_m_p2_p3(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2), uint(tint_symbol_3));
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.msl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.msl
index 572eb1c..02f86ed 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.msl
@@ -30,7 +30,6 @@
 }
 
 kernel void f(const constant tint_array<Outer, 4>* tint_symbol_5 [[buffer(0)]]) {
-  int const I = 1;
   int const tint_symbol = i();
   int const p_a_i_save = tint_symbol;
   int const tint_symbol_1 = i();
diff --git a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.spvasm
similarity index 62%
rename from test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.spvasm
index 726683f..bb1c350 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 218
+; Bound: 204
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %a_block "a_block"
-               OpMemberName %a_block 0 "inner"
+               OpName %a_block_std140 "a_block_std140"
+               OpMemberName %a_block_std140 0 "inner"
                OpName %Outer_std140 "Outer_std140"
                OpMemberName %Outer_std140 0 "a"
                OpName %Inner_std140 "Inner_std140"
@@ -26,7 +26,7 @@
                OpName %val_0 "val"
                OpName %arr "arr"
                OpName %i_0 "i"
-               OpName %var_for_index "var_for_index"
+               OpName %var_for_index_1 "var_for_index_1"
                OpName %Outer "Outer"
                OpMemberName %Outer 0 "a"
                OpName %conv_Outer "conv_Outer"
@@ -35,22 +35,22 @@
                OpName %val_2 "val"
                OpName %arr_0 "arr"
                OpName %i_1 "i"
-               OpName %var_for_index_1 "var_for_index_1"
-               OpName %load_a_p0_a_p1_m "load_a_p0_a_p1_m"
+               OpName %var_for_index "var_for_index"
+               OpName %load_a_inner_p0_a_p1_m "load_a_inner_p0_a_p1_m"
                OpName %p0 "p0"
                OpName %p1 "p1"
-               OpName %load_a_p0_a_p1_m_p2 "load_a_p0_a_p1_m_p2"
+               OpName %load_a_inner_p0_a_p1_m_p2 "load_a_inner_p0_a_p1_m_p2"
                OpName %p0_0 "p0"
                OpName %p1_0 "p1"
                OpName %p2 "p2"
-               OpName %load_a_p0_a_p1_m_p2_p3 "load_a_p0_a_p1_m_p2_p3"
+               OpName %load_a_inner_p0_a_p1_m_p2_p3 "load_a_inner_p0_a_p1_m_p2_p3"
                OpName %p0_1 "p0"
                OpName %p1_1 "p1"
                OpName %p2_0 "p2"
                OpName %p3 "p3"
                OpName %f "f"
-               OpDecorate %a_block Block
-               OpMemberDecorate %a_block 0 Offset 0
+               OpDecorate %a_block_std140 Block
+               OpMemberDecorate %a_block_std140 0 Offset 0
                OpMemberDecorate %Outer_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 1 Offset 8
@@ -74,9 +74,9 @@
 %_arr_Inner_std140_uint_4 = OpTypeArray %Inner_std140 %uint_4
 %Outer_std140 = OpTypeStruct %_arr_Inner_std140_uint_4
 %_arr_Outer_std140_uint_4 = OpTypeArray %Outer_std140 %uint_4
-    %a_block = OpTypeStruct %_arr_Outer_std140_uint_4
-%_ptr_Uniform_a_block = OpTypePointer Uniform %a_block
-          %a = OpVariable %_ptr_Uniform_a_block Uniform
+%a_block_std140 = OpTypeStruct %_arr_Outer_std140_uint_4
+%_ptr_Uniform_a_block_std140 = OpTypePointer Uniform %a_block_std140
+          %a = OpVariable %_ptr_Uniform_a_block_std140 Uniform
         %int = OpTypeInt 32 1
          %13 = OpConstantNull %int
 %_ptr_Private_int = OpTypePointer Private %int
@@ -110,19 +110,19 @@
 %_ptr_Function_Outer_std140 = OpTypePointer Function %Outer_std140
         %110 = OpTypeFunction %mat3v2float %uint %uint
      %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_2 = OpConstant %uint 2
-        %125 = OpTypeFunction %v2float %uint %uint %uint
-        %142 = OpConstantNull %v2float
-        %143 = OpTypeFunction %float %uint %uint %uint %uint
+        %131 = OpTypeFunction %v2float %uint %uint %uint
+        %148 = OpConstantNull %v2float
+        %149 = OpTypeFunction %float %uint %uint %uint %uint
 %_ptr_Uniform_float = OpTypePointer Uniform %float
-        %162 = OpConstantNull %float
+        %168 = OpConstantNull %float
        %void = OpTypeVoid
-        %163 = OpTypeFunction %void
+        %169 = OpTypeFunction %void
 %_ptr_Uniform__arr_Outer_std140_uint_4 = OpTypePointer Uniform %_arr_Outer_std140_uint_4
 %_ptr_Uniform_Outer_std140 = OpTypePointer Uniform %Outer_std140
 %_ptr_Uniform__arr_Inner_std140_uint_4 = OpTypePointer Uniform %_arr_Inner_std140_uint_4
-%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
           %i = OpFunction %int None %16
          %18 = OpLabel
          %19 = OpLoad %int %counter
@@ -146,7 +146,7 @@
          %38 = OpLabel
         %arr = OpVariable %_ptr_Function__arr_Inner_uint_4 Function %41
         %i_0 = OpVariable %_ptr_Function_uint Function %44
-%var_for_index = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %57
+%var_for_index_1 = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %57
                OpBranch %45
          %45 = OpLabel
                OpLoopMerge %46 %47 None
@@ -160,11 +160,11 @@
          %54 = OpLabel
                OpBranch %46
          %53 = OpLabel
-               OpStore %var_for_index %val_0
+               OpStore %var_for_index_1 %val_0
          %58 = OpLoad %uint %i_0
          %60 = OpAccessChain %_ptr_Function_Inner %arr %58
          %62 = OpLoad %uint %i_0
-         %64 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index %62
+         %64 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index_1 %62
          %65 = OpLoad %Inner_std140 %64
          %61 = OpFunctionCall %Inner %conv_Inner %65
                OpStore %60 %61
@@ -191,7 +191,7 @@
          %82 = OpLabel
       %arr_0 = OpVariable %_ptr_Function__arr_Outer_uint_4 Function %85
         %i_1 = OpVariable %_ptr_Function_uint Function %44
-%var_for_index_1 = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %98
+%var_for_index = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %98
                OpBranch %87
          %87 = OpLabel
                OpLoopMerge %88 %89 None
@@ -205,11 +205,11 @@
          %95 = OpLabel
                OpBranch %88
          %94 = OpLabel
-               OpStore %var_for_index_1 %val_2
+               OpStore %var_for_index %val_2
          %99 = OpLoad %uint %i_1
         %101 = OpAccessChain %_ptr_Function_Outer %arr_0 %99
         %103 = OpLoad %uint %i_1
-        %105 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index_1 %103
+        %105 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index %103
         %106 = OpLoad %Outer_std140 %105
         %102 = OpFunctionCall %Outer %conv_Outer %106
                OpStore %101 %102
@@ -223,116 +223,98 @@
         %109 = OpLoad %_arr_Outer_uint_4 %arr_0
                OpReturnValue %109
                OpFunctionEnd
-%load_a_p0_a_p1_m = OpFunction %mat3v2float None %110
+%load_a_inner_p0_a_p1_m = OpFunction %mat3v2float None %110
          %p0 = OpFunctionParameter %uint
          %p1 = OpFunctionParameter %uint
         %114 = OpLabel
-        %117 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0 %uint_0 %p1 %uint_0
-        %118 = OpLoad %v2float %117
-        %119 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0 %uint_0 %p1 %uint_1
-        %120 = OpLoad %v2float %119
-        %122 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0 %uint_0 %p1 %uint_2
-        %123 = OpLoad %v2float %122
-        %124 = OpCompositeConstruct %mat3v2float %118 %120 %123
-               OpReturnValue %124
+        %118 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %p0 %uint_0 %p1
+        %121 = OpAccessChain %_ptr_Uniform_v2float %118 %uint_0
+        %122 = OpLoad %v2float %121
+        %124 = OpAccessChain %_ptr_Uniform_v2float %118 %uint_1
+        %125 = OpLoad %v2float %124
+        %128 = OpAccessChain %_ptr_Uniform_v2float %118 %uint_2
+        %129 = OpLoad %v2float %128
+        %130 = OpCompositeConstruct %mat3v2float %122 %125 %129
+               OpReturnValue %130
                OpFunctionEnd
-%load_a_p0_a_p1_m_p2 = OpFunction %v2float None %125
+%load_a_inner_p0_a_p1_m_p2 = OpFunction %v2float None %131
        %p0_0 = OpFunctionParameter %uint
        %p1_0 = OpFunctionParameter %uint
          %p2 = OpFunctionParameter %uint
-        %130 = OpLabel
-               OpSelectionMerge %131 None
-               OpSwitch %p2 %132 0 %133 1 %134 2 %135
-        %133 = OpLabel
-        %136 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_0
-        %137 = OpLoad %v2float %136
-               OpReturnValue %137
-        %134 = OpLabel
-        %138 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_1
-        %139 = OpLoad %v2float %138
-               OpReturnValue %139
-        %135 = OpLabel
-        %140 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_2
-        %141 = OpLoad %v2float %140
-               OpReturnValue %141
-        %132 = OpLabel
-               OpReturnValue %142
-        %131 = OpLabel
-               OpReturnValue %142
+        %136 = OpLabel
+               OpSelectionMerge %137 None
+               OpSwitch %p2 %138 0 %139 1 %140 2 %141
+        %139 = OpLabel
+        %142 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_0
+        %143 = OpLoad %v2float %142
+               OpReturnValue %143
+        %140 = OpLabel
+        %144 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_1
+        %145 = OpLoad %v2float %144
+               OpReturnValue %145
+        %141 = OpLabel
+        %146 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_2
+        %147 = OpLoad %v2float %146
+               OpReturnValue %147
+        %138 = OpLabel
+               OpReturnValue %148
+        %137 = OpLabel
+               OpReturnValue %148
                OpFunctionEnd
-%load_a_p0_a_p1_m_p2_p3 = OpFunction %float None %143
+%load_a_inner_p0_a_p1_m_p2_p3 = OpFunction %float None %149
        %p0_1 = OpFunctionParameter %uint
        %p1_1 = OpFunctionParameter %uint
        %p2_0 = OpFunctionParameter %uint
          %p3 = OpFunctionParameter %uint
-        %149 = OpLabel
-               OpSelectionMerge %150 None
-               OpSwitch %p2_0 %151 0 %152 1 %153 2 %154
-        %152 = OpLabel
-        %156 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_0 %p3
-        %157 = OpLoad %float %156
-               OpReturnValue %157
-        %153 = OpLabel
-        %158 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_1 %p3
-        %159 = OpLoad %float %158
-               OpReturnValue %159
-        %154 = OpLabel
-        %160 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_2 %p3
-        %161 = OpLoad %float %160
-               OpReturnValue %161
-        %151 = OpLabel
-               OpReturnValue %162
-        %150 = OpLabel
-               OpReturnValue %162
+        %155 = OpLabel
+               OpSelectionMerge %156 None
+               OpSwitch %p2_0 %157 0 %158 1 %159 2 %160
+        %158 = OpLabel
+        %162 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_0 %p3
+        %163 = OpLoad %float %162
+               OpReturnValue %163
+        %159 = OpLabel
+        %164 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_1 %p3
+        %165 = OpLoad %float %164
+               OpReturnValue %165
+        %160 = OpLabel
+        %166 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_2 %p3
+        %167 = OpLoad %float %166
+               OpReturnValue %167
+        %157 = OpLabel
+               OpReturnValue %168
+        %156 = OpLabel
+               OpReturnValue %168
                OpFunctionEnd
-          %f = OpFunction %void None %163
-        %166 = OpLabel
-        %169 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %170 = OpLoad %_arr_Outer_std140_uint_4 %169
-        %167 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %170
-        %171 = OpFunctionCall %int %i
-        %174 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %171
-        %175 = OpLoad %Outer_std140 %174
-        %172 = OpFunctionCall %Outer %conv_Outer %175
-        %178 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %171 %uint_0
-        %179 = OpLoad %_arr_Inner_std140_uint_4 %178
-        %176 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %179
-        %180 = OpFunctionCall %int %i
-        %183 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %171 %uint_0 %180
-        %184 = OpLoad %Inner_std140 %183
-        %181 = OpFunctionCall %Inner %conv_Inner %184
-        %186 = OpBitcast %uint %171
-        %187 = OpBitcast %uint %180
-        %185 = OpFunctionCall %mat3v2float %load_a_p0_a_p1_m %186 %187
-        %188 = OpFunctionCall %int %i
-        %190 = OpBitcast %uint %171
-        %191 = OpBitcast %uint %180
-        %192 = OpBitcast %uint %188
-        %189 = OpFunctionCall %v2float %load_a_p0_a_p1_m_p2 %190 %191 %192
-        %194 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %195 = OpLoad %_arr_Outer_std140_uint_4 %194
-        %193 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %195
-        %197 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %171
-        %198 = OpLoad %Outer_std140 %197
-        %196 = OpFunctionCall %Outer %conv_Outer %198
-        %200 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %171 %uint_0
-        %201 = OpLoad %_arr_Inner_std140_uint_4 %200
-        %199 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %201
-        %203 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %171 %uint_0 %180
-        %204 = OpLoad %Inner_std140 %203
-        %202 = OpFunctionCall %Inner %conv_Inner %204
-        %206 = OpBitcast %uint %171
-        %207 = OpBitcast %uint %180
-        %205 = OpFunctionCall %mat3v2float %load_a_p0_a_p1_m %206 %207
-        %209 = OpBitcast %uint %171
-        %210 = OpBitcast %uint %180
-        %211 = OpBitcast %uint %188
-        %208 = OpFunctionCall %v2float %load_a_p0_a_p1_m_p2 %209 %210 %211
-        %212 = OpFunctionCall %int %i
-        %214 = OpBitcast %uint %171
-        %215 = OpBitcast %uint %180
-        %216 = OpBitcast %uint %188
-        %217 = OpBitcast %uint %212
-        %213 = OpFunctionCall %float %load_a_p0_a_p1_m_p2_p3 %214 %215 %216 %217
+          %f = OpFunction %void None %169
+        %172 = OpLabel
+        %173 = OpFunctionCall %int %i
+        %174 = OpFunctionCall %int %i
+        %175 = OpFunctionCall %int %i
+        %178 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
+        %179 = OpLoad %_arr_Outer_std140_uint_4 %178
+        %176 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %179
+        %182 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %173
+        %183 = OpLoad %Outer_std140 %182
+        %180 = OpFunctionCall %Outer %conv_Outer %183
+        %186 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %173 %uint_0
+        %187 = OpLoad %_arr_Inner_std140_uint_4 %186
+        %184 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %187
+        %189 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %173 %uint_0 %174
+        %190 = OpLoad %Inner_std140 %189
+        %188 = OpFunctionCall %Inner %conv_Inner %190
+        %192 = OpBitcast %uint %173
+        %193 = OpBitcast %uint %174
+        %191 = OpFunctionCall %mat3v2float %load_a_inner_p0_a_p1_m %192 %193
+        %195 = OpBitcast %uint %173
+        %196 = OpBitcast %uint %174
+        %197 = OpBitcast %uint %175
+        %194 = OpFunctionCall %v2float %load_a_inner_p0_a_p1_m_p2 %195 %196 %197
+        %198 = OpFunctionCall %int %i
+        %200 = OpBitcast %uint %173
+        %201 = OpBitcast %uint %174
+        %202 = OpBitcast %uint %175
+        %203 = OpBitcast %uint %198
+        %199 = OpFunctionCall %float %load_a_inner_p0_a_p1_m_p2_p3 %200 %201 %202 %203
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.wgsl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.wgsl
index aea4e87..2ee2439 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/dynamic_index_via_ptr.wgsl.expected.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/dynamic_index_via_ptr.wgsl.expected.wgsl
@@ -18,7 +18,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
   let p_a = &(a);
   let p_a_i = &((*(p_a))[i()]);
   let p_a_i_a = &((*(p_a_i)).a);
diff --git a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl
similarity index 97%
rename from test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl
index f52dbc0..d6e6f10 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl
@@ -10,8 +10,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
-
   let p_a = &a;
   let p_a_3 = &((*p_a)[3]);
   let p_a_3_a = &((*p_a_3).a);
diff --git a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
index 5c62062..3558206 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -53,7 +53,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const Outer l_a[4] = tint_symbol(a, 0u);
   const Outer l_a_3 = tint_symbol_1(a, 768u);
   const Inner l_a_3_a[4] = tint_symbol_2(a, 768u);
diff --git a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
similarity index 98%
copy from test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
copy to test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
index 5c62062..3558206 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -53,7 +53,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const Outer l_a[4] = tint_symbol(a, 0u);
   const Outer l_a_3 = tint_symbol_1(a, 768u);
   const Inner l_a_3_a[4] = tint_symbol_2(a, 768u);
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..2d72a86
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,97 @@
+#version 310 es
+
+struct Inner {
+  mat3x2 m;
+  uint pad;
+  uint pad_1;
+  uint pad_2;
+  uint pad_3;
+  uint pad_4;
+  uint pad_5;
+  uint pad_6;
+  uint pad_7;
+  uint pad_8;
+  uint pad_9;
+};
+
+struct Inner_std140 {
+  vec2 m_0;
+  vec2 m_1;
+  vec2 m_2;
+  uint pad;
+  uint pad_1;
+  uint pad_2;
+  uint pad_3;
+  uint pad_4;
+  uint pad_5;
+  uint pad_6;
+  uint pad_7;
+  uint pad_8;
+  uint pad_9;
+};
+
+struct Outer {
+  Inner a[4];
+};
+
+struct Outer_std140 {
+  Inner_std140 a[4];
+};
+
+layout(binding = 0, std140) uniform a_block_std140_ubo {
+  Outer_std140 inner[4];
+} a;
+
+Inner conv_Inner(Inner_std140 val) {
+  return Inner(mat3x2(val.m_0, val.m_1, val.m_2), val.pad, val.pad_1, val.pad_2, val.pad_3, val.pad_4, val.pad_5, val.pad_6, val.pad_7, val.pad_8, val.pad_9);
+}
+
+Inner[4] conv_arr_4_Inner(Inner_std140 val[4]) {
+  Inner arr[4] = Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u));
+  {
+    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = conv_Inner(val[i]);
+    }
+  }
+  return arr;
+}
+
+Outer conv_Outer(Outer_std140 val) {
+  return Outer(conv_arr_4_Inner(val.a));
+}
+
+Outer[4] conv_arr_4_Outer(Outer_std140 val[4]) {
+  Outer arr[4] = Outer[4](Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u))), Outer(Inner[4](Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u), Inner(mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u))));
+  {
+    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = conv_Outer(val[i]);
+    }
+  }
+  return arr;
+}
+
+mat3x2 load_a_inner_3_a_2_m() {
+  return mat3x2(a.inner[3u].a[2u].m_0, a.inner[3u].a[2u].m_1, a.inner[3u].a[2u].m_2);
+}
+
+void f() {
+  Outer p_a[4] = conv_arr_4_Outer(a.inner);
+  Outer p_a_3 = conv_Outer(a.inner[3u]);
+  Inner p_a_3_a[4] = conv_arr_4_Inner(a.inner[3u].a);
+  Inner p_a_3_a_2 = conv_Inner(a.inner[3u].a[2u]);
+  mat3x2 p_a_3_a_2_m = load_a_inner_3_a_2_m();
+  vec2 p_a_3_a_2_m_1 = a.inner[3u].a[2u].m_1;
+  Outer l_a[4] = conv_arr_4_Outer(a.inner);
+  Outer l_a_3 = conv_Outer(a.inner[3u]);
+  Inner l_a_3_a[4] = conv_arr_4_Inner(a.inner[3u].a);
+  Inner l_a_3_a_2 = conv_Inner(a.inner[3u].a[2u]);
+  mat3x2 l_a_3_a_2_m = load_a_inner_3_a_2_m();
+  vec2 l_a_3_a_2_m_1 = a.inner[3u].a[2u].m_1;
+  float l_a_3_a_2_m_1_0 = a.inner[3u].a[2u].m_1[0u];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.msl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.msl
index e9a1217..e475756 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.msl
@@ -24,7 +24,6 @@
 };
 
 kernel void f(const constant tint_array<Outer, 4>* tint_symbol [[buffer(0)]]) {
-  int const I = 1;
   tint_array<Outer, 4> const l_a = *(tint_symbol);
   Outer const l_a_3 = (*(tint_symbol))[3];
   tint_array<Inner, 4> const l_a_3_a = (*(tint_symbol))[3].a;
diff --git a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.spvasm
similarity index 71%
rename from test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.spvasm
index 63a09e6..cfe1926 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 156
+; Bound: 144
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %a_block "a_block"
-               OpMemberName %a_block 0 "inner"
+               OpName %a_block_std140 "a_block_std140"
+               OpMemberName %a_block_std140 0 "inner"
                OpName %Outer_std140 "Outer_std140"
                OpMemberName %Outer_std140 0 "a"
                OpName %Inner_std140 "Inner_std140"
@@ -24,7 +24,7 @@
                OpName %val_0 "val"
                OpName %arr "arr"
                OpName %i "i"
-               OpName %var_for_index "var_for_index"
+               OpName %var_for_index_1 "var_for_index_1"
                OpName %Outer "Outer"
                OpMemberName %Outer 0 "a"
                OpName %conv_Outer "conv_Outer"
@@ -33,11 +33,11 @@
                OpName %val_2 "val"
                OpName %arr_0 "arr"
                OpName %i_0 "i"
-               OpName %var_for_index_1 "var_for_index_1"
-               OpName %load_a_3_a_2_m "load_a_3_a_2_m"
+               OpName %var_for_index "var_for_index"
+               OpName %load_a_inner_3_a_2_m "load_a_inner_3_a_2_m"
                OpName %f "f"
-               OpDecorate %a_block Block
-               OpMemberDecorate %a_block 0 Offset 0
+               OpDecorate %a_block_std140 Block
+               OpMemberDecorate %a_block_std140 0 Offset 0
                OpMemberDecorate %Outer_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 1 Offset 8
@@ -61,9 +61,9 @@
 %_arr_Inner_std140_uint_4 = OpTypeArray %Inner_std140 %uint_4
 %Outer_std140 = OpTypeStruct %_arr_Inner_std140_uint_4
 %_arr_Outer_std140_uint_4 = OpTypeArray %Outer_std140 %uint_4
-    %a_block = OpTypeStruct %_arr_Outer_std140_uint_4
-%_ptr_Uniform_a_block = OpTypePointer Uniform %a_block
-          %a = OpVariable %_ptr_Uniform_a_block Uniform
+%a_block_std140 = OpTypeStruct %_arr_Outer_std140_uint_4
+%_ptr_Uniform_a_block_std140 = OpTypePointer Uniform %a_block_std140
+          %a = OpVariable %_ptr_Uniform_a_block_std140 Uniform
 %mat3v2float = OpTypeMatrix %v2float 3
       %Inner = OpTypeStruct %mat3v2float
          %12 = OpTypeFunction %Inner %Inner_std140
@@ -93,15 +93,13 @@
      %uint_0 = OpConstant %uint 0
      %uint_3 = OpConstant %uint 3
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
        %void = OpTypeVoid
-        %113 = OpTypeFunction %void
-        %int = OpTypeInt 32 1
-      %int_1 = OpConstant %int 1
+        %119 = OpTypeFunction %void
 %_ptr_Uniform__arr_Outer_std140_uint_4 = OpTypePointer Uniform %_arr_Outer_std140_uint_4
 %_ptr_Uniform_Outer_std140 = OpTypePointer Uniform %Outer_std140
 %_ptr_Uniform__arr_Inner_std140_uint_4 = OpTypePointer Uniform %_arr_Inner_std140_uint_4
-%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
 %_ptr_Uniform_float = OpTypePointer Uniform %float
  %conv_Inner = OpFunction %Inner None %12
         %val = OpFunctionParameter %Inner_std140
@@ -118,7 +116,7 @@
          %27 = OpLabel
         %arr = OpVariable %_ptr_Function__arr_Inner_uint_4 Function %30
           %i = OpVariable %_ptr_Function_uint Function %33
-%var_for_index = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %46
+%var_for_index_1 = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %46
                OpBranch %34
          %34 = OpLabel
                OpLoopMerge %35 %36 None
@@ -132,11 +130,11 @@
          %43 = OpLabel
                OpBranch %35
          %42 = OpLabel
-               OpStore %var_for_index %val_0
+               OpStore %var_for_index_1 %val_0
          %47 = OpLoad %uint %i
          %49 = OpAccessChain %_ptr_Function_Inner %arr %47
          %51 = OpLoad %uint %i
-         %53 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index %51
+         %53 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index_1 %51
          %54 = OpLoad %Inner_std140 %53
          %50 = OpFunctionCall %Inner %conv_Inner %54
                OpStore %49 %50
@@ -163,7 +161,7 @@
          %71 = OpLabel
       %arr_0 = OpVariable %_ptr_Function__arr_Outer_uint_4 Function %74
         %i_0 = OpVariable %_ptr_Function_uint Function %33
-%var_for_index_1 = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %87
+%var_for_index = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %87
                OpBranch %76
          %76 = OpLabel
                OpLoopMerge %77 %78 None
@@ -177,11 +175,11 @@
          %84 = OpLabel
                OpBranch %77
          %83 = OpLabel
-               OpStore %var_for_index_1 %val_2
+               OpStore %var_for_index %val_2
          %88 = OpLoad %uint %i_0
          %90 = OpAccessChain %_ptr_Function_Outer %arr_0 %88
          %92 = OpLoad %uint %i_0
-         %94 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index_1 %92
+         %94 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index %92
          %95 = OpLoad %Outer_std140 %94
          %91 = OpFunctionCall %Outer %conv_Outer %95
                OpStore %90 %91
@@ -195,50 +193,36 @@
          %98 = OpLoad %_arr_Outer_uint_4 %arr_0
                OpReturnValue %98
                OpFunctionEnd
-%load_a_3_a_2_m = OpFunction %mat3v2float None %99
+%load_a_inner_3_a_2_m = OpFunction %mat3v2float None %99
         %101 = OpLabel
-        %106 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_0
-        %107 = OpLoad %v2float %106
-        %108 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
-        %109 = OpLoad %v2float %108
-        %110 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_2
+        %107 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
+        %110 = OpAccessChain %_ptr_Uniform_v2float %107 %uint_0
         %111 = OpLoad %v2float %110
-        %112 = OpCompositeConstruct %mat3v2float %107 %109 %111
-               OpReturnValue %112
+        %113 = OpAccessChain %_ptr_Uniform_v2float %107 %uint_1
+        %114 = OpLoad %v2float %113
+        %116 = OpAccessChain %_ptr_Uniform_v2float %107 %uint_2
+        %117 = OpLoad %v2float %116
+        %118 = OpCompositeConstruct %mat3v2float %111 %114 %117
+               OpReturnValue %118
                OpFunctionEnd
-          %f = OpFunction %void None %113
-        %116 = OpLabel
-        %121 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %122 = OpLoad %_arr_Outer_std140_uint_4 %121
-        %119 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %122
-        %125 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %uint_3
-        %126 = OpLoad %Outer_std140 %125
-        %123 = OpFunctionCall %Outer %conv_Outer %126
-        %129 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %uint_3 %uint_0
-        %130 = OpLoad %_arr_Inner_std140_uint_4 %129
-        %127 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %130
-        %133 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
-        %134 = OpLoad %Inner_std140 %133
-        %131 = OpFunctionCall %Inner %conv_Inner %134
-        %135 = OpFunctionCall %mat3v2float %load_a_3_a_2_m
-        %136 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
-        %137 = OpLoad %v2float %136
-        %139 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %140 = OpLoad %_arr_Outer_std140_uint_4 %139
-        %138 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %140
-        %142 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %uint_3
-        %143 = OpLoad %Outer_std140 %142
-        %141 = OpFunctionCall %Outer %conv_Outer %143
-        %145 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %uint_3 %uint_0
-        %146 = OpLoad %_arr_Inner_std140_uint_4 %145
-        %144 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %146
-        %148 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
-        %149 = OpLoad %Inner_std140 %148
-        %147 = OpFunctionCall %Inner %conv_Inner %149
-        %150 = OpFunctionCall %mat3v2float %load_a_3_a_2_m
-        %151 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
-        %152 = OpLoad %v2float %151
-        %154 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1 %33
-        %155 = OpLoad %float %154
+          %f = OpFunction %void None %119
+        %122 = OpLabel
+        %125 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
+        %126 = OpLoad %_arr_Outer_std140_uint_4 %125
+        %123 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %126
+        %129 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %uint_3
+        %130 = OpLoad %Outer_std140 %129
+        %127 = OpFunctionCall %Outer %conv_Outer %130
+        %133 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %uint_3 %uint_0
+        %134 = OpLoad %_arr_Inner_std140_uint_4 %133
+        %131 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %134
+        %136 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
+        %137 = OpLoad %Inner_std140 %136
+        %135 = OpFunctionCall %Inner %conv_Inner %137
+        %138 = OpFunctionCall %mat3v2float %load_a_inner_3_a_2_m
+        %139 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
+        %140 = OpLoad %v2float %139
+        %142 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1 %33
+        %143 = OpLoad %float %142
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.wgsl
similarity index 97%
rename from test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.wgsl
index bea0f53..73396ee 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/static_index_via_ptr.wgsl.expected.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/static_index_via_ptr.wgsl.expected.wgsl
@@ -11,7 +11,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
   let p_a = &(a);
   let p_a_3 = &((*(p_a))[3]);
   let p_a_3_a = &((*(p_a_3)).a);
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.glsl
similarity index 73%
rename from test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.glsl
index 2d02c4d..93a683e 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.glsl
@@ -2,8 +2,12 @@
 
 struct S {
   int before;
+  uint pad;
   mat3x2 m;
+  uint pad_1;
+  uint pad_2;
   int after;
+  uint pad_3;
 };
 
 struct S_std140 {
@@ -18,16 +22,16 @@
   uint pad_3;
 };
 
-layout(binding = 0, std140) uniform u_block_ubo {
+layout(binding = 0, std140) uniform u_block_std140_ubo {
   S_std140 inner[4];
 } u;
 
-mat3x2 load_u_2_m() {
+mat3x2 load_u_inner_2_m() {
   return mat3x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2);
 }
 
 void f() {
-  mat2x3 t = transpose(load_u_2_m());
+  mat2x3 t = transpose(load_u_inner_2_m());
   float l = length(u.inner[0u].m_1.yx);
   float a = abs(u.inner[0u].m_1.yx[0u]);
 }
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.spvasm
new file mode 100644
index 0000000..ab0ed96
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.spvasm
@@ -0,0 +1,82 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 52
+; Schema: 0
+               OpCapability Shader
+         %42 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
+               OpName %S_std140 "S_std140"
+               OpMemberName %S_std140 0 "before"
+               OpMemberName %S_std140 1 "m_0"
+               OpMemberName %S_std140 2 "m_1"
+               OpMemberName %S_std140 3 "m_2"
+               OpMemberName %S_std140 4 "after"
+               OpName %u "u"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %S_std140 0 Offset 0
+               OpMemberDecorate %S_std140 1 Offset 8
+               OpMemberDecorate %S_std140 2 Offset 16
+               OpMemberDecorate %S_std140 3 Offset 24
+               OpMemberDecorate %S_std140 4 Offset 40
+               OpDecorate %_arr_S_std140_uint_4 ArrayStride 48
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+        %int = OpTypeInt 32 1
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+   %S_std140 = OpTypeStruct %int %v2float %v2float %v2float %int
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat3v2float = OpTypeMatrix %v2float 3
+         %11 = OpTypeFunction %mat3v2float
+     %uint_0 = OpConstant %uint 0
+     %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
+     %uint_1 = OpConstant %uint 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+         %33 = OpTypeFunction %void
+    %v3float = OpTypeVector %float 3
+%mat2v3float = OpTypeMatrix %v3float 2
+         %43 = OpConstantNull %uint
+%load_u_inner_2_m = OpFunction %mat3v2float None %11
+         %14 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %23 = OpAccessChain %_ptr_Uniform_v2float %19 %uint_1
+         %24 = OpLoad %v2float %23
+         %26 = OpAccessChain %_ptr_Uniform_v2float %19 %uint_2
+         %27 = OpLoad %v2float %26
+         %30 = OpAccessChain %_ptr_Uniform_v2float %19 %uint_3
+         %31 = OpLoad %v2float %30
+         %32 = OpCompositeConstruct %mat3v2float %24 %27 %31
+               OpReturnValue %32
+               OpFunctionEnd
+          %f = OpFunction %void None %33
+         %36 = OpLabel
+         %40 = OpFunctionCall %mat3v2float %load_u_inner_2_m
+         %37 = OpTranspose %mat2v3float %40
+         %44 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %43 %uint_2
+         %45 = OpLoad %v2float %44
+         %46 = OpVectorShuffle %v2float %45 %45 1 0
+         %41 = OpExtInst %float %42 Length %46
+         %48 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %43 %uint_2
+         %49 = OpLoad %v2float %48
+         %50 = OpVectorShuffle %v2float %49 %49 1 0
+         %51 = OpCompositeExtract %float %50 0
+         %47 = OpExtInst %float %42 FAbs %51
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_builtin.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_builtin.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.glsl
similarity index 62%
copy from test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.glsl
copy to test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.glsl
index fd4678d..720e66b 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.glsl
@@ -20,35 +20,45 @@
 
 struct S_std140 {
   int before;
-  uint pad_12;
+  uint pad;
   vec2 m_0;
   vec2 m_1;
   vec2 m_2;
-  uint pad_13;
-  uint pad_14;
-  uint pad_15;
-  uint pad_16;
-  uint pad_17;
-  uint pad_18;
-  uint pad_19;
-  uint pad_20;
-  uint pad_21;
-  uint pad_22;
+  uint pad_1;
+  uint pad_2;
+  uint pad_3;
+  uint pad_4;
+  uint pad_5;
+  uint pad_6;
+  uint pad_7;
+  uint pad_8;
+  uint pad_9;
+  uint pad_10;
   int after;
-  uint pad_23;
+  uint pad_11;
 };
 
-layout(binding = 0, std140) uniform u_block_ubo {
+layout(binding = 0, std140) uniform u_block_std140_ubo {
   S_std140 inner[4];
 } u;
 
-layout(binding = 1, std430) buffer s_block_ssbo {
-  S inner[4];
-} s;
+void a(S a_1[4]) {
+}
+
+void b(S s) {
+}
+
+void c(mat3x2 m) {
+}
+
+void d(vec2 v) {
+}
+
+void e(float f_1) {
+}
 
 S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, 0u, mat3x2(val.m_0, val.m_1, val.m_2), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, val.after, 0u);
-  return tint_symbol;
+  return S(val.before, val.pad, mat3x2(val.m_0, val.m_1, val.m_2), val.pad_1, val.pad_2, val.pad_3, val.pad_4, val.pad_5, val.pad_6, val.pad_7, val.pad_8, val.pad_9, val.pad_10, val.after, val.pad_11);
 }
 
 S[4] conv_arr_4_S(S_std140 val[4]) {
@@ -61,15 +71,16 @@
   return arr;
 }
 
-mat3x2 load_u_2_m() {
+mat3x2 load_u_inner_2_m() {
   return mat3x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2);
 }
 
 void f() {
-  s.inner = conv_arr_4_S(u.inner);
-  s.inner[1] = conv_S(u.inner[2u]);
-  s.inner[3].m = load_u_2_m();
-  s.inner[1].m[0] = u.inner[0u].m_1.yx;
+  a(conv_arr_4_S(u.inner));
+  b(conv_S(u.inner[2u]));
+  c(load_u_inner_2_m());
+  d(u.inner[0u].m_1.yx);
+  e(u.inner[0u].m_1.yx[0u]);
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.spvasm
similarity index 76%
rename from test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.spvasm
index b6ae5ab..148b7b6 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 119
+; Bound: 124
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -37,10 +37,10 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -63,9 +63,9 @@
        %uint = OpTypeInt 32 0
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
        %void = OpTypeVoid
 %mat3v2float = OpTypeMatrix %v2float 3
           %S = OpTypeStruct %int %mat3v2float %int
@@ -90,11 +90,11 @@
          %81 = OpTypeFunction %mat3v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_3 = OpConstant %uint 3
-         %95 = OpTypeFunction %void
+        %101 = OpTypeFunction %void
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
           %a = OpFunction %void None %11
         %a_1 = OpFunctionParameter %_arr_S_uint_4
          %18 = OpLabel
@@ -169,37 +169,38 @@
          %80 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %80
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat3v2float None %81
+%load_u_inner_2_m = OpFunction %mat3v2float None %81
          %83 = OpLabel
-         %87 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %88 = OpLoad %v2float %87
-         %89 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %90 = OpLoad %v2float %89
-         %92 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_3
-         %93 = OpLoad %v2float %92
-         %94 = OpCompositeConstruct %mat3v2float %88 %90 %93
-               OpReturnValue %94
+         %88 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %91 = OpAccessChain %_ptr_Uniform_v2float %88 %uint_1
+         %92 = OpLoad %v2float %91
+         %94 = OpAccessChain %_ptr_Uniform_v2float %88 %uint_2
+         %95 = OpLoad %v2float %94
+         %98 = OpAccessChain %_ptr_Uniform_v2float %88 %uint_3
+         %99 = OpLoad %v2float %98
+        %100 = OpCompositeConstruct %mat3v2float %92 %95 %99
+               OpReturnValue %100
                OpFunctionEnd
-          %f = OpFunction %void None %95
-         %97 = OpLabel
-        %101 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-        %102 = OpLoad %_arr_S_std140_uint_4 %101
-         %99 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %102
-         %98 = OpFunctionCall %void %a %99
-        %106 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-        %107 = OpLoad %S_std140 %106
-        %104 = OpFunctionCall %S %conv_S %107
-        %103 = OpFunctionCall %void %b %104
-        %109 = OpFunctionCall %mat3v2float %load_u_2_m
-        %108 = OpFunctionCall %void %c %109
-        %111 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %55 %uint_2
-        %112 = OpLoad %v2float %111
-        %113 = OpVectorShuffle %v2float %112 %112 1 0
-        %110 = OpFunctionCall %void %d %113
-        %115 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %55 %uint_2
-        %116 = OpLoad %v2float %115
-        %117 = OpVectorShuffle %v2float %116 %116 1 0
-        %118 = OpCompositeExtract %float %117 0
-        %114 = OpFunctionCall %void %e %118
+          %f = OpFunction %void None %101
+        %103 = OpLabel
+        %107 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+        %108 = OpLoad %_arr_S_std140_uint_4 %107
+        %105 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %108
+        %104 = OpFunctionCall %void %a %105
+        %111 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+        %112 = OpLoad %S_std140 %111
+        %110 = OpFunctionCall %S %conv_S %112
+        %109 = OpFunctionCall %void %b %110
+        %114 = OpFunctionCall %mat3v2float %load_u_inner_2_m
+        %113 = OpFunctionCall %void %c %114
+        %116 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %55 %uint_2
+        %117 = OpLoad %v2float %116
+        %118 = OpVectorShuffle %v2float %117 %117 1 0
+        %115 = OpFunctionCall %void %d %118
+        %120 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %55 %uint_2
+        %121 = OpLoad %v2float %120
+        %122 = OpVectorShuffle %v2float %121 %121 1 0
+        %123 = OpCompositeExtract %float %122 0
+        %119 = OpFunctionCall %void %e %123
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_fn.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_fn.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.glsl
new file mode 100644
index 0000000..5fa11e4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.glsl
@@ -0,0 +1,75 @@
+#version 310 es
+
+struct S {
+  int before;
+  uint pad;
+  mat3x2 m;
+  uint pad_1;
+  uint pad_2;
+  uint pad_3;
+  uint pad_4;
+  uint pad_5;
+  uint pad_6;
+  uint pad_7;
+  uint pad_8;
+  uint pad_9;
+  uint pad_10;
+  int after;
+  uint pad_11;
+};
+
+struct S_std140 {
+  int before;
+  uint pad;
+  vec2 m_0;
+  vec2 m_1;
+  vec2 m_2;
+  uint pad_1;
+  uint pad_2;
+  uint pad_3;
+  uint pad_4;
+  uint pad_5;
+  uint pad_6;
+  uint pad_7;
+  uint pad_8;
+  uint pad_9;
+  uint pad_10;
+  int after;
+  uint pad_11;
+};
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  S_std140 inner[4];
+} u;
+
+S p[4] = S[4](S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u), S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u), S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u), S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u));
+S conv_S(S_std140 val) {
+  return S(val.before, val.pad, mat3x2(val.m_0, val.m_1, val.m_2), val.pad_1, val.pad_2, val.pad_3, val.pad_4, val.pad_5, val.pad_6, val.pad_7, val.pad_8, val.pad_9, val.pad_10, val.after, val.pad_11);
+}
+
+S[4] conv_arr_4_S(S_std140 val[4]) {
+  S arr[4] = S[4](S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u), S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u), S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u), S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u));
+  {
+    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = conv_S(val[i]);
+    }
+  }
+  return arr;
+}
+
+mat3x2 load_u_inner_2_m() {
+  return mat3x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2);
+}
+
+void f() {
+  p = conv_arr_4_S(u.inner);
+  p[1] = conv_S(u.inner[2u]);
+  p[3].m = load_u_inner_2_m();
+  p[1].m[0] = u.inner[0u].m_1.yx;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.spvasm
similarity index 73%
rename from test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.spvasm
index 9156099..0320931 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 101
+; Bound: 106
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -28,10 +28,10 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -54,9 +54,9 @@
        %uint = OpTypeInt 32 0
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat3v2float = OpTypeMatrix %v2float 3
           %S = OpTypeStruct %int %mat3v2float %int
 %_arr_S_uint_4 = OpTypeArray %S %uint_4
@@ -77,17 +77,17 @@
          %62 = OpTypeFunction %mat3v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_3 = OpConstant %uint 3
        %void = OpTypeVoid
-         %76 = OpTypeFunction %void
+         %82 = OpTypeFunction %void
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
       %int_1 = OpConstant %int 1
 %_ptr_Private_S = OpTypePointer Private %S
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
       %int_3 = OpConstant %int 3
 %_ptr_Private_mat3v2float = OpTypePointer Private %mat3v2float
-         %95 = OpConstantNull %int
+        %100 = OpConstantNull %int
 %_ptr_Private_v2float = OpTypePointer Private %v2float
      %conv_S = OpFunction %S None %17
         %val = OpFunctionParameter %S_std140
@@ -138,35 +138,36 @@
          %61 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %61
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat3v2float None %62
+%load_u_inner_2_m = OpFunction %mat3v2float None %62
          %64 = OpLabel
-         %68 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %69 = OpLoad %v2float %68
-         %70 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %71 = OpLoad %v2float %70
-         %73 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_3
-         %74 = OpLoad %v2float %73
-         %75 = OpCompositeConstruct %mat3v2float %69 %71 %74
-               OpReturnValue %75
+         %69 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %72 = OpAccessChain %_ptr_Uniform_v2float %69 %uint_1
+         %73 = OpLoad %v2float %72
+         %75 = OpAccessChain %_ptr_Uniform_v2float %69 %uint_2
+         %76 = OpLoad %v2float %75
+         %79 = OpAccessChain %_ptr_Uniform_v2float %69 %uint_3
+         %80 = OpLoad %v2float %79
+         %81 = OpCompositeConstruct %mat3v2float %73 %76 %80
+               OpReturnValue %81
                OpFunctionEnd
-          %f = OpFunction %void None %76
-         %79 = OpLabel
-         %82 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-         %83 = OpLoad %_arr_S_std140_uint_4 %82
-         %80 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %83
-               OpStore %p %80
-         %86 = OpAccessChain %_ptr_Private_S %p %int_1
-         %89 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-         %90 = OpLoad %S_std140 %89
-         %87 = OpFunctionCall %S %conv_S %90
-               OpStore %86 %87
-         %93 = OpAccessChain %_ptr_Private_mat3v2float %p %int_3 %uint_1
-         %94 = OpFunctionCall %mat3v2float %load_u_2_m
-               OpStore %93 %94
-         %97 = OpAccessChain %_ptr_Private_v2float %p %int_1 %uint_1 %95
-         %98 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %36 %uint_2
-         %99 = OpLoad %v2float %98
-        %100 = OpVectorShuffle %v2float %99 %99 1 0
-               OpStore %97 %100
+          %f = OpFunction %void None %82
+         %85 = OpLabel
+         %88 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+         %89 = OpLoad %_arr_S_std140_uint_4 %88
+         %86 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %89
+               OpStore %p %86
+         %92 = OpAccessChain %_ptr_Private_S %p %int_1
+         %94 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %95 = OpLoad %S_std140 %94
+         %93 = OpFunctionCall %S %conv_S %95
+               OpStore %92 %93
+         %98 = OpAccessChain %_ptr_Private_mat3v2float %p %int_3 %uint_1
+         %99 = OpFunctionCall %mat3v2float %load_u_inner_2_m
+               OpStore %98 %99
+        %102 = OpAccessChain %_ptr_Private_v2float %p %int_1 %uint_1 %100
+        %103 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %36 %uint_2
+        %104 = OpLoad %v2float %103
+        %105 = OpVectorShuffle %v2float %104 %104 1 0
+               OpStore %102 %105
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_private.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_private.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.glsl
similarity index 69%
rename from test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.glsl
index fd4678d..ccd6e88 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.glsl
@@ -20,35 +20,34 @@
 
 struct S_std140 {
   int before;
-  uint pad_12;
+  uint pad;
   vec2 m_0;
   vec2 m_1;
   vec2 m_2;
-  uint pad_13;
-  uint pad_14;
-  uint pad_15;
-  uint pad_16;
-  uint pad_17;
-  uint pad_18;
-  uint pad_19;
-  uint pad_20;
-  uint pad_21;
-  uint pad_22;
+  uint pad_1;
+  uint pad_2;
+  uint pad_3;
+  uint pad_4;
+  uint pad_5;
+  uint pad_6;
+  uint pad_7;
+  uint pad_8;
+  uint pad_9;
+  uint pad_10;
   int after;
-  uint pad_23;
+  uint pad_11;
 };
 
-layout(binding = 0, std140) uniform u_block_ubo {
+layout(binding = 0, std140) uniform u_block_std140_ubo {
   S_std140 inner[4];
 } u;
 
-layout(binding = 1, std430) buffer s_block_ssbo {
+layout(binding = 1, std430) buffer u_block_ssbo {
   S inner[4];
 } s;
 
 S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, 0u, mat3x2(val.m_0, val.m_1, val.m_2), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, val.after, 0u);
-  return tint_symbol;
+  return S(val.before, val.pad, mat3x2(val.m_0, val.m_1, val.m_2), val.pad_1, val.pad_2, val.pad_3, val.pad_4, val.pad_5, val.pad_6, val.pad_7, val.pad_8, val.pad_9, val.pad_10, val.after, val.pad_11);
 }
 
 S[4] conv_arr_4_S(S_std140 val[4]) {
@@ -61,14 +60,14 @@
   return arr;
 }
 
-mat3x2 load_u_2_m() {
+mat3x2 load_u_inner_2_m() {
   return mat3x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2);
 }
 
 void f() {
   s.inner = conv_arr_4_S(u.inner);
   s.inner[1] = conv_S(u.inner[2u]);
-  s.inner[3].m = load_u_2_m();
+  s.inner[3].m = load_u_inner_2_m();
   s.inner[1].m[0] = u.inner[0u].m_1.yx;
 }
 
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.spvasm
similarity index 72%
rename from test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.spvasm
index ec518fd..3032953 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 104
+; Bound: 109
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -16,8 +16,8 @@
                OpMemberName %S_std140 3 "m_2"
                OpMemberName %S_std140 4 "after"
                OpName %u "u"
-               OpName %s_block "s_block"
-               OpMemberName %s_block 0 "inner"
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
                OpName %S "S"
                OpMemberName %S 0 "before"
                OpMemberName %S 1 "m"
@@ -30,10 +30,10 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -43,8 +43,8 @@
                OpDecorate %u NonWritable
                OpDecorate %u DescriptorSet 0
                OpDecorate %u Binding 0
-               OpDecorate %s_block Block
-               OpMemberDecorate %s_block 0 Offset 0
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
                OpMemberDecorate %S 0 Offset 0
                OpMemberDecorate %S 1 Offset 8
                OpMemberDecorate %S 1 ColMajor
@@ -60,15 +60,15 @@
        %uint = OpTypeInt 32 0
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat3v2float = OpTypeMatrix %v2float 3
           %S = OpTypeStruct %int %mat3v2float %int
 %_arr_S_uint_4 = OpTypeArray %S %uint_4
-    %s_block = OpTypeStruct %_arr_S_uint_4
-%_ptr_StorageBuffer_s_block = OpTypePointer StorageBuffer %s_block
-          %s = OpVariable %_ptr_StorageBuffer_s_block StorageBuffer
+    %u_block = OpTypeStruct %_arr_S_uint_4
+%_ptr_StorageBuffer_u_block = OpTypePointer StorageBuffer %u_block
+          %s = OpVariable %_ptr_StorageBuffer_u_block StorageBuffer
          %17 = OpTypeFunction %S %S_std140
          %28 = OpTypeFunction %_arr_S_uint_4 %_arr_S_std140_uint_4
 %_ptr_Function__arr_S_uint_4 = OpTypePointer Function %_arr_S_uint_4
@@ -84,18 +84,18 @@
          %63 = OpTypeFunction %mat3v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_3 = OpConstant %uint 3
        %void = OpTypeVoid
-         %77 = OpTypeFunction %void
+         %83 = OpTypeFunction %void
 %_ptr_StorageBuffer__arr_S_uint_4 = OpTypePointer StorageBuffer %_arr_S_uint_4
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
       %int_1 = OpConstant %int 1
 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
       %int_3 = OpConstant %int 3
 %_ptr_StorageBuffer_mat3v2float = OpTypePointer StorageBuffer %mat3v2float
-         %98 = OpConstantNull %int
+        %103 = OpConstantNull %int
 %_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
      %conv_S = OpFunction %S None %17
         %val = OpFunctionParameter %S_std140
@@ -146,36 +146,37 @@
          %62 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %62
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat3v2float None %63
+%load_u_inner_2_m = OpFunction %mat3v2float None %63
          %65 = OpLabel
-         %69 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %70 = OpLoad %v2float %69
-         %71 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %72 = OpLoad %v2float %71
-         %74 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_3
-         %75 = OpLoad %v2float %74
-         %76 = OpCompositeConstruct %mat3v2float %70 %72 %75
-               OpReturnValue %76
+         %70 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %73 = OpAccessChain %_ptr_Uniform_v2float %70 %uint_1
+         %74 = OpLoad %v2float %73
+         %76 = OpAccessChain %_ptr_Uniform_v2float %70 %uint_2
+         %77 = OpLoad %v2float %76
+         %80 = OpAccessChain %_ptr_Uniform_v2float %70 %uint_3
+         %81 = OpLoad %v2float %80
+         %82 = OpCompositeConstruct %mat3v2float %74 %77 %81
+               OpReturnValue %82
                OpFunctionEnd
-          %f = OpFunction %void None %77
-         %80 = OpLabel
-         %82 = OpAccessChain %_ptr_StorageBuffer__arr_S_uint_4 %s %uint_0
-         %85 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-         %86 = OpLoad %_arr_S_std140_uint_4 %85
-         %83 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %86
-               OpStore %82 %83
-         %89 = OpAccessChain %_ptr_StorageBuffer_S %s %uint_0 %int_1
-         %92 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-         %93 = OpLoad %S_std140 %92
-         %90 = OpFunctionCall %S %conv_S %93
-               OpStore %89 %90
-         %96 = OpAccessChain %_ptr_StorageBuffer_mat3v2float %s %uint_0 %int_3 %uint_1
-         %97 = OpFunctionCall %mat3v2float %load_u_2_m
-               OpStore %96 %97
-        %100 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1 %uint_1 %98
-        %101 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %37 %uint_2
-        %102 = OpLoad %v2float %101
-        %103 = OpVectorShuffle %v2float %102 %102 1 0
-               OpStore %100 %103
+          %f = OpFunction %void None %83
+         %86 = OpLabel
+         %88 = OpAccessChain %_ptr_StorageBuffer__arr_S_uint_4 %s %uint_0
+         %91 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+         %92 = OpLoad %_arr_S_std140_uint_4 %91
+         %89 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %92
+               OpStore %88 %89
+         %95 = OpAccessChain %_ptr_StorageBuffer_S %s %uint_0 %int_1
+         %97 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %98 = OpLoad %S_std140 %97
+         %96 = OpFunctionCall %S %conv_S %98
+               OpStore %95 %96
+        %101 = OpAccessChain %_ptr_StorageBuffer_mat3v2float %s %uint_0 %int_3 %uint_1
+        %102 = OpFunctionCall %mat3v2float %load_u_inner_2_m
+               OpStore %101 %102
+        %105 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1 %uint_1 %103
+        %106 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %37 %uint_2
+        %107 = OpLoad %v2float %106
+        %108 = OpVectorShuffle %v2float %107 %107 1 0
+               OpStore %105 %108
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_storage.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_storage.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.glsl
new file mode 100644
index 0000000..fd14f19
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.glsl
@@ -0,0 +1,83 @@
+#version 310 es
+
+struct S {
+  int before;
+  uint pad;
+  mat3x2 m;
+  uint pad_1;
+  uint pad_2;
+  uint pad_3;
+  uint pad_4;
+  uint pad_5;
+  uint pad_6;
+  uint pad_7;
+  uint pad_8;
+  uint pad_9;
+  uint pad_10;
+  int after;
+  uint pad_11;
+};
+
+struct S_std140 {
+  int before;
+  uint pad;
+  vec2 m_0;
+  vec2 m_1;
+  vec2 m_2;
+  uint pad_1;
+  uint pad_2;
+  uint pad_3;
+  uint pad_4;
+  uint pad_5;
+  uint pad_6;
+  uint pad_7;
+  uint pad_8;
+  uint pad_9;
+  uint pad_10;
+  int after;
+  uint pad_11;
+};
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  S_std140 inner[4];
+} u;
+
+shared S w[4];
+S conv_S(S_std140 val) {
+  return S(val.before, val.pad, mat3x2(val.m_0, val.m_1, val.m_2), val.pad_1, val.pad_2, val.pad_3, val.pad_4, val.pad_5, val.pad_6, val.pad_7, val.pad_8, val.pad_9, val.pad_10, val.after, val.pad_11);
+}
+
+S[4] conv_arr_4_S(S_std140 val[4]) {
+  S arr[4] = S[4](S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u), S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u), S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u), S(0, 0u, mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u));
+  {
+    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = conv_S(val[i]);
+    }
+  }
+  return arr;
+}
+
+mat3x2 load_u_inner_2_m() {
+  return mat3x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2);
+}
+
+void f(uint local_invocation_index) {
+  {
+    for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+      uint i = idx;
+      S tint_symbol = S(0, 0u, mat3x2(vec2(0.0f), vec2(0.0f), vec2(0.0f)), 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0, 0u);
+      w[i] = tint_symbol;
+    }
+  }
+  barrier();
+  w = conv_arr_4_S(u.inner);
+  w[1] = conv_S(u.inner[2u]);
+  w[3].m = load_u_inner_2_m();
+  w[1].m[0] = u.inner[0u].m_1.yx;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f(gl_LocalInvocationIndex);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.spvasm
similarity index 68%
rename from test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.spvasm
index 325aa7e..9db5af8 100644
--- a/test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.spvasm
@@ -1,15 +1,15 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 126
+; Bound: 131
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f" %local_invocation_index_1
                OpExecutionMode %f LocalSize 1 1 1
                OpName %local_invocation_index_1 "local_invocation_index_1"
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -29,14 +29,14 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f_inner "f_inner"
                OpName %local_invocation_index "local_invocation_index"
                OpName %idx "idx"
                OpName %f "f"
                OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -61,9 +61,9 @@
    %S_std140 = OpTypeStruct %int %v2float %v2float %v2float %int
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat3v2float = OpTypeMatrix %v2float 3
           %S = OpTypeStruct %int %mat3v2float %int
 %_arr_S_uint_4 = OpTypeArray %S %uint_4
@@ -84,21 +84,21 @@
          %64 = OpTypeFunction %mat3v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_3 = OpConstant %uint 3
        %void = OpTypeVoid
-         %78 = OpTypeFunction %void %uint
+         %84 = OpTypeFunction %void %uint
 %_ptr_Workgroup_S = OpTypePointer Workgroup %S
-         %96 = OpConstantNull %S
+        %102 = OpConstantNull %S
    %uint_264 = OpConstant %uint 264
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
       %int_1 = OpConstant %int 1
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
       %int_3 = OpConstant %int 3
 %_ptr_Workgroup_mat3v2float = OpTypePointer Workgroup %mat3v2float
-        %115 = OpConstantNull %int
+        %120 = OpConstantNull %int
 %_ptr_Workgroup_v2float = OpTypePointer Workgroup %v2float
-        %121 = OpTypeFunction %void
+        %126 = OpTypeFunction %void
      %conv_S = OpFunction %S None %18
         %val = OpFunctionParameter %S_std140
          %21 = OpLabel
@@ -148,68 +148,69 @@
          %63 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %63
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat3v2float None %64
+%load_u_inner_2_m = OpFunction %mat3v2float None %64
          %66 = OpLabel
-         %70 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %71 = OpLoad %v2float %70
-         %72 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %73 = OpLoad %v2float %72
-         %75 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_3
-         %76 = OpLoad %v2float %75
-         %77 = OpCompositeConstruct %mat3v2float %71 %73 %76
-               OpReturnValue %77
+         %71 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %74 = OpAccessChain %_ptr_Uniform_v2float %71 %uint_1
+         %75 = OpLoad %v2float %74
+         %77 = OpAccessChain %_ptr_Uniform_v2float %71 %uint_2
+         %78 = OpLoad %v2float %77
+         %81 = OpAccessChain %_ptr_Uniform_v2float %71 %uint_3
+         %82 = OpLoad %v2float %81
+         %83 = OpCompositeConstruct %mat3v2float %75 %78 %82
+               OpReturnValue %83
                OpFunctionEnd
-    %f_inner = OpFunction %void None %78
+    %f_inner = OpFunction %void None %84
 %local_invocation_index = OpFunctionParameter %uint
-         %82 = OpLabel
+         %88 = OpLabel
         %idx = OpVariable %_ptr_Function_uint Function %38
                OpStore %idx %local_invocation_index
-               OpBranch %84
-         %84 = OpLabel
-               OpLoopMerge %85 %86 None
-               OpBranch %87
-         %87 = OpLabel
-         %89 = OpLoad %uint %idx
-         %90 = OpULessThan %bool %89 %uint_4
-         %88 = OpLogicalNot %bool %90
-               OpSelectionMerge %91 None
-               OpBranchConditional %88 %92 %91
+               OpBranch %90
+         %90 = OpLabel
+               OpLoopMerge %91 %92 None
+               OpBranch %93
+         %93 = OpLabel
+         %95 = OpLoad %uint %idx
+         %96 = OpULessThan %bool %95 %uint_4
+         %94 = OpLogicalNot %bool %96
+               OpSelectionMerge %97 None
+               OpBranchConditional %94 %98 %97
+         %98 = OpLabel
+               OpBranch %91
+         %97 = OpLabel
+         %99 = OpLoad %uint %idx
+        %101 = OpAccessChain %_ptr_Workgroup_S %w %99
+               OpStore %101 %102
+               OpBranch %92
          %92 = OpLabel
-               OpBranch %85
+        %103 = OpLoad %uint %idx
+        %104 = OpIAdd %uint %103 %uint_1
+               OpStore %idx %104
+               OpBranch %90
          %91 = OpLabel
-         %93 = OpLoad %uint %idx
-         %95 = OpAccessChain %_ptr_Workgroup_S %w %93
-               OpStore %95 %96
-               OpBranch %86
-         %86 = OpLabel
-         %97 = OpLoad %uint %idx
-         %98 = OpIAdd %uint %97 %uint_1
-               OpStore %idx %98
-               OpBranch %84
-         %85 = OpLabel
                OpControlBarrier %uint_2 %uint_2 %uint_264
-        %103 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-        %104 = OpLoad %_arr_S_std140_uint_4 %103
-        %101 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %104
-               OpStore %w %101
-        %106 = OpAccessChain %_ptr_Workgroup_S %w %int_1
-        %109 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-        %110 = OpLoad %S_std140 %109
-        %107 = OpFunctionCall %S %conv_S %110
-               OpStore %106 %107
-        %113 = OpAccessChain %_ptr_Workgroup_mat3v2float %w %int_3 %uint_1
-        %114 = OpFunctionCall %mat3v2float %load_u_2_m
-               OpStore %113 %114
-        %117 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1 %uint_1 %115
-        %118 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %38 %uint_2
-        %119 = OpLoad %v2float %118
-        %120 = OpVectorShuffle %v2float %119 %119 1 0
-               OpStore %117 %120
+        %109 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+        %110 = OpLoad %_arr_S_std140_uint_4 %109
+        %107 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %110
+               OpStore %w %107
+        %112 = OpAccessChain %_ptr_Workgroup_S %w %int_1
+        %114 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+        %115 = OpLoad %S_std140 %114
+        %113 = OpFunctionCall %S %conv_S %115
+               OpStore %112 %113
+        %118 = OpAccessChain %_ptr_Workgroup_mat3v2float %w %int_3 %uint_1
+        %119 = OpFunctionCall %mat3v2float %load_u_inner_2_m
+               OpStore %118 %119
+        %122 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1 %uint_1 %120
+        %123 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %38 %uint_2
+        %124 = OpLoad %v2float %123
+        %125 = OpVectorShuffle %v2float %124 %124 1 0
+               OpStore %122 %125
                OpReturn
                OpFunctionEnd
-          %f = OpFunction %void None %121
-        %123 = OpLabel
-        %125 = OpLoad %uint %local_invocation_index_1
-        %124 = OpFunctionCall %void %f_inner %125
+          %f = OpFunction %void None %126
+        %128 = OpLabel
+        %130 = OpLoad %uint %local_invocation_index_1
+        %129 = OpFunctionCall %void %f_inner %130
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat3x2/to_workgroup.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat3x2/to_workgroup.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl
index ea019e1..512ab8c 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl
@@ -13,8 +13,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
-
   let p_a           = &a;
   let p_a_i         = &((*p_a)[i()]);
   let p_a_i_a       = &((*p_a_i).a);
diff --git a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
similarity index 99%
rename from test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
index e6bf304..e8e8cba 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -61,7 +61,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const int p_a_i_save = i();
   const int p_a_i_a_i_save = i();
   const int p_a_i_a_i_m_i_save = i();
diff --git a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
similarity index 99%
rename from test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
index e6bf304..e8e8cba 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -61,7 +61,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const int p_a_i_save = i();
   const int p_a_i_a_i_save = i();
   const int p_a_i_a_i_m_i_save = i();
diff --git a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl
similarity index 80%
rename from test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl
index da098b6..7e60332 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl
@@ -19,7 +19,7 @@
   Inner_std140 a[4];
 };
 
-layout(binding = 0, std140) uniform a_block_ubo {
+layout(binding = 0, std140) uniform a_block_std140_ubo {
   Outer_std140 inner[4];
 } a;
 
@@ -30,8 +30,7 @@
 }
 
 Inner conv_Inner(Inner_std140 val) {
-  Inner tint_symbol_4 = Inner(mat4x2(val.m_0, val.m_1, val.m_2, val.m_3));
-  return tint_symbol_4;
+  return Inner(mat4x2(val.m_0, val.m_1, val.m_2, val.m_3));
 }
 
 Inner[4] conv_arr_4_Inner(Inner_std140 val[4]) {
@@ -45,8 +44,7 @@
 }
 
 Outer conv_Outer(Outer_std140 val) {
-  Outer tint_symbol_5 = Outer(conv_arr_4_Inner(val.a));
-  return tint_symbol_5;
+  return Outer(conv_arr_4_Inner(val.a));
 }
 
 Outer[4] conv_arr_4_Outer(Outer_std140 val[4]) {
@@ -59,13 +57,13 @@
   return arr;
 }
 
-mat4x2 load_a_p0_a_p1_m(uint p0, uint p1) {
+mat4x2 load_a_inner_p0_a_p1_m(uint p0, uint p1) {
   uint s_save = p0;
   uint s_save_1 = p1;
   return mat4x2(a.inner[s_save].a[s_save_1].m_0, a.inner[s_save].a[s_save_1].m_1, a.inner[s_save].a[s_save_1].m_2, a.inner[s_save].a[s_save_1].m_3);
 }
 
-vec2 load_a_p0_a_p1_m_p2(uint p0, uint p1, uint p2) {
+vec2 load_a_inner_p0_a_p1_m_p2(uint p0, uint p1, uint p2) {
   switch(p2) {
     case 0u: {
       return a.inner[p0].a[p1].m_0;
@@ -90,7 +88,7 @@
   }
 }
 
-float load_a_p0_a_p1_m_p2_p3(uint p0, uint p1, uint p2, uint p3) {
+float load_a_inner_p0_a_p1_m_p2_p3(uint p0, uint p1, uint p2, uint p3) {
   switch(p2) {
     case 0u: {
       return a.inner[p0].a[p1].m_0[p3];
@@ -116,24 +114,23 @@
 }
 
 void f() {
-  int I = 1;
   Outer p_a[4] = conv_arr_4_Outer(a.inner);
   int tint_symbol = i();
   Outer p_a_i = conv_Outer(a.inner[tint_symbol]);
   Inner p_a_i_a[4] = conv_arr_4_Inner(a.inner[tint_symbol].a);
   int tint_symbol_1 = i();
   Inner p_a_i_a_i = conv_Inner(a.inner[tint_symbol].a[tint_symbol_1]);
-  mat4x2 p_a_i_a_i_m = load_a_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
+  mat4x2 p_a_i_a_i_m = load_a_inner_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
   int tint_symbol_2 = i();
-  vec2 p_a_i_a_i_m_i = load_a_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
+  vec2 p_a_i_a_i_m_i = load_a_inner_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
   Outer l_a[4] = conv_arr_4_Outer(a.inner);
   Outer l_a_i = conv_Outer(a.inner[tint_symbol]);
   Inner l_a_i_a[4] = conv_arr_4_Inner(a.inner[tint_symbol].a);
   Inner l_a_i_a_i = conv_Inner(a.inner[tint_symbol].a[tint_symbol_1]);
-  mat4x2 l_a_i_a_i_m = load_a_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
-  vec2 l_a_i_a_i_m_i = load_a_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
+  mat4x2 l_a_i_a_i_m = load_a_inner_p0_a_p1_m(uint(tint_symbol), uint(tint_symbol_1));
+  vec2 l_a_i_a_i_m_i = load_a_inner_p0_a_p1_m_p2(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2));
   int tint_symbol_3 = i();
-  float l_a_i_a_i_m_i_i = load_a_p0_a_p1_m_p2_p3(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2), uint(tint_symbol_3));
+  float l_a_i_a_i_m_i_i = load_a_inner_p0_a_p1_m_p2_p3(uint(tint_symbol), uint(tint_symbol_1), uint(tint_symbol_2), uint(tint_symbol_3));
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl
index 017e1e8..2f43afe 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl
@@ -29,7 +29,6 @@
 }
 
 kernel void f(const constant tint_array<Outer, 4>* tint_symbol_5 [[buffer(0)]]) {
-  int const I = 1;
   int const tint_symbol = i();
   int const p_a_i_save = tint_symbol;
   int const tint_symbol_1 = i();
diff --git a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm
similarity index 61%
rename from test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm
index 5de20f5..2a4d2ca 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 228
+; Bound: 215
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %a_block "a_block"
-               OpMemberName %a_block 0 "inner"
+               OpName %a_block_std140 "a_block_std140"
+               OpMemberName %a_block_std140 0 "inner"
                OpName %Outer_std140 "Outer_std140"
                OpMemberName %Outer_std140 0 "a"
                OpName %Inner_std140 "Inner_std140"
@@ -27,7 +27,7 @@
                OpName %val_0 "val"
                OpName %arr "arr"
                OpName %i_0 "i"
-               OpName %var_for_index "var_for_index"
+               OpName %var_for_index_1 "var_for_index_1"
                OpName %Outer "Outer"
                OpMemberName %Outer 0 "a"
                OpName %conv_Outer "conv_Outer"
@@ -36,22 +36,22 @@
                OpName %val_2 "val"
                OpName %arr_0 "arr"
                OpName %i_1 "i"
-               OpName %var_for_index_1 "var_for_index_1"
-               OpName %load_a_p0_a_p1_m "load_a_p0_a_p1_m"
+               OpName %var_for_index "var_for_index"
+               OpName %load_a_inner_p0_a_p1_m "load_a_inner_p0_a_p1_m"
                OpName %p0 "p0"
                OpName %p1 "p1"
-               OpName %load_a_p0_a_p1_m_p2 "load_a_p0_a_p1_m_p2"
+               OpName %load_a_inner_p0_a_p1_m_p2 "load_a_inner_p0_a_p1_m_p2"
                OpName %p0_0 "p0"
                OpName %p1_0 "p1"
                OpName %p2 "p2"
-               OpName %load_a_p0_a_p1_m_p2_p3 "load_a_p0_a_p1_m_p2_p3"
+               OpName %load_a_inner_p0_a_p1_m_p2_p3 "load_a_inner_p0_a_p1_m_p2_p3"
                OpName %p0_1 "p0"
                OpName %p1_1 "p1"
                OpName %p2_0 "p2"
                OpName %p3 "p3"
                OpName %f "f"
-               OpDecorate %a_block Block
-               OpMemberDecorate %a_block 0 Offset 0
+               OpDecorate %a_block_std140 Block
+               OpMemberDecorate %a_block_std140 0 Offset 0
                OpMemberDecorate %Outer_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 1 Offset 8
@@ -76,9 +76,9 @@
 %_arr_Inner_std140_uint_4 = OpTypeArray %Inner_std140 %uint_4
 %Outer_std140 = OpTypeStruct %_arr_Inner_std140_uint_4
 %_arr_Outer_std140_uint_4 = OpTypeArray %Outer_std140 %uint_4
-    %a_block = OpTypeStruct %_arr_Outer_std140_uint_4
-%_ptr_Uniform_a_block = OpTypePointer Uniform %a_block
-          %a = OpVariable %_ptr_Uniform_a_block Uniform
+%a_block_std140 = OpTypeStruct %_arr_Outer_std140_uint_4
+%_ptr_Uniform_a_block_std140 = OpTypePointer Uniform %a_block_std140
+          %a = OpVariable %_ptr_Uniform_a_block_std140 Uniform
         %int = OpTypeInt 32 1
          %13 = OpConstantNull %int
 %_ptr_Private_int = OpTypePointer Private %int
@@ -112,20 +112,20 @@
 %_ptr_Function_Outer_std140 = OpTypePointer Function %Outer_std140
         %111 = OpTypeFunction %mat4v2float %uint %uint
      %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_2 = OpConstant %uint 2
      %uint_3 = OpConstant %uint 3
-        %129 = OpTypeFunction %v2float %uint %uint %uint
-        %149 = OpConstantNull %v2float
-        %150 = OpTypeFunction %float %uint %uint %uint %uint
+        %136 = OpTypeFunction %v2float %uint %uint %uint
+        %156 = OpConstantNull %v2float
+        %157 = OpTypeFunction %float %uint %uint %uint %uint
 %_ptr_Uniform_float = OpTypePointer Uniform %float
-        %172 = OpConstantNull %float
+        %179 = OpConstantNull %float
        %void = OpTypeVoid
-        %173 = OpTypeFunction %void
+        %180 = OpTypeFunction %void
 %_ptr_Uniform__arr_Outer_std140_uint_4 = OpTypePointer Uniform %_arr_Outer_std140_uint_4
 %_ptr_Uniform_Outer_std140 = OpTypePointer Uniform %Outer_std140
 %_ptr_Uniform__arr_Inner_std140_uint_4 = OpTypePointer Uniform %_arr_Inner_std140_uint_4
-%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
           %i = OpFunction %int None %16
          %18 = OpLabel
          %19 = OpLoad %int %counter
@@ -150,7 +150,7 @@
          %39 = OpLabel
         %arr = OpVariable %_ptr_Function__arr_Inner_uint_4 Function %42
         %i_0 = OpVariable %_ptr_Function_uint Function %45
-%var_for_index = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %58
+%var_for_index_1 = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %58
                OpBranch %46
          %46 = OpLabel
                OpLoopMerge %47 %48 None
@@ -164,11 +164,11 @@
          %55 = OpLabel
                OpBranch %47
          %54 = OpLabel
-               OpStore %var_for_index %val_0
+               OpStore %var_for_index_1 %val_0
          %59 = OpLoad %uint %i_0
          %61 = OpAccessChain %_ptr_Function_Inner %arr %59
          %63 = OpLoad %uint %i_0
-         %65 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index %63
+         %65 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index_1 %63
          %66 = OpLoad %Inner_std140 %65
          %62 = OpFunctionCall %Inner %conv_Inner %66
                OpStore %61 %62
@@ -195,7 +195,7 @@
          %83 = OpLabel
       %arr_0 = OpVariable %_ptr_Function__arr_Outer_uint_4 Function %86
         %i_1 = OpVariable %_ptr_Function_uint Function %45
-%var_for_index_1 = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %99
+%var_for_index = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %99
                OpBranch %88
          %88 = OpLabel
                OpLoopMerge %89 %90 None
@@ -209,11 +209,11 @@
          %96 = OpLabel
                OpBranch %89
          %95 = OpLabel
-               OpStore %var_for_index_1 %val_2
+               OpStore %var_for_index %val_2
         %100 = OpLoad %uint %i_1
         %102 = OpAccessChain %_ptr_Function_Outer %arr_0 %100
         %104 = OpLoad %uint %i_1
-        %106 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index_1 %104
+        %106 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index %104
         %107 = OpLoad %Outer_std140 %106
         %103 = OpFunctionCall %Outer %conv_Outer %107
                OpStore %102 %103
@@ -227,126 +227,108 @@
         %110 = OpLoad %_arr_Outer_uint_4 %arr_0
                OpReturnValue %110
                OpFunctionEnd
-%load_a_p0_a_p1_m = OpFunction %mat4v2float None %111
+%load_a_inner_p0_a_p1_m = OpFunction %mat4v2float None %111
          %p0 = OpFunctionParameter %uint
          %p1 = OpFunctionParameter %uint
         %115 = OpLabel
-        %118 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0 %uint_0 %p1 %uint_0
-        %119 = OpLoad %v2float %118
-        %120 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0 %uint_0 %p1 %uint_1
-        %121 = OpLoad %v2float %120
-        %123 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0 %uint_0 %p1 %uint_2
-        %124 = OpLoad %v2float %123
-        %126 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0 %uint_0 %p1 %uint_3
-        %127 = OpLoad %v2float %126
-        %128 = OpCompositeConstruct %mat4v2float %119 %121 %124 %127
-               OpReturnValue %128
+        %119 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %p0 %uint_0 %p1
+        %122 = OpAccessChain %_ptr_Uniform_v2float %119 %uint_0
+        %123 = OpLoad %v2float %122
+        %125 = OpAccessChain %_ptr_Uniform_v2float %119 %uint_1
+        %126 = OpLoad %v2float %125
+        %129 = OpAccessChain %_ptr_Uniform_v2float %119 %uint_2
+        %130 = OpLoad %v2float %129
+        %133 = OpAccessChain %_ptr_Uniform_v2float %119 %uint_3
+        %134 = OpLoad %v2float %133
+        %135 = OpCompositeConstruct %mat4v2float %123 %126 %130 %134
+               OpReturnValue %135
                OpFunctionEnd
-%load_a_p0_a_p1_m_p2 = OpFunction %v2float None %129
+%load_a_inner_p0_a_p1_m_p2 = OpFunction %v2float None %136
        %p0_0 = OpFunctionParameter %uint
        %p1_0 = OpFunctionParameter %uint
          %p2 = OpFunctionParameter %uint
-        %134 = OpLabel
-               OpSelectionMerge %135 None
-               OpSwitch %p2 %136 0 %137 1 %138 2 %139 3 %140
-        %137 = OpLabel
-        %141 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_0
-        %142 = OpLoad %v2float %141
-               OpReturnValue %142
-        %138 = OpLabel
-        %143 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_1
-        %144 = OpLoad %v2float %143
-               OpReturnValue %144
-        %139 = OpLabel
-        %145 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_2
-        %146 = OpLoad %v2float %145
-               OpReturnValue %146
-        %140 = OpLabel
-        %147 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_3
-        %148 = OpLoad %v2float %147
-               OpReturnValue %148
-        %136 = OpLabel
+        %141 = OpLabel
+               OpSelectionMerge %142 None
+               OpSwitch %p2 %143 0 %144 1 %145 2 %146 3 %147
+        %144 = OpLabel
+        %148 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_0
+        %149 = OpLoad %v2float %148
                OpReturnValue %149
-        %135 = OpLabel
-               OpReturnValue %149
+        %145 = OpLabel
+        %150 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_1
+        %151 = OpLoad %v2float %150
+               OpReturnValue %151
+        %146 = OpLabel
+        %152 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_2
+        %153 = OpLoad %v2float %152
+               OpReturnValue %153
+        %147 = OpLabel
+        %154 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %p0_0 %uint_0 %p1_0 %uint_3
+        %155 = OpLoad %v2float %154
+               OpReturnValue %155
+        %143 = OpLabel
+               OpReturnValue %156
+        %142 = OpLabel
+               OpReturnValue %156
                OpFunctionEnd
-%load_a_p0_a_p1_m_p2_p3 = OpFunction %float None %150
+%load_a_inner_p0_a_p1_m_p2_p3 = OpFunction %float None %157
        %p0_1 = OpFunctionParameter %uint
        %p1_1 = OpFunctionParameter %uint
        %p2_0 = OpFunctionParameter %uint
          %p3 = OpFunctionParameter %uint
-        %156 = OpLabel
-               OpSelectionMerge %157 None
-               OpSwitch %p2_0 %158 0 %159 1 %160 2 %161 3 %162
-        %159 = OpLabel
-        %164 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_0 %p3
-        %165 = OpLoad %float %164
-               OpReturnValue %165
-        %160 = OpLabel
-        %166 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_1 %p3
-        %167 = OpLoad %float %166
-               OpReturnValue %167
-        %161 = OpLabel
-        %168 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_2 %p3
-        %169 = OpLoad %float %168
-               OpReturnValue %169
-        %162 = OpLabel
-        %170 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_3 %p3
-        %171 = OpLoad %float %170
-               OpReturnValue %171
-        %158 = OpLabel
+        %163 = OpLabel
+               OpSelectionMerge %164 None
+               OpSwitch %p2_0 %165 0 %166 1 %167 2 %168 3 %169
+        %166 = OpLabel
+        %171 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_0 %p3
+        %172 = OpLoad %float %171
                OpReturnValue %172
-        %157 = OpLabel
-               OpReturnValue %172
+        %167 = OpLabel
+        %173 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_1 %p3
+        %174 = OpLoad %float %173
+               OpReturnValue %174
+        %168 = OpLabel
+        %175 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_2 %p3
+        %176 = OpLoad %float %175
+               OpReturnValue %176
+        %169 = OpLabel
+        %177 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %p0_1 %uint_0 %p1_1 %uint_3 %p3
+        %178 = OpLoad %float %177
+               OpReturnValue %178
+        %165 = OpLabel
+               OpReturnValue %179
+        %164 = OpLabel
+               OpReturnValue %179
                OpFunctionEnd
-          %f = OpFunction %void None %173
-        %176 = OpLabel
-        %179 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %180 = OpLoad %_arr_Outer_std140_uint_4 %179
-        %177 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %180
-        %181 = OpFunctionCall %int %i
-        %184 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %181
-        %185 = OpLoad %Outer_std140 %184
-        %182 = OpFunctionCall %Outer %conv_Outer %185
-        %188 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %181 %uint_0
-        %189 = OpLoad %_arr_Inner_std140_uint_4 %188
-        %186 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %189
-        %190 = OpFunctionCall %int %i
-        %193 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %181 %uint_0 %190
-        %194 = OpLoad %Inner_std140 %193
-        %191 = OpFunctionCall %Inner %conv_Inner %194
-        %196 = OpBitcast %uint %181
-        %197 = OpBitcast %uint %190
-        %195 = OpFunctionCall %mat4v2float %load_a_p0_a_p1_m %196 %197
-        %198 = OpFunctionCall %int %i
-        %200 = OpBitcast %uint %181
-        %201 = OpBitcast %uint %190
-        %202 = OpBitcast %uint %198
-        %199 = OpFunctionCall %v2float %load_a_p0_a_p1_m_p2 %200 %201 %202
-        %204 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %205 = OpLoad %_arr_Outer_std140_uint_4 %204
-        %203 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %205
-        %207 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %181
-        %208 = OpLoad %Outer_std140 %207
-        %206 = OpFunctionCall %Outer %conv_Outer %208
-        %210 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %181 %uint_0
-        %211 = OpLoad %_arr_Inner_std140_uint_4 %210
-        %209 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %211
-        %213 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %181 %uint_0 %190
-        %214 = OpLoad %Inner_std140 %213
-        %212 = OpFunctionCall %Inner %conv_Inner %214
-        %216 = OpBitcast %uint %181
-        %217 = OpBitcast %uint %190
-        %215 = OpFunctionCall %mat4v2float %load_a_p0_a_p1_m %216 %217
-        %219 = OpBitcast %uint %181
-        %220 = OpBitcast %uint %190
-        %221 = OpBitcast %uint %198
-        %218 = OpFunctionCall %v2float %load_a_p0_a_p1_m_p2 %219 %220 %221
-        %222 = OpFunctionCall %int %i
-        %224 = OpBitcast %uint %181
-        %225 = OpBitcast %uint %190
-        %226 = OpBitcast %uint %198
-        %227 = OpBitcast %uint %222
-        %223 = OpFunctionCall %float %load_a_p0_a_p1_m_p2_p3 %224 %225 %226 %227
+          %f = OpFunction %void None %180
+        %183 = OpLabel
+        %184 = OpFunctionCall %int %i
+        %185 = OpFunctionCall %int %i
+        %186 = OpFunctionCall %int %i
+        %189 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
+        %190 = OpLoad %_arr_Outer_std140_uint_4 %189
+        %187 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %190
+        %193 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %184
+        %194 = OpLoad %Outer_std140 %193
+        %191 = OpFunctionCall %Outer %conv_Outer %194
+        %197 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %184 %uint_0
+        %198 = OpLoad %_arr_Inner_std140_uint_4 %197
+        %195 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %198
+        %200 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %184 %uint_0 %185
+        %201 = OpLoad %Inner_std140 %200
+        %199 = OpFunctionCall %Inner %conv_Inner %201
+        %203 = OpBitcast %uint %184
+        %204 = OpBitcast %uint %185
+        %202 = OpFunctionCall %mat4v2float %load_a_inner_p0_a_p1_m %203 %204
+        %206 = OpBitcast %uint %184
+        %207 = OpBitcast %uint %185
+        %208 = OpBitcast %uint %186
+        %205 = OpFunctionCall %v2float %load_a_inner_p0_a_p1_m_p2 %206 %207 %208
+        %209 = OpFunctionCall %int %i
+        %211 = OpBitcast %uint %184
+        %212 = OpBitcast %uint %185
+        %213 = OpBitcast %uint %186
+        %214 = OpBitcast %uint %209
+        %210 = OpFunctionCall %float %load_a_inner_p0_a_p1_m_p2_p3 %211 %212 %213 %214
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl
index 8417933..7cc47fe 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl
@@ -17,7 +17,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
   let p_a = &(a);
   let p_a_i = &((*(p_a))[i()]);
   let p_a_i_a = &((*(p_a_i)).a);
diff --git a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl
similarity index 97%
rename from test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl
index 8731181..582e8ac 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl
@@ -10,8 +10,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
-
   let p_a = &a;
   let p_a_3 = &((*p_a)[3]);
   let p_a_3_a = &((*p_a_3).a);
diff --git a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
index 597afef..512f6ba 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -55,7 +55,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const Outer l_a[4] = tint_symbol(a, 0u);
   const Outer l_a_3 = tint_symbol_1(a, 384u);
   const Inner l_a_3_a[4] = tint_symbol_2(a, 384u);
diff --git a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
similarity index 98%
copy from test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
copy to test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
index 597afef..512f6ba 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -55,7 +55,6 @@
 
 [numthreads(1, 1, 1)]
 void f() {
-  const int I = 1;
   const Outer l_a[4] = tint_symbol(a, 0u);
   const Outer l_a_3 = tint_symbol_1(a, 384u);
   const Inner l_a_3_a[4] = tint_symbol_2(a, 384u);
diff --git a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.glsl
similarity index 88%
rename from test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.glsl
index 99394e5..c14425b 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.glsl
@@ -19,13 +19,12 @@
   Inner_std140 a[4];
 };
 
-layout(binding = 0, std140) uniform a_block_ubo {
+layout(binding = 0, std140) uniform a_block_std140_ubo {
   Outer_std140 inner[4];
 } a;
 
 Inner conv_Inner(Inner_std140 val) {
-  Inner tint_symbol = Inner(mat4x2(val.m_0, val.m_1, val.m_2, val.m_3));
-  return tint_symbol;
+  return Inner(mat4x2(val.m_0, val.m_1, val.m_2, val.m_3));
 }
 
 Inner[4] conv_arr_4_Inner(Inner_std140 val[4]) {
@@ -39,8 +38,7 @@
 }
 
 Outer conv_Outer(Outer_std140 val) {
-  Outer tint_symbol_1 = Outer(conv_arr_4_Inner(val.a));
-  return tint_symbol_1;
+  return Outer(conv_arr_4_Inner(val.a));
 }
 
 Outer[4] conv_arr_4_Outer(Outer_std140 val[4]) {
@@ -53,23 +51,22 @@
   return arr;
 }
 
-mat4x2 load_a_3_a_2_m() {
+mat4x2 load_a_inner_3_a_2_m() {
   return mat4x2(a.inner[3u].a[2u].m_0, a.inner[3u].a[2u].m_1, a.inner[3u].a[2u].m_2, a.inner[3u].a[2u].m_3);
 }
 
 void f() {
-  int I = 1;
   Outer p_a[4] = conv_arr_4_Outer(a.inner);
   Outer p_a_3 = conv_Outer(a.inner[3u]);
   Inner p_a_3_a[4] = conv_arr_4_Inner(a.inner[3u].a);
   Inner p_a_3_a_2 = conv_Inner(a.inner[3u].a[2u]);
-  mat4x2 p_a_3_a_2_m = load_a_3_a_2_m();
+  mat4x2 p_a_3_a_2_m = load_a_inner_3_a_2_m();
   vec2 p_a_3_a_2_m_1 = a.inner[3u].a[2u].m_1;
   Outer l_a[4] = conv_arr_4_Outer(a.inner);
   Outer l_a_3 = conv_Outer(a.inner[3u]);
   Inner l_a_3_a[4] = conv_arr_4_Inner(a.inner[3u].a);
   Inner l_a_3_a_2 = conv_Inner(a.inner[3u].a[2u]);
-  mat4x2 l_a_3_a_2_m = load_a_3_a_2_m();
+  mat4x2 l_a_3_a_2_m = load_a_inner_3_a_2_m();
   vec2 l_a_3_a_2_m_1 = a.inner[3u].a[2u].m_1;
   float l_a_3_a_2_m_1_0 = a.inner[3u].a[2u].m_1[0u];
 }
diff --git a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.msl
similarity index 98%
rename from test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.msl
index ef14c73..457e620 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.msl
@@ -23,7 +23,6 @@
 };
 
 kernel void f(const constant tint_array<Outer, 4>* tint_symbol [[buffer(0)]]) {
-  int const I = 1;
   tint_array<Outer, 4> const l_a = *(tint_symbol);
   Outer const l_a_3 = (*(tint_symbol))[3];
   tint_array<Inner, 4> const l_a_3_a = (*(tint_symbol))[3].a;
diff --git a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.spvasm
similarity index 71%
rename from test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.spvasm
index f752945..3cd3ef3 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 159
+; Bound: 148
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %a_block "a_block"
-               OpMemberName %a_block 0 "inner"
+               OpName %a_block_std140 "a_block_std140"
+               OpMemberName %a_block_std140 0 "inner"
                OpName %Outer_std140 "Outer_std140"
                OpMemberName %Outer_std140 0 "a"
                OpName %Inner_std140 "Inner_std140"
@@ -25,7 +25,7 @@
                OpName %val_0 "val"
                OpName %arr "arr"
                OpName %i "i"
-               OpName %var_for_index "var_for_index"
+               OpName %var_for_index_1 "var_for_index_1"
                OpName %Outer "Outer"
                OpMemberName %Outer 0 "a"
                OpName %conv_Outer "conv_Outer"
@@ -34,11 +34,11 @@
                OpName %val_2 "val"
                OpName %arr_0 "arr"
                OpName %i_0 "i"
-               OpName %var_for_index_1 "var_for_index_1"
-               OpName %load_a_3_a_2_m "load_a_3_a_2_m"
+               OpName %var_for_index "var_for_index"
+               OpName %load_a_inner_3_a_2_m "load_a_inner_3_a_2_m"
                OpName %f "f"
-               OpDecorate %a_block Block
-               OpMemberDecorate %a_block 0 Offset 0
+               OpDecorate %a_block_std140 Block
+               OpMemberDecorate %a_block_std140 0 Offset 0
                OpMemberDecorate %Outer_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 0 Offset 0
                OpMemberDecorate %Inner_std140 1 Offset 8
@@ -63,9 +63,9 @@
 %_arr_Inner_std140_uint_4 = OpTypeArray %Inner_std140 %uint_4
 %Outer_std140 = OpTypeStruct %_arr_Inner_std140_uint_4
 %_arr_Outer_std140_uint_4 = OpTypeArray %Outer_std140 %uint_4
-    %a_block = OpTypeStruct %_arr_Outer_std140_uint_4
-%_ptr_Uniform_a_block = OpTypePointer Uniform %a_block
-          %a = OpVariable %_ptr_Uniform_a_block Uniform
+%a_block_std140 = OpTypeStruct %_arr_Outer_std140_uint_4
+%_ptr_Uniform_a_block_std140 = OpTypePointer Uniform %a_block_std140
+          %a = OpVariable %_ptr_Uniform_a_block_std140 Uniform
 %mat4v2float = OpTypeMatrix %v2float 4
       %Inner = OpTypeStruct %mat4v2float
          %12 = OpTypeFunction %Inner %Inner_std140
@@ -95,15 +95,13 @@
      %uint_0 = OpConstant %uint 0
      %uint_3 = OpConstant %uint 3
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
        %void = OpTypeVoid
-        %116 = OpTypeFunction %void
-        %int = OpTypeInt 32 1
-      %int_1 = OpConstant %int 1
+        %123 = OpTypeFunction %void
 %_ptr_Uniform__arr_Outer_std140_uint_4 = OpTypePointer Uniform %_arr_Outer_std140_uint_4
 %_ptr_Uniform_Outer_std140 = OpTypePointer Uniform %Outer_std140
 %_ptr_Uniform__arr_Inner_std140_uint_4 = OpTypePointer Uniform %_arr_Inner_std140_uint_4
-%_ptr_Uniform_Inner_std140 = OpTypePointer Uniform %Inner_std140
 %_ptr_Uniform_float = OpTypePointer Uniform %float
  %conv_Inner = OpFunction %Inner None %12
         %val = OpFunctionParameter %Inner_std140
@@ -121,7 +119,7 @@
          %28 = OpLabel
         %arr = OpVariable %_ptr_Function__arr_Inner_uint_4 Function %31
           %i = OpVariable %_ptr_Function_uint Function %34
-%var_for_index = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %47
+%var_for_index_1 = OpVariable %_ptr_Function__arr_Inner_std140_uint_4 Function %47
                OpBranch %35
          %35 = OpLabel
                OpLoopMerge %36 %37 None
@@ -135,11 +133,11 @@
          %44 = OpLabel
                OpBranch %36
          %43 = OpLabel
-               OpStore %var_for_index %val_0
+               OpStore %var_for_index_1 %val_0
          %48 = OpLoad %uint %i
          %50 = OpAccessChain %_ptr_Function_Inner %arr %48
          %52 = OpLoad %uint %i
-         %54 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index %52
+         %54 = OpAccessChain %_ptr_Function_Inner_std140 %var_for_index_1 %52
          %55 = OpLoad %Inner_std140 %54
          %51 = OpFunctionCall %Inner %conv_Inner %55
                OpStore %50 %51
@@ -166,7 +164,7 @@
          %72 = OpLabel
       %arr_0 = OpVariable %_ptr_Function__arr_Outer_uint_4 Function %75
         %i_0 = OpVariable %_ptr_Function_uint Function %34
-%var_for_index_1 = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %88
+%var_for_index = OpVariable %_ptr_Function__arr_Outer_std140_uint_4 Function %88
                OpBranch %77
          %77 = OpLabel
                OpLoopMerge %78 %79 None
@@ -180,11 +178,11 @@
          %85 = OpLabel
                OpBranch %78
          %84 = OpLabel
-               OpStore %var_for_index_1 %val_2
+               OpStore %var_for_index %val_2
          %89 = OpLoad %uint %i_0
          %91 = OpAccessChain %_ptr_Function_Outer %arr_0 %89
          %93 = OpLoad %uint %i_0
-         %95 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index_1 %93
+         %95 = OpAccessChain %_ptr_Function_Outer_std140 %var_for_index %93
          %96 = OpLoad %Outer_std140 %95
          %92 = OpFunctionCall %Outer %conv_Outer %96
                OpStore %91 %92
@@ -198,52 +196,38 @@
          %99 = OpLoad %_arr_Outer_uint_4 %arr_0
                OpReturnValue %99
                OpFunctionEnd
-%load_a_3_a_2_m = OpFunction %mat4v2float None %100
+%load_a_inner_3_a_2_m = OpFunction %mat4v2float None %100
         %102 = OpLabel
-        %107 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_0
-        %108 = OpLoad %v2float %107
-        %109 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
-        %110 = OpLoad %v2float %109
-        %111 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_2
+        %108 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
+        %111 = OpAccessChain %_ptr_Uniform_v2float %108 %uint_0
         %112 = OpLoad %v2float %111
-        %113 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_3
-        %114 = OpLoad %v2float %113
-        %115 = OpCompositeConstruct %mat4v2float %108 %110 %112 %114
-               OpReturnValue %115
+        %114 = OpAccessChain %_ptr_Uniform_v2float %108 %uint_1
+        %115 = OpLoad %v2float %114
+        %117 = OpAccessChain %_ptr_Uniform_v2float %108 %uint_2
+        %118 = OpLoad %v2float %117
+        %120 = OpAccessChain %_ptr_Uniform_v2float %108 %uint_3
+        %121 = OpLoad %v2float %120
+        %122 = OpCompositeConstruct %mat4v2float %112 %115 %118 %121
+               OpReturnValue %122
                OpFunctionEnd
-          %f = OpFunction %void None %116
-        %119 = OpLabel
-        %124 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %125 = OpLoad %_arr_Outer_std140_uint_4 %124
-        %122 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %125
-        %128 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %uint_3
-        %129 = OpLoad %Outer_std140 %128
-        %126 = OpFunctionCall %Outer %conv_Outer %129
-        %132 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %uint_3 %uint_0
-        %133 = OpLoad %_arr_Inner_std140_uint_4 %132
-        %130 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %133
-        %136 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
-        %137 = OpLoad %Inner_std140 %136
-        %134 = OpFunctionCall %Inner %conv_Inner %137
-        %138 = OpFunctionCall %mat4v2float %load_a_3_a_2_m
-        %139 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
-        %140 = OpLoad %v2float %139
-        %142 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
-        %143 = OpLoad %_arr_Outer_std140_uint_4 %142
-        %141 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %143
-        %145 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %uint_3
-        %146 = OpLoad %Outer_std140 %145
-        %144 = OpFunctionCall %Outer %conv_Outer %146
-        %148 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %uint_3 %uint_0
-        %149 = OpLoad %_arr_Inner_std140_uint_4 %148
-        %147 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %149
-        %151 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
-        %152 = OpLoad %Inner_std140 %151
-        %150 = OpFunctionCall %Inner %conv_Inner %152
-        %153 = OpFunctionCall %mat4v2float %load_a_3_a_2_m
-        %154 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
-        %155 = OpLoad %v2float %154
-        %157 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1 %34
-        %158 = OpLoad %float %157
+          %f = OpFunction %void None %123
+        %126 = OpLabel
+        %129 = OpAccessChain %_ptr_Uniform__arr_Outer_std140_uint_4 %a %uint_0
+        %130 = OpLoad %_arr_Outer_std140_uint_4 %129
+        %127 = OpFunctionCall %_arr_Outer_uint_4 %conv_arr_4_Outer %130
+        %133 = OpAccessChain %_ptr_Uniform_Outer_std140 %a %uint_0 %uint_3
+        %134 = OpLoad %Outer_std140 %133
+        %131 = OpFunctionCall %Outer %conv_Outer %134
+        %137 = OpAccessChain %_ptr_Uniform__arr_Inner_std140_uint_4 %a %uint_0 %uint_3 %uint_0
+        %138 = OpLoad %_arr_Inner_std140_uint_4 %137
+        %135 = OpFunctionCall %_arr_Inner_uint_4 %conv_arr_4_Inner %138
+        %140 = OpAccessChain %_ptr_Uniform_Inner_std140 %a %uint_0 %uint_3 %uint_0 %uint_2
+        %141 = OpLoad %Inner_std140 %140
+        %139 = OpFunctionCall %Inner %conv_Inner %141
+        %142 = OpFunctionCall %mat4v2float %load_a_inner_3_a_2_m
+        %143 = OpAccessChain %_ptr_Uniform_v2float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1
+        %144 = OpLoad %v2float %143
+        %146 = OpAccessChain %_ptr_Uniform_float %a %uint_0 %uint_3 %uint_0 %uint_2 %uint_1 %34
+        %147 = OpLoad %float %146
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.wgsl
similarity index 97%
rename from test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.wgsl
index ff8de06..6347a0e 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/static_index_via_ptr.wgsl.expected.wgsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/static_index_via_ptr.wgsl.expected.wgsl
@@ -10,7 +10,6 @@
 
 @compute @workgroup_size(1)
 fn f() {
-  let I = 1;
   let p_a = &(a);
   let p_a_3 = &((*(p_a))[3]);
   let p_a_3_a = &((*(p_a_3)).a);
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.glsl
similarity index 76%
rename from test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.glsl
index 9eede3e..b5bbb97 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.glsl
@@ -2,8 +2,10 @@
 
 struct S {
   int before;
+  uint pad;
   mat4x2 m;
   int after;
+  uint pad_1;
 };
 
 struct S_std140 {
@@ -17,16 +19,16 @@
   uint pad_1;
 };
 
-layout(binding = 0, std140) uniform u_block_ubo {
+layout(binding = 0, std140) uniform u_block_std140_ubo {
   S_std140 inner[4];
 } u;
 
-mat4x2 load_u_2_m() {
+mat4x2 load_u_inner_2_m() {
   return mat4x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2, u.inner[2u].m_3);
 }
 
 void f() {
-  mat2x4 t = transpose(load_u_2_m());
+  mat2x4 t = transpose(load_u_inner_2_m());
   float l = length(u.inner[0u].m_1.yx);
   float a = abs(u.inner[0u].m_1.yx[0u]);
 }
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.spvasm
new file mode 100644
index 0000000..831410f
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.spvasm
@@ -0,0 +1,86 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 55
+; Schema: 0
+               OpCapability Shader
+         %45 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
+               OpName %S_std140 "S_std140"
+               OpMemberName %S_std140 0 "before"
+               OpMemberName %S_std140 1 "m_0"
+               OpMemberName %S_std140 2 "m_1"
+               OpMemberName %S_std140 3 "m_2"
+               OpMemberName %S_std140 4 "m_3"
+               OpMemberName %S_std140 5 "after"
+               OpName %u "u"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %S_std140 0 Offset 0
+               OpMemberDecorate %S_std140 1 Offset 8
+               OpMemberDecorate %S_std140 2 Offset 16
+               OpMemberDecorate %S_std140 3 Offset 24
+               OpMemberDecorate %S_std140 4 Offset 32
+               OpMemberDecorate %S_std140 5 Offset 40
+               OpDecorate %_arr_S_std140_uint_4 ArrayStride 48
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+        %int = OpTypeInt 32 1
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+   %S_std140 = OpTypeStruct %int %v2float %v2float %v2float %v2float %int
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat4v2float = OpTypeMatrix %v2float 4
+         %11 = OpTypeFunction %mat4v2float
+     %uint_0 = OpConstant %uint 0
+     %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
+     %uint_1 = OpConstant %uint 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+         %36 = OpTypeFunction %void
+    %v4float = OpTypeVector %float 4
+%mat2v4float = OpTypeMatrix %v4float 2
+         %46 = OpConstantNull %uint
+%load_u_inner_2_m = OpFunction %mat4v2float None %11
+         %14 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %23 = OpAccessChain %_ptr_Uniform_v2float %19 %uint_1
+         %24 = OpLoad %v2float %23
+         %26 = OpAccessChain %_ptr_Uniform_v2float %19 %uint_2
+         %27 = OpLoad %v2float %26
+         %30 = OpAccessChain %_ptr_Uniform_v2float %19 %uint_3
+         %31 = OpLoad %v2float %30
+         %33 = OpAccessChain %_ptr_Uniform_v2float %19 %uint_4
+         %34 = OpLoad %v2float %33
+         %35 = OpCompositeConstruct %mat4v2float %24 %27 %31 %34
+               OpReturnValue %35
+               OpFunctionEnd
+          %f = OpFunction %void None %36
+         %39 = OpLabel
+         %43 = OpFunctionCall %mat4v2float %load_u_inner_2_m
+         %40 = OpTranspose %mat2v4float %43
+         %47 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %46 %uint_2
+         %48 = OpLoad %v2float %47
+         %49 = OpVectorShuffle %v2float %48 %48 1 0
+         %44 = OpExtInst %float %45 Length %49
+         %51 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %46 %uint_2
+         %52 = OpLoad %v2float %51
+         %53 = OpVectorShuffle %v2float %52 %52 1 0
+         %54 = OpCompositeExtract %float %53 0
+         %50 = OpExtInst %float %45 FAbs %54
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_builtin.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_builtin.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.glsl
similarity index 66%
copy from test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.glsl
copy to test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.glsl
index 13e7964..42fa3a1 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.glsl
@@ -10,26 +10,36 @@
 
 struct S_std140 {
   int before;
-  uint pad_2;
+  uint pad;
   vec2 m_0;
   vec2 m_1;
   vec2 m_2;
   vec2 m_3;
   int after;
-  uint pad_3;
+  uint pad_1;
 };
 
-layout(binding = 0, std140) uniform u_block_ubo {
+layout(binding = 0, std140) uniform u_block_std140_ubo {
   S_std140 inner[4];
 } u;
 
-layout(binding = 1, std430) buffer s_block_ssbo {
-  S inner[4];
-} s;
+void a(S a_1[4]) {
+}
+
+void b(S s) {
+}
+
+void c(mat4x2 m) {
+}
+
+void d(vec2 v) {
+}
+
+void e(float f_1) {
+}
 
 S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, 0u, mat4x2(val.m_0, val.m_1, val.m_2, val.m_3), val.after, 0u);
-  return tint_symbol;
+  return S(val.before, val.pad, mat4x2(val.m_0, val.m_1, val.m_2, val.m_3), val.after, val.pad_1);
 }
 
 S[4] conv_arr_4_S(S_std140 val[4]) {
@@ -42,15 +52,16 @@
   return arr;
 }
 
-mat4x2 load_u_2_m() {
+mat4x2 load_u_inner_2_m() {
   return mat4x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2, u.inner[2u].m_3);
 }
 
 void f() {
-  s.inner = conv_arr_4_S(u.inner);
-  s.inner[1] = conv_S(u.inner[2u]);
-  s.inner[3].m = load_u_2_m();
-  s.inner[1].m[0] = u.inner[0u].m_1.yx;
+  a(conv_arr_4_S(u.inner));
+  b(conv_S(u.inner[2u]));
+  c(load_u_inner_2_m());
+  d(u.inner[0u].m_1.yx);
+  e(u.inner[0u].m_1.yx[0u]);
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.spvasm
similarity index 76%
rename from test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.spvasm
index 9993de9..06de1ef 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 122
+; Bound: 128
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -38,10 +38,10 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -65,9 +65,9 @@
        %uint = OpTypeInt 32 0
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
        %void = OpTypeVoid
 %mat4v2float = OpTypeMatrix %v2float 4
           %S = OpTypeStruct %int %mat4v2float %int
@@ -92,11 +92,11 @@
          %82 = OpTypeFunction %mat4v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_3 = OpConstant %uint 3
-         %98 = OpTypeFunction %void
+        %105 = OpTypeFunction %void
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
           %a = OpFunction %void None %11
         %a_1 = OpFunctionParameter %_arr_S_uint_4
          %18 = OpLabel
@@ -172,39 +172,40 @@
          %81 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %81
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat4v2float None %82
+%load_u_inner_2_m = OpFunction %mat4v2float None %82
          %84 = OpLabel
-         %88 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %89 = OpLoad %v2float %88
-         %90 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %91 = OpLoad %v2float %90
-         %93 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_3
-         %94 = OpLoad %v2float %93
-         %95 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_4
+         %89 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %92 = OpAccessChain %_ptr_Uniform_v2float %89 %uint_1
+         %93 = OpLoad %v2float %92
+         %95 = OpAccessChain %_ptr_Uniform_v2float %89 %uint_2
          %96 = OpLoad %v2float %95
-         %97 = OpCompositeConstruct %mat4v2float %89 %91 %94 %96
-               OpReturnValue %97
+         %99 = OpAccessChain %_ptr_Uniform_v2float %89 %uint_3
+        %100 = OpLoad %v2float %99
+        %102 = OpAccessChain %_ptr_Uniform_v2float %89 %uint_4
+        %103 = OpLoad %v2float %102
+        %104 = OpCompositeConstruct %mat4v2float %93 %96 %100 %103
+               OpReturnValue %104
                OpFunctionEnd
-          %f = OpFunction %void None %98
-        %100 = OpLabel
-        %104 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-        %105 = OpLoad %_arr_S_std140_uint_4 %104
-        %102 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %105
-        %101 = OpFunctionCall %void %a %102
-        %109 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-        %110 = OpLoad %S_std140 %109
-        %107 = OpFunctionCall %S %conv_S %110
-        %106 = OpFunctionCall %void %b %107
-        %112 = OpFunctionCall %mat4v2float %load_u_2_m
-        %111 = OpFunctionCall %void %c %112
-        %114 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %56 %uint_2
-        %115 = OpLoad %v2float %114
-        %116 = OpVectorShuffle %v2float %115 %115 1 0
-        %113 = OpFunctionCall %void %d %116
-        %118 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %56 %uint_2
-        %119 = OpLoad %v2float %118
-        %120 = OpVectorShuffle %v2float %119 %119 1 0
-        %121 = OpCompositeExtract %float %120 0
-        %117 = OpFunctionCall %void %e %121
+          %f = OpFunction %void None %105
+        %107 = OpLabel
+        %111 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+        %112 = OpLoad %_arr_S_std140_uint_4 %111
+        %109 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %112
+        %108 = OpFunctionCall %void %a %109
+        %115 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+        %116 = OpLoad %S_std140 %115
+        %114 = OpFunctionCall %S %conv_S %116
+        %113 = OpFunctionCall %void %b %114
+        %118 = OpFunctionCall %mat4v2float %load_u_inner_2_m
+        %117 = OpFunctionCall %void %c %118
+        %120 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %56 %uint_2
+        %121 = OpLoad %v2float %120
+        %122 = OpVectorShuffle %v2float %121 %121 1 0
+        %119 = OpFunctionCall %void %d %122
+        %124 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %56 %uint_2
+        %125 = OpLoad %v2float %124
+        %126 = OpVectorShuffle %v2float %125 %125 1 0
+        %127 = OpCompositeExtract %float %126 0
+        %123 = OpFunctionCall %void %e %127
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_fn.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_fn.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.glsl
new file mode 100644
index 0000000..658610e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.glsl
@@ -0,0 +1,56 @@
+#version 310 es
+
+struct S {
+  int before;
+  uint pad;
+  mat4x2 m;
+  int after;
+  uint pad_1;
+};
+
+struct S_std140 {
+  int before;
+  uint pad;
+  vec2 m_0;
+  vec2 m_1;
+  vec2 m_2;
+  vec2 m_3;
+  int after;
+  uint pad_1;
+};
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  S_std140 inner[4];
+} u;
+
+S p[4] = S[4](S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u));
+S conv_S(S_std140 val) {
+  return S(val.before, val.pad, mat4x2(val.m_0, val.m_1, val.m_2, val.m_3), val.after, val.pad_1);
+}
+
+S[4] conv_arr_4_S(S_std140 val[4]) {
+  S arr[4] = S[4](S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u));
+  {
+    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = conv_S(val[i]);
+    }
+  }
+  return arr;
+}
+
+mat4x2 load_u_inner_2_m() {
+  return mat4x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2, u.inner[2u].m_3);
+}
+
+void f() {
+  p = conv_arr_4_S(u.inner);
+  p[1] = conv_S(u.inner[2u]);
+  p[3].m = load_u_inner_2_m();
+  p[1].m[0] = u.inner[0u].m_1.yx;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.spvasm
similarity index 74%
rename from test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.spvasm
index a5b0ac5..ea4bf22 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 104
+; Bound: 110
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -29,10 +29,10 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -56,9 +56,9 @@
        %uint = OpTypeInt 32 0
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat4v2float = OpTypeMatrix %v2float 4
           %S = OpTypeStruct %int %mat4v2float %int
 %_arr_S_uint_4 = OpTypeArray %S %uint_4
@@ -79,17 +79,17 @@
          %63 = OpTypeFunction %mat4v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_3 = OpConstant %uint 3
        %void = OpTypeVoid
-         %79 = OpTypeFunction %void
+         %86 = OpTypeFunction %void
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
       %int_1 = OpConstant %int 1
 %_ptr_Private_S = OpTypePointer Private %S
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
       %int_3 = OpConstant %int 3
 %_ptr_Private_mat4v2float = OpTypePointer Private %mat4v2float
-         %98 = OpConstantNull %int
+        %104 = OpConstantNull %int
 %_ptr_Private_v2float = OpTypePointer Private %v2float
      %conv_S = OpFunction %S None %17
         %val = OpFunctionParameter %S_std140
@@ -141,37 +141,38 @@
          %62 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %62
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat4v2float None %63
+%load_u_inner_2_m = OpFunction %mat4v2float None %63
          %65 = OpLabel
-         %69 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %70 = OpLoad %v2float %69
-         %71 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %72 = OpLoad %v2float %71
-         %74 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_3
-         %75 = OpLoad %v2float %74
-         %76 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_4
+         %70 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %73 = OpAccessChain %_ptr_Uniform_v2float %70 %uint_1
+         %74 = OpLoad %v2float %73
+         %76 = OpAccessChain %_ptr_Uniform_v2float %70 %uint_2
          %77 = OpLoad %v2float %76
-         %78 = OpCompositeConstruct %mat4v2float %70 %72 %75 %77
-               OpReturnValue %78
+         %80 = OpAccessChain %_ptr_Uniform_v2float %70 %uint_3
+         %81 = OpLoad %v2float %80
+         %83 = OpAccessChain %_ptr_Uniform_v2float %70 %uint_4
+         %84 = OpLoad %v2float %83
+         %85 = OpCompositeConstruct %mat4v2float %74 %77 %81 %84
+               OpReturnValue %85
                OpFunctionEnd
-          %f = OpFunction %void None %79
-         %82 = OpLabel
-         %85 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-         %86 = OpLoad %_arr_S_std140_uint_4 %85
-         %83 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %86
-               OpStore %p %83
-         %89 = OpAccessChain %_ptr_Private_S %p %int_1
-         %92 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-         %93 = OpLoad %S_std140 %92
-         %90 = OpFunctionCall %S %conv_S %93
-               OpStore %89 %90
-         %96 = OpAccessChain %_ptr_Private_mat4v2float %p %int_3 %uint_1
-         %97 = OpFunctionCall %mat4v2float %load_u_2_m
+          %f = OpFunction %void None %86
+         %89 = OpLabel
+         %92 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+         %93 = OpLoad %_arr_S_std140_uint_4 %92
+         %90 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %93
+               OpStore %p %90
+         %96 = OpAccessChain %_ptr_Private_S %p %int_1
+         %98 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %99 = OpLoad %S_std140 %98
+         %97 = OpFunctionCall %S %conv_S %99
                OpStore %96 %97
-        %100 = OpAccessChain %_ptr_Private_v2float %p %int_1 %uint_1 %98
-        %101 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %37 %uint_2
-        %102 = OpLoad %v2float %101
-        %103 = OpVectorShuffle %v2float %102 %102 1 0
-               OpStore %100 %103
+        %102 = OpAccessChain %_ptr_Private_mat4v2float %p %int_3 %uint_1
+        %103 = OpFunctionCall %mat4v2float %load_u_inner_2_m
+               OpStore %102 %103
+        %106 = OpAccessChain %_ptr_Private_v2float %p %int_1 %uint_1 %104
+        %107 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %37 %uint_2
+        %108 = OpLoad %v2float %107
+        %109 = OpVectorShuffle %v2float %108 %108 1 0
+               OpStore %106 %109
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_private.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_private.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.glsl
similarity index 77%
rename from test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.glsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.glsl
index 13e7964..90098bd 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.glsl
@@ -10,26 +10,25 @@
 
 struct S_std140 {
   int before;
-  uint pad_2;
+  uint pad;
   vec2 m_0;
   vec2 m_1;
   vec2 m_2;
   vec2 m_3;
   int after;
-  uint pad_3;
+  uint pad_1;
 };
 
-layout(binding = 0, std140) uniform u_block_ubo {
+layout(binding = 0, std140) uniform u_block_std140_ubo {
   S_std140 inner[4];
 } u;
 
-layout(binding = 1, std430) buffer s_block_ssbo {
+layout(binding = 1, std430) buffer u_block_ssbo {
   S inner[4];
 } s;
 
 S conv_S(S_std140 val) {
-  S tint_symbol = S(val.before, 0u, mat4x2(val.m_0, val.m_1, val.m_2, val.m_3), val.after, 0u);
-  return tint_symbol;
+  return S(val.before, val.pad, mat4x2(val.m_0, val.m_1, val.m_2, val.m_3), val.after, val.pad_1);
 }
 
 S[4] conv_arr_4_S(S_std140 val[4]) {
@@ -42,14 +41,14 @@
   return arr;
 }
 
-mat4x2 load_u_2_m() {
+mat4x2 load_u_inner_2_m() {
   return mat4x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2, u.inner[2u].m_3);
 }
 
 void f() {
   s.inner = conv_arr_4_S(u.inner);
   s.inner[1] = conv_S(u.inner[2u]);
-  s.inner[3].m = load_u_2_m();
+  s.inner[3].m = load_u_inner_2_m();
   s.inner[1].m[0] = u.inner[0u].m_1.yx;
 }
 
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.spvasm
similarity index 73%
rename from test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.spvasm
index eec2559..5d20562 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 107
+; Bound: 113
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f"
                OpExecutionMode %f LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -17,8 +17,8 @@
                OpMemberName %S_std140 4 "m_3"
                OpMemberName %S_std140 5 "after"
                OpName %u "u"
-               OpName %s_block "s_block"
-               OpMemberName %s_block 0 "inner"
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
                OpName %S "S"
                OpMemberName %S 0 "before"
                OpMemberName %S 1 "m"
@@ -31,10 +31,10 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f "f"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -45,8 +45,8 @@
                OpDecorate %u NonWritable
                OpDecorate %u DescriptorSet 0
                OpDecorate %u Binding 0
-               OpDecorate %s_block Block
-               OpMemberDecorate %s_block 0 Offset 0
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
                OpMemberDecorate %S 0 Offset 0
                OpMemberDecorate %S 1 Offset 8
                OpMemberDecorate %S 1 ColMajor
@@ -62,15 +62,15 @@
        %uint = OpTypeInt 32 0
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat4v2float = OpTypeMatrix %v2float 4
           %S = OpTypeStruct %int %mat4v2float %int
 %_arr_S_uint_4 = OpTypeArray %S %uint_4
-    %s_block = OpTypeStruct %_arr_S_uint_4
-%_ptr_StorageBuffer_s_block = OpTypePointer StorageBuffer %s_block
-          %s = OpVariable %_ptr_StorageBuffer_s_block StorageBuffer
+    %u_block = OpTypeStruct %_arr_S_uint_4
+%_ptr_StorageBuffer_u_block = OpTypePointer StorageBuffer %u_block
+          %s = OpVariable %_ptr_StorageBuffer_u_block StorageBuffer
          %17 = OpTypeFunction %S %S_std140
          %29 = OpTypeFunction %_arr_S_uint_4 %_arr_S_std140_uint_4
 %_ptr_Function__arr_S_uint_4 = OpTypePointer Function %_arr_S_uint_4
@@ -86,18 +86,18 @@
          %64 = OpTypeFunction %mat4v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_3 = OpConstant %uint 3
        %void = OpTypeVoid
-         %80 = OpTypeFunction %void
+         %87 = OpTypeFunction %void
 %_ptr_StorageBuffer__arr_S_uint_4 = OpTypePointer StorageBuffer %_arr_S_uint_4
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
       %int_1 = OpConstant %int 1
 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
       %int_3 = OpConstant %int 3
 %_ptr_StorageBuffer_mat4v2float = OpTypePointer StorageBuffer %mat4v2float
-        %101 = OpConstantNull %int
+        %107 = OpConstantNull %int
 %_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
      %conv_S = OpFunction %S None %17
         %val = OpFunctionParameter %S_std140
@@ -149,38 +149,39 @@
          %63 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %63
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat4v2float None %64
+%load_u_inner_2_m = OpFunction %mat4v2float None %64
          %66 = OpLabel
-         %70 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %71 = OpLoad %v2float %70
-         %72 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %73 = OpLoad %v2float %72
-         %75 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_3
-         %76 = OpLoad %v2float %75
-         %77 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_4
+         %71 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %74 = OpAccessChain %_ptr_Uniform_v2float %71 %uint_1
+         %75 = OpLoad %v2float %74
+         %77 = OpAccessChain %_ptr_Uniform_v2float %71 %uint_2
          %78 = OpLoad %v2float %77
-         %79 = OpCompositeConstruct %mat4v2float %71 %73 %76 %78
-               OpReturnValue %79
+         %81 = OpAccessChain %_ptr_Uniform_v2float %71 %uint_3
+         %82 = OpLoad %v2float %81
+         %84 = OpAccessChain %_ptr_Uniform_v2float %71 %uint_4
+         %85 = OpLoad %v2float %84
+         %86 = OpCompositeConstruct %mat4v2float %75 %78 %82 %85
+               OpReturnValue %86
                OpFunctionEnd
-          %f = OpFunction %void None %80
-         %83 = OpLabel
-         %85 = OpAccessChain %_ptr_StorageBuffer__arr_S_uint_4 %s %uint_0
-         %88 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-         %89 = OpLoad %_arr_S_std140_uint_4 %88
-         %86 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %89
-               OpStore %85 %86
-         %92 = OpAccessChain %_ptr_StorageBuffer_S %s %uint_0 %int_1
-         %95 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-         %96 = OpLoad %S_std140 %95
-         %93 = OpFunctionCall %S %conv_S %96
+          %f = OpFunction %void None %87
+         %90 = OpLabel
+         %92 = OpAccessChain %_ptr_StorageBuffer__arr_S_uint_4 %s %uint_0
+         %95 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+         %96 = OpLoad %_arr_S_std140_uint_4 %95
+         %93 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %96
                OpStore %92 %93
-         %99 = OpAccessChain %_ptr_StorageBuffer_mat4v2float %s %uint_0 %int_3 %uint_1
-        %100 = OpFunctionCall %mat4v2float %load_u_2_m
+         %99 = OpAccessChain %_ptr_StorageBuffer_S %s %uint_0 %int_1
+        %101 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+        %102 = OpLoad %S_std140 %101
+        %100 = OpFunctionCall %S %conv_S %102
                OpStore %99 %100
-        %103 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1 %uint_1 %101
-        %104 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %38 %uint_2
-        %105 = OpLoad %v2float %104
-        %106 = OpVectorShuffle %v2float %105 %105 1 0
-               OpStore %103 %106
+        %105 = OpAccessChain %_ptr_StorageBuffer_mat4v2float %s %uint_0 %int_3 %uint_1
+        %106 = OpFunctionCall %mat4v2float %load_u_inner_2_m
+               OpStore %105 %106
+        %109 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1 %uint_1 %107
+        %110 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %38 %uint_2
+        %111 = OpLoad %v2float %110
+        %112 = OpVectorShuffle %v2float %111 %111 1 0
+               OpStore %109 %112
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_storage.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_storage.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.dxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.dxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.fxc.hlsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.fxc.hlsl
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.glsl
new file mode 100644
index 0000000..07cabf9
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.glsl
@@ -0,0 +1,64 @@
+#version 310 es
+
+struct S {
+  int before;
+  uint pad;
+  mat4x2 m;
+  int after;
+  uint pad_1;
+};
+
+struct S_std140 {
+  int before;
+  uint pad;
+  vec2 m_0;
+  vec2 m_1;
+  vec2 m_2;
+  vec2 m_3;
+  int after;
+  uint pad_1;
+};
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  S_std140 inner[4];
+} u;
+
+shared S w[4];
+S conv_S(S_std140 val) {
+  return S(val.before, val.pad, mat4x2(val.m_0, val.m_1, val.m_2, val.m_3), val.after, val.pad_1);
+}
+
+S[4] conv_arr_4_S(S_std140 val[4]) {
+  S arr[4] = S[4](S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u), S(0, 0u, mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f), 0, 0u));
+  {
+    for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+      arr[i] = conv_S(val[i]);
+    }
+  }
+  return arr;
+}
+
+mat4x2 load_u_inner_2_m() {
+  return mat4x2(u.inner[2u].m_0, u.inner[2u].m_1, u.inner[2u].m_2, u.inner[2u].m_3);
+}
+
+void f(uint local_invocation_index) {
+  {
+    for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+      uint i = idx;
+      S tint_symbol = S(0, 0u, mat4x2(vec2(0.0f), vec2(0.0f), vec2(0.0f), vec2(0.0f)), 0, 0u);
+      w[i] = tint_symbol;
+    }
+  }
+  barrier();
+  w = conv_arr_4_S(u.inner);
+  w[1] = conv_S(u.inner[2u]);
+  w[3].m = load_u_inner_2_m();
+  w[1].m[0] = u.inner[0u].m_1.yx;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f(gl_LocalInvocationIndex);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.msl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.msl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.msl
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.spvasm
similarity index 69%
rename from test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.spvasm
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.spvasm
index ec0684a..80ec01c 100644
--- a/test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.spvasm
@@ -1,15 +1,15 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 129
+; Bound: 135
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %f "f" %local_invocation_index_1
                OpExecutionMode %f LocalSize 1 1 1
                OpName %local_invocation_index_1 "local_invocation_index_1"
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner"
                OpName %S_std140 "S_std140"
                OpMemberName %S_std140 0 "before"
                OpMemberName %S_std140 1 "m_0"
@@ -30,14 +30,14 @@
                OpName %arr "arr"
                OpName %i "i"
                OpName %var_for_index "var_for_index"
-               OpName %load_u_2_m "load_u_2_m"
+               OpName %load_u_inner_2_m "load_u_inner_2_m"
                OpName %f_inner "f_inner"
                OpName %local_invocation_index "local_invocation_index"
                OpName %idx "idx"
                OpName %f "f"
                OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
                OpMemberDecorate %S_std140 0 Offset 0
                OpMemberDecorate %S_std140 1 Offset 8
                OpMemberDecorate %S_std140 2 Offset 16
@@ -63,9 +63,9 @@
    %S_std140 = OpTypeStruct %int %v2float %v2float %v2float %v2float %int
      %uint_4 = OpConstant %uint 4
 %_arr_S_std140_uint_4 = OpTypeArray %S_std140 %uint_4
-    %u_block = OpTypeStruct %_arr_S_std140_uint_4
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
+%u_block_std140 = OpTypeStruct %_arr_S_std140_uint_4
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat4v2float = OpTypeMatrix %v2float 4
           %S = OpTypeStruct %int %mat4v2float %int
 %_arr_S_uint_4 = OpTypeArray %S %uint_4
@@ -86,21 +86,21 @@
          %65 = OpTypeFunction %mat4v2float
      %uint_0 = OpConstant %uint 0
      %uint_2 = OpConstant %uint 2
+%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_3 = OpConstant %uint 3
        %void = OpTypeVoid
-         %81 = OpTypeFunction %void %uint
+         %88 = OpTypeFunction %void %uint
 %_ptr_Workgroup_S = OpTypePointer Workgroup %S
-         %99 = OpConstantNull %S
+        %106 = OpConstantNull %S
    %uint_264 = OpConstant %uint 264
 %_ptr_Uniform__arr_S_std140_uint_4 = OpTypePointer Uniform %_arr_S_std140_uint_4
       %int_1 = OpConstant %int 1
-%_ptr_Uniform_S_std140 = OpTypePointer Uniform %S_std140
       %int_3 = OpConstant %int 3
 %_ptr_Workgroup_mat4v2float = OpTypePointer Workgroup %mat4v2float
-        %118 = OpConstantNull %int
+        %124 = OpConstantNull %int
 %_ptr_Workgroup_v2float = OpTypePointer Workgroup %v2float
-        %124 = OpTypeFunction %void
+        %130 = OpTypeFunction %void
      %conv_S = OpFunction %S None %18
         %val = OpFunctionParameter %S_std140
          %21 = OpLabel
@@ -151,70 +151,71 @@
          %64 = OpLoad %_arr_S_uint_4 %arr
                OpReturnValue %64
                OpFunctionEnd
- %load_u_2_m = OpFunction %mat4v2float None %65
+%load_u_inner_2_m = OpFunction %mat4v2float None %65
          %67 = OpLabel
-         %71 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_1
-         %72 = OpLoad %v2float %71
-         %73 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_2
-         %74 = OpLoad %v2float %73
-         %76 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_3
-         %77 = OpLoad %v2float %76
-         %78 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %uint_2 %uint_4
+         %72 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+         %75 = OpAccessChain %_ptr_Uniform_v2float %72 %uint_1
+         %76 = OpLoad %v2float %75
+         %78 = OpAccessChain %_ptr_Uniform_v2float %72 %uint_2
          %79 = OpLoad %v2float %78
-         %80 = OpCompositeConstruct %mat4v2float %72 %74 %77 %79
-               OpReturnValue %80
+         %82 = OpAccessChain %_ptr_Uniform_v2float %72 %uint_3
+         %83 = OpLoad %v2float %82
+         %85 = OpAccessChain %_ptr_Uniform_v2float %72 %uint_4
+         %86 = OpLoad %v2float %85
+         %87 = OpCompositeConstruct %mat4v2float %76 %79 %83 %86
+               OpReturnValue %87
                OpFunctionEnd
-    %f_inner = OpFunction %void None %81
+    %f_inner = OpFunction %void None %88
 %local_invocation_index = OpFunctionParameter %uint
-         %85 = OpLabel
+         %92 = OpLabel
         %idx = OpVariable %_ptr_Function_uint Function %39
                OpStore %idx %local_invocation_index
-               OpBranch %87
-         %87 = OpLabel
-               OpLoopMerge %88 %89 None
-               OpBranch %90
-         %90 = OpLabel
-         %92 = OpLoad %uint %idx
-         %93 = OpULessThan %bool %92 %uint_4
-         %91 = OpLogicalNot %bool %93
-               OpSelectionMerge %94 None
-               OpBranchConditional %91 %95 %94
-         %95 = OpLabel
-               OpBranch %88
+               OpBranch %94
          %94 = OpLabel
-         %96 = OpLoad %uint %idx
-         %98 = OpAccessChain %_ptr_Workgroup_S %w %96
-               OpStore %98 %99
-               OpBranch %89
-         %89 = OpLabel
-        %100 = OpLoad %uint %idx
-        %101 = OpIAdd %uint %100 %uint_1
-               OpStore %idx %101
-               OpBranch %87
-         %88 = OpLabel
+               OpLoopMerge %95 %96 None
+               OpBranch %97
+         %97 = OpLabel
+         %99 = OpLoad %uint %idx
+        %100 = OpULessThan %bool %99 %uint_4
+         %98 = OpLogicalNot %bool %100
+               OpSelectionMerge %101 None
+               OpBranchConditional %98 %102 %101
+        %102 = OpLabel
+               OpBranch %95
+        %101 = OpLabel
+        %103 = OpLoad %uint %idx
+        %105 = OpAccessChain %_ptr_Workgroup_S %w %103
+               OpStore %105 %106
+               OpBranch %96
+         %96 = OpLabel
+        %107 = OpLoad %uint %idx
+        %108 = OpIAdd %uint %107 %uint_1
+               OpStore %idx %108
+               OpBranch %94
+         %95 = OpLabel
                OpControlBarrier %uint_2 %uint_2 %uint_264
-        %106 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
-        %107 = OpLoad %_arr_S_std140_uint_4 %106
-        %104 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %107
-               OpStore %w %104
-        %109 = OpAccessChain %_ptr_Workgroup_S %w %int_1
-        %112 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
-        %113 = OpLoad %S_std140 %112
-        %110 = OpFunctionCall %S %conv_S %113
-               OpStore %109 %110
-        %116 = OpAccessChain %_ptr_Workgroup_mat4v2float %w %int_3 %uint_1
-        %117 = OpFunctionCall %mat4v2float %load_u_2_m
+        %113 = OpAccessChain %_ptr_Uniform__arr_S_std140_uint_4 %u %uint_0
+        %114 = OpLoad %_arr_S_std140_uint_4 %113
+        %111 = OpFunctionCall %_arr_S_uint_4 %conv_arr_4_S %114
+               OpStore %w %111
+        %116 = OpAccessChain %_ptr_Workgroup_S %w %int_1
+        %118 = OpAccessChain %_ptr_Uniform_S_std140 %u %uint_0 %uint_2
+        %119 = OpLoad %S_std140 %118
+        %117 = OpFunctionCall %S %conv_S %119
                OpStore %116 %117
-        %120 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1 %uint_1 %118
-        %121 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %39 %uint_2
-        %122 = OpLoad %v2float %121
-        %123 = OpVectorShuffle %v2float %122 %122 1 0
-               OpStore %120 %123
+        %122 = OpAccessChain %_ptr_Workgroup_mat4v2float %w %int_3 %uint_1
+        %123 = OpFunctionCall %mat4v2float %load_u_inner_2_m
+               OpStore %122 %123
+        %126 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1 %uint_1 %124
+        %127 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0 %39 %uint_2
+        %128 = OpLoad %v2float %127
+        %129 = OpVectorShuffle %v2float %128 %128 1 0
+               OpStore %126 %129
                OpReturn
                OpFunctionEnd
-          %f = OpFunction %void None %124
-        %126 = OpLabel
-        %128 = OpLoad %uint %local_invocation_index_1
-        %127 = OpFunctionCall %void %f_inner %128
+          %f = OpFunction %void None %130
+        %132 = OpLabel
+        %134 = OpLoad %uint %local_invocation_index_1
+        %133 = OpFunctionCall %void %f_inner %134
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/buffer/uniform/std140/mat4x2/to_workgroup.wgsl.expected.wgsl
rename to test/tint/buffer/uniform/std140/struct/mat4x2/to_workgroup.wgsl.expected.wgsl
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl
new file mode 100644
index 0000000..494e81e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl
@@ -0,0 +1,13 @@
+@group(0) @binding(0) var<uniform> m : mat2x2<f32>;
+
+var<private> counter = 0;
+fn i() -> i32 { counter++; return counter; }
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m   = &m;
+  let p_m_i = &((*p_m)[i()]);
+
+  let l_m   : mat2x2<f32> = *p_m;
+  let l_m_i : vec2<f32>   = *p_m_i;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..4eeea70
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -0,0 +1,27 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[1];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float2x2 tint_symbol(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const int p_m_i_save = i();
+  const float2x2 l_m = tint_symbol(m, 0u);
+  const uint scalar_offset_2 = ((8u * uint(p_m_i_save))) / 4;
+  uint4 ubo_load_2 = m[scalar_offset_2 / 4];
+  const float2 l_m_i = asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..4eeea70
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -0,0 +1,27 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[1];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float2x2 tint_symbol(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const int p_m_i_save = i();
+  const float2x2 l_m = tint_symbol(m, 0u);
+  const uint scalar_offset_2 = ((8u * uint(p_m_i_save))) / 4;
+  uint4 ubo_load_2 = m[scalar_offset_2 / 4];
+  const float2 l_m_i = asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..99bde8b
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,47 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform m_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+} m;
+
+int counter = 0;
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+mat2 load_m_inner() {
+  return mat2(m.inner_0, m.inner_1);
+}
+
+vec2 load_m_inner_p0(uint p0) {
+  switch(p0) {
+    case 0u: {
+      return m.inner_0;
+      break;
+    }
+    case 1u: {
+      return m.inner_1;
+      break;
+    }
+    default: {
+      return vec2(0.0f);
+      break;
+    }
+  }
+}
+
+void f() {
+  mat2 p_m = load_m_inner();
+  int tint_symbol = i();
+  vec2 p_m_i = load_m_inner_p0(uint(tint_symbol));
+  mat2 l_m = load_m_inner();
+  vec2 l_m_i = load_m_inner_p0(uint(tint_symbol));
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl
new file mode 100644
index 0000000..61e6798
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.msl
@@ -0,0 +1,17 @@
+#include <metal_stdlib>
+
+using namespace metal;
+int i() {
+  thread int tint_symbol_1 = 0;
+  tint_symbol_1 = as_type<int>((as_type<uint>(tint_symbol_1) + as_type<uint>(1)));
+  return tint_symbol_1;
+}
+
+kernel void f(const constant float2x2* tint_symbol_2 [[buffer(0)]]) {
+  int const tint_symbol = i();
+  int const p_m_i_save = tint_symbol;
+  float2x2 const l_m = *(tint_symbol_2);
+  float2 const l_m_i = (*(tint_symbol_2))[p_m_i_save];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm
new file mode 100644
index 0000000..a2554c6
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.spvasm
@@ -0,0 +1,89 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 54
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %m_block_std140 "m_block_std140"
+               OpMemberName %m_block_std140 0 "inner_0"
+               OpMemberName %m_block_std140 1 "inner_1"
+               OpName %m "m"
+               OpName %counter "counter"
+               OpName %i "i"
+               OpName %load_m_inner "load_m_inner"
+               OpName %load_m_inner_p0 "load_m_inner_p0"
+               OpName %p0 "p0"
+               OpName %f "f"
+               OpDecorate %m_block_std140 Block
+               OpMemberDecorate %m_block_std140 0 Offset 0
+               OpMemberDecorate %m_block_std140 1 Offset 8
+               OpDecorate %m NonWritable
+               OpDecorate %m DescriptorSet 0
+               OpDecorate %m Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%m_block_std140 = OpTypeStruct %v2float %v2float
+%_ptr_Uniform_m_block_std140 = OpTypePointer Uniform %m_block_std140
+          %m = OpVariable %_ptr_Uniform_m_block_std140 Uniform
+        %int = OpTypeInt 32 1
+          %7 = OpConstantNull %int
+%_ptr_Private_int = OpTypePointer Private %int
+    %counter = OpVariable %_ptr_Private_int Private %7
+         %10 = OpTypeFunction %int
+      %int_1 = OpConstant %int 1
+%mat2v2float = OpTypeMatrix %v2float 2
+         %17 = OpTypeFunction %mat2v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+         %33 = OpTypeFunction %v2float %uint
+         %45 = OpConstantNull %v2float
+       %void = OpTypeVoid
+         %46 = OpTypeFunction %void
+          %i = OpFunction %int None %10
+         %12 = OpLabel
+         %13 = OpLoad %int %counter
+         %15 = OpIAdd %int %13 %int_1
+               OpStore %counter %15
+         %16 = OpLoad %int %counter
+               OpReturnValue %16
+               OpFunctionEnd
+%load_m_inner = OpFunction %mat2v2float None %17
+         %20 = OpLabel
+         %26 = OpAccessChain %_ptr_Uniform_v2float %m %uint_0
+         %27 = OpLoad %v2float %26
+         %30 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %31 = OpLoad %v2float %30
+         %32 = OpCompositeConstruct %mat2v2float %27 %31
+               OpReturnValue %32
+               OpFunctionEnd
+%load_m_inner_p0 = OpFunction %v2float None %33
+         %p0 = OpFunctionParameter %uint
+         %36 = OpLabel
+               OpSelectionMerge %37 None
+               OpSwitch %p0 %38 0 %39 1 %40
+         %39 = OpLabel
+         %41 = OpAccessChain %_ptr_Uniform_v2float %m %uint_0
+         %42 = OpLoad %v2float %41
+               OpReturnValue %42
+         %40 = OpLabel
+         %43 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %44 = OpLoad %v2float %43
+               OpReturnValue %44
+         %38 = OpLabel
+               OpReturnValue %45
+         %37 = OpLabel
+               OpReturnValue %45
+               OpFunctionEnd
+          %f = OpFunction %void None %46
+         %49 = OpLabel
+         %50 = OpFunctionCall %int %i
+         %51 = OpFunctionCall %mat2v2float %load_m_inner
+         %53 = OpBitcast %uint %50
+         %52 = OpFunctionCall %v2float %load_m_inner_p0 %53
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl
new file mode 100644
index 0000000..8218448
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/dynamic_index_via_ptr.wgsl.expected.wgsl
@@ -0,0 +1,16 @@
+@group(0) @binding(0) var<uniform> m : mat2x2<f32>;
+
+var<private> counter = 0;
+
+fn i() -> i32 {
+  counter++;
+  return counter;
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m = &(m);
+  let p_m_i = &((*(p_m))[i()]);
+  let l_m : mat2x2<f32> = *(p_m);
+  let l_m_i : vec2<f32> = *(p_m_i);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl
new file mode 100644
index 0000000..b749a4d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl
@@ -0,0 +1,13 @@
+@group(0) @binding(0) var<uniform> m : mat2x2<f32>;
+
+var<private> counter = 0;
+fn i() -> i32 { counter++; return counter; }
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m   = &m;
+  let p_m_1 = &((*p_m)[1]);
+
+  let l_m   : mat2x2<f32> = *p_m;
+  let l_m_1 : vec2<f32>   = *p_m_1;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..1193c5a
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -0,0 +1,24 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[1];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float2x2 tint_symbol(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x2 l_m = tint_symbol(m, 0u);
+  const float2 l_m_1 = asfloat(m[0].zw);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..1193c5a
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -0,0 +1,24 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[1];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float2x2 tint_symbol(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x2 l_m = tint_symbol(m, 0u);
+  const float2 l_m_1 = asfloat(m[0].zw);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..5c2a99f
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,23 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform m_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+} m;
+
+mat2 load_m_inner() {
+  return mat2(m.inner_0, m.inner_1);
+}
+
+void f() {
+  mat2 p_m = load_m_inner();
+  vec2 p_m_1 = m.inner_1;
+  mat2 l_m = load_m_inner();
+  vec2 l_m_1 = m.inner_1;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.msl
new file mode 100644
index 0000000..6b2c368
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.msl
@@ -0,0 +1,15 @@
+#include <metal_stdlib>
+
+using namespace metal;
+int i() {
+  thread int tint_symbol = 0;
+  tint_symbol = as_type<int>((as_type<uint>(tint_symbol) + as_type<uint>(1)));
+  return tint_symbol;
+}
+
+kernel void f(const constant float2x2* tint_symbol_1 [[buffer(0)]]) {
+  float2x2 const l_m = *(tint_symbol_1);
+  float2 const l_m_1 = (*(tint_symbol_1))[1];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.spvasm
new file mode 100644
index 0000000..51af351
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 40
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %m_block_std140 "m_block_std140"
+               OpMemberName %m_block_std140 0 "inner_0"
+               OpMemberName %m_block_std140 1 "inner_1"
+               OpName %m "m"
+               OpName %counter "counter"
+               OpName %i "i"
+               OpName %load_m_inner "load_m_inner"
+               OpName %f "f"
+               OpDecorate %m_block_std140 Block
+               OpMemberDecorate %m_block_std140 0 Offset 0
+               OpMemberDecorate %m_block_std140 1 Offset 8
+               OpDecorate %m NonWritable
+               OpDecorate %m DescriptorSet 0
+               OpDecorate %m Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%m_block_std140 = OpTypeStruct %v2float %v2float
+%_ptr_Uniform_m_block_std140 = OpTypePointer Uniform %m_block_std140
+          %m = OpVariable %_ptr_Uniform_m_block_std140 Uniform
+        %int = OpTypeInt 32 1
+          %7 = OpConstantNull %int
+%_ptr_Private_int = OpTypePointer Private %int
+    %counter = OpVariable %_ptr_Private_int Private %7
+         %10 = OpTypeFunction %int
+      %int_1 = OpConstant %int 1
+%mat2v2float = OpTypeMatrix %v2float 2
+         %17 = OpTypeFunction %mat2v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+       %void = OpTypeVoid
+         %33 = OpTypeFunction %void
+          %i = OpFunction %int None %10
+         %12 = OpLabel
+         %13 = OpLoad %int %counter
+         %15 = OpIAdd %int %13 %int_1
+               OpStore %counter %15
+         %16 = OpLoad %int %counter
+               OpReturnValue %16
+               OpFunctionEnd
+%load_m_inner = OpFunction %mat2v2float None %17
+         %20 = OpLabel
+         %26 = OpAccessChain %_ptr_Uniform_v2float %m %uint_0
+         %27 = OpLoad %v2float %26
+         %30 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %31 = OpLoad %v2float %30
+         %32 = OpCompositeConstruct %mat2v2float %27 %31
+               OpReturnValue %32
+               OpFunctionEnd
+          %f = OpFunction %void None %33
+         %36 = OpLabel
+         %37 = OpFunctionCall %mat2v2float %load_m_inner
+         %38 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %39 = OpLoad %v2float %38
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.wgsl
new file mode 100644
index 0000000..5c46f6a
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/static_index_via_ptr.wgsl.expected.wgsl
@@ -0,0 +1,16 @@
+@group(0) @binding(0) var<uniform> m : mat2x2<f32>;
+
+var<private> counter = 0;
+
+fn i() -> i32 {
+  counter++;
+  return counter;
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m = &(m);
+  let p_m_1 = &((*(p_m))[1]);
+  let l_m : mat2x2<f32> = *(p_m);
+  let l_m_1 : vec2<f32> = *(p_m_1);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl
new file mode 100644
index 0000000..db062e3
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl
@@ -0,0 +1,8 @@
+@group(0) @binding(0) var<uniform> u : mat2x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    let t = transpose(u);
+    let l = length(u[1]);
+    let a = abs(u[0].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..693985f
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.dxc.hlsl
@@ -0,0 +1,19 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[1];
+};
+
+float2x2 tint_symbol(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x2 t = transpose(tint_symbol(u, 0u));
+  const float l = length(asfloat(u[0].zw));
+  const float a = abs(asfloat(u[0].xy).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..693985f
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.fxc.hlsl
@@ -0,0 +1,19 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[1];
+};
+
+float2x2 tint_symbol(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x2 t = transpose(tint_symbol(u, 0u));
+  const float l = length(asfloat(u[0].zw));
+  const float a = abs(asfloat(u[0].xy).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.glsl
new file mode 100644
index 0000000..734e399
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.glsl
@@ -0,0 +1,22 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+} u;
+
+mat2 load_u_inner() {
+  return mat2(u.inner_0, u.inner_1);
+}
+
+void f() {
+  mat2 t = transpose(load_u_inner());
+  float l = length(u.inner_1);
+  float a = abs(u.inner_0.yx[0u]);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.msl
new file mode 100644
index 0000000..1a4d22e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.msl
@@ -0,0 +1,10 @@
+#include <metal_stdlib>
+
+using namespace metal;
+kernel void f(const constant float2x2* tint_symbol [[buffer(0)]]) {
+  float2x2 const t = transpose(*(tint_symbol));
+  float const l = length((*(tint_symbol))[1]);
+  float const a = fabs(float2((*(tint_symbol))[0]).yx[0]);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.spvasm
new file mode 100644
index 0000000..2659b93
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 38
+; Schema: 0
+               OpCapability Shader
+         %29 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpName %u "u"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat2v2float = OpTypeMatrix %v2float 2
+          %6 = OpTypeFunction %mat2v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+       %void = OpTypeVoid
+         %22 = OpTypeFunction %void
+         %36 = OpConstantNull %uint
+%load_u_inner = OpFunction %mat2v2float None %6
+          %9 = OpLabel
+         %15 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %16 = OpLoad %v2float %15
+         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %20 = OpLoad %v2float %19
+         %21 = OpCompositeConstruct %mat2v2float %16 %20
+               OpReturnValue %21
+               OpFunctionEnd
+          %f = OpFunction %void None %22
+         %25 = OpLabel
+         %27 = OpFunctionCall %mat2v2float %load_u_inner
+         %26 = OpTranspose %mat2v2float %27
+         %30 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %31 = OpLoad %v2float %30
+         %28 = OpExtInst %float %29 Length %31
+         %33 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %34 = OpLoad %v2float %33
+         %35 = OpVectorShuffle %v2float %34 %34 1 0
+         %37 = OpCompositeExtract %float %35 0
+         %32 = OpExtInst %float %29 FAbs %37
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.wgsl
new file mode 100644
index 0000000..21b2b9c
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_builtin.wgsl.expected.wgsl
@@ -0,0 +1,8 @@
+@group(0) @binding(0) var<uniform> u : mat2x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  let t = transpose(u);
+  let l = length(u[1]);
+  let a = abs(u[0].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl
new file mode 100644
index 0000000..f8cb4ea
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl
@@ -0,0 +1,14 @@
+@group(0) @binding(0) var<uniform> u : mat2x2<f32>;
+
+fn a(m : mat2x2<f32>) {}
+fn b(v : vec2<f32>) {}
+fn c(f : f32) {}
+
+@compute @workgroup_size(1)
+fn f() {
+    a(u);
+    b(u[1]);
+    b(u[1].yx);
+    c(u[1].x);
+    c(u[1].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..0f4581e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.dxc.hlsl
@@ -0,0 +1,30 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[1];
+};
+
+void a(float2x2 m) {
+}
+
+void b(float2 v) {
+}
+
+void c(float f_1) {
+}
+
+float2x2 tint_symbol(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  a(tint_symbol(u, 0u));
+  b(asfloat(u[0].zw));
+  b(asfloat(u[0].zw).yx);
+  c(asfloat(u[0].z));
+  c(asfloat(u[0].zw).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..0f4581e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.fxc.hlsl
@@ -0,0 +1,30 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[1];
+};
+
+void a(float2x2 m) {
+}
+
+void b(float2 v) {
+}
+
+void c(float f_1) {
+}
+
+float2x2 tint_symbol(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  a(tint_symbol(u, 0u));
+  b(asfloat(u[0].zw));
+  b(asfloat(u[0].zw).yx);
+  c(asfloat(u[0].z));
+  c(asfloat(u[0].zw).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.glsl
new file mode 100644
index 0000000..161c7ab
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.glsl
@@ -0,0 +1,33 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+} u;
+
+void a(mat2 m) {
+}
+
+void b(vec2 v) {
+}
+
+void c(float f_1) {
+}
+
+mat2 load_u_inner() {
+  return mat2(u.inner_0, u.inner_1);
+}
+
+void f() {
+  a(load_u_inner());
+  b(u.inner_1);
+  b(u.inner_1.yx);
+  c(u.inner_1[0u]);
+  c(u.inner_1.yx[0u]);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.msl
new file mode 100644
index 0000000..f160d72
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.msl
@@ -0,0 +1,21 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void a(float2x2 m) {
+}
+
+void b(float2 v) {
+}
+
+void c(float f_1) {
+}
+
+kernel void f(const constant float2x2* tint_symbol [[buffer(0)]]) {
+  a(*(tint_symbol));
+  b((*(tint_symbol))[1]);
+  b(float2((*(tint_symbol))[1]).yx);
+  c((*(tint_symbol))[1][0]);
+  c(float2((*(tint_symbol))[1]).yx[0]);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.spvasm
new file mode 100644
index 0000000..62a2607
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.spvasm
@@ -0,0 +1,90 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 57
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpName %u "u"
+               OpName %a "a"
+               OpName %m "m"
+               OpName %b "b"
+               OpName %v "v"
+               OpName %c "c"
+               OpName %f_1 "f_1"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+       %void = OpTypeVoid
+%mat2v2float = OpTypeMatrix %v2float 2
+          %6 = OpTypeFunction %void %mat2v2float
+         %12 = OpTypeFunction %void %v2float
+         %16 = OpTypeFunction %void %float
+         %20 = OpTypeFunction %mat2v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+         %35 = OpTypeFunction %void
+         %48 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+          %a = OpFunction %void None %6
+          %m = OpFunctionParameter %mat2v2float
+         %11 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %b = OpFunction %void None %12
+          %v = OpFunctionParameter %v2float
+         %15 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %c = OpFunction %void None %16
+        %f_1 = OpFunctionParameter %float
+         %19 = OpLabel
+               OpReturn
+               OpFunctionEnd
+%load_u_inner = OpFunction %mat2v2float None %20
+         %22 = OpLabel
+         %28 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %29 = OpLoad %v2float %28
+         %32 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %33 = OpLoad %v2float %32
+         %34 = OpCompositeConstruct %mat2v2float %29 %33
+               OpReturnValue %34
+               OpFunctionEnd
+          %f = OpFunction %void None %35
+         %37 = OpLabel
+         %39 = OpFunctionCall %mat2v2float %load_u_inner
+         %38 = OpFunctionCall %void %a %39
+         %41 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %42 = OpLoad %v2float %41
+         %40 = OpFunctionCall %void %b %42
+         %44 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %45 = OpLoad %v2float %44
+         %46 = OpVectorShuffle %v2float %45 %45 1 0
+         %43 = OpFunctionCall %void %b %46
+         %50 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %48
+         %51 = OpLoad %float %50
+         %47 = OpFunctionCall %void %c %51
+         %53 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %54 = OpLoad %v2float %53
+         %55 = OpVectorShuffle %v2float %54 %54 1 0
+         %56 = OpCompositeExtract %float %55 0
+         %52 = OpFunctionCall %void %c %56
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.wgsl
new file mode 100644
index 0000000..d670763
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_fn.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+@group(0) @binding(0) var<uniform> u : mat2x2<f32>;
+
+fn a(m : mat2x2<f32>) {
+}
+
+fn b(v : vec2<f32>) {
+}
+
+fn c(f : f32) {
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  a(u);
+  b(u[1]);
+  b(u[1].yx);
+  c(u[1].x);
+  c(u[1].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl
new file mode 100644
index 0000000..50c4510
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl
@@ -0,0 +1,10 @@
+@group(0) @binding(0) var<uniform> u : mat2x2<f32>;
+var<private> p : mat2x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    p = u;
+    p[1] = u[0];
+    p[1] = u[0].yx;
+    p[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..daa1db4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.dxc.hlsl
@@ -0,0 +1,21 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[1];
+};
+static float2x2 p = float2x2(0.0f, 0.0f, 0.0f, 0.0f);
+
+float2x2 tint_symbol(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  p = tint_symbol(u, 0u);
+  p[1] = asfloat(u[0].xy);
+  p[1] = asfloat(u[0].xy).yx;
+  p[0][1] = asfloat(u[0].z);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..daa1db4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.fxc.hlsl
@@ -0,0 +1,21 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[1];
+};
+static float2x2 p = float2x2(0.0f, 0.0f, 0.0f, 0.0f);
+
+float2x2 tint_symbol(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  p = tint_symbol(u, 0u);
+  p[1] = asfloat(u[0].xy);
+  p[1] = asfloat(u[0].xy).yx;
+  p[0][1] = asfloat(u[0].z);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.glsl
new file mode 100644
index 0000000..cbb8b88
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.glsl
@@ -0,0 +1,24 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+} u;
+
+mat2 p = mat2(0.0f, 0.0f, 0.0f, 0.0f);
+mat2 load_u_inner() {
+  return mat2(u.inner_0, u.inner_1);
+}
+
+void f() {
+  p = load_u_inner();
+  p[1] = u.inner_0;
+  p[1] = u.inner_0.yx;
+  p[0][1] = u.inner_1[0u];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.msl
new file mode 100644
index 0000000..76bf1ad
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.msl
@@ -0,0 +1,12 @@
+#include <metal_stdlib>
+
+using namespace metal;
+kernel void f(const constant float2x2* tint_symbol_1 [[buffer(0)]]) {
+  thread float2x2 tint_symbol = float2x2(0.0f);
+  tint_symbol = *(tint_symbol_1);
+  tint_symbol[1] = (*(tint_symbol_1))[0];
+  tint_symbol[1] = float2((*(tint_symbol_1))[0]).yx;
+  tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.spvasm
new file mode 100644
index 0000000..cb61baf
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.spvasm
@@ -0,0 +1,73 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 47
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpName %u "u"
+               OpName %p "p"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat2v2float = OpTypeMatrix %v2float 2
+%_ptr_Private_mat2v2float = OpTypePointer Private %mat2v2float
+          %9 = OpConstantNull %mat2v2float
+          %p = OpVariable %_ptr_Private_mat2v2float Private %9
+         %10 = OpTypeFunction %mat2v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_Private_v2float = OpTypePointer Private %v2float
+         %40 = OpConstantNull %int
+%_ptr_Private_float = OpTypePointer Private %float
+         %43 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+%load_u_inner = OpFunction %mat2v2float None %10
+         %12 = OpLabel
+         %18 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %19 = OpLoad %v2float %18
+         %22 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %23 = OpLoad %v2float %22
+         %24 = OpCompositeConstruct %mat2v2float %19 %23
+               OpReturnValue %24
+               OpFunctionEnd
+          %f = OpFunction %void None %25
+         %28 = OpLabel
+         %29 = OpFunctionCall %mat2v2float %load_u_inner
+               OpStore %p %29
+         %33 = OpAccessChain %_ptr_Private_v2float %p %int_1
+         %34 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %35 = OpLoad %v2float %34
+               OpStore %33 %35
+         %36 = OpAccessChain %_ptr_Private_v2float %p %int_1
+         %37 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %38 = OpLoad %v2float %37
+         %39 = OpVectorShuffle %v2float %38 %38 1 0
+               OpStore %36 %39
+         %42 = OpAccessChain %_ptr_Private_float %p %40 %int_1
+         %45 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %43
+         %46 = OpLoad %float %45
+               OpStore %42 %46
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.wgsl
new file mode 100644
index 0000000..15e7f58
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_private.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> u : mat2x2<f32>;
+
+var<private> p : mat2x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  p = u;
+  p[1] = u[0];
+  p[1] = u[0].yx;
+  p[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl
new file mode 100644
index 0000000..e7b02ae
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl
@@ -0,0 +1,10 @@
+@group(0) @binding(0) var<uniform> u : mat2x2<f32>;
+@group(0) @binding(1) var<storage, read_write> s : mat2x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    s = u;
+    s[1] = u[0];
+    s[1] = u[0].yx;
+    s[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..9457624
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.dxc.hlsl
@@ -0,0 +1,26 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[1];
+};
+RWByteAddressBuffer s : register(u1, space0);
+
+void tint_symbol(RWByteAddressBuffer buffer, uint offset, float2x2 value) {
+  buffer.Store2((offset + 0u), asuint(value[0u]));
+  buffer.Store2((offset + 8u), asuint(value[1u]));
+}
+
+float2x2 tint_symbol_2(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  tint_symbol(s, 0u, tint_symbol_2(u, 0u));
+  s.Store2(8u, asuint(asfloat(u[0].xy)));
+  s.Store2(8u, asuint(asfloat(u[0].xy).yx));
+  s.Store(4u, asuint(asfloat(u[0].z)));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..9457624
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.fxc.hlsl
@@ -0,0 +1,26 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[1];
+};
+RWByteAddressBuffer s : register(u1, space0);
+
+void tint_symbol(RWByteAddressBuffer buffer, uint offset, float2x2 value) {
+  buffer.Store2((offset + 0u), asuint(value[0u]));
+  buffer.Store2((offset + 8u), asuint(value[1u]));
+}
+
+float2x2 tint_symbol_2(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  tint_symbol(s, 0u, tint_symbol_2(u, 0u));
+  s.Store2(8u, asuint(asfloat(u[0].xy)));
+  s.Store2(8u, asuint(asfloat(u[0].xy).yx));
+  s.Store(4u, asuint(asfloat(u[0].z)));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.glsl
new file mode 100644
index 0000000..c215c51
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.glsl
@@ -0,0 +1,27 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+} u;
+
+layout(binding = 1, std430) buffer u_block_ssbo {
+  mat2 inner;
+} s;
+
+mat2 load_u_inner() {
+  return mat2(u.inner_0, u.inner_1);
+}
+
+void f() {
+  s.inner = load_u_inner();
+  s.inner[1] = u.inner_0;
+  s.inner[1] = u.inner_0.yx;
+  s.inner[0][1] = u.inner_1[0u];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.msl
new file mode 100644
index 0000000..c265005
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.msl
@@ -0,0 +1,11 @@
+#include <metal_stdlib>
+
+using namespace metal;
+kernel void f(device float2x2* tint_symbol [[buffer(1)]], const constant float2x2* tint_symbol_1 [[buffer(0)]]) {
+  *(tint_symbol) = *(tint_symbol_1);
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
+  (*(tint_symbol))[1] = float2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.spvasm
new file mode 100644
index 0000000..f18c153
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.spvasm
@@ -0,0 +1,83 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 49
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpName %u "u"
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %s "s"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %s DescriptorSet 0
+               OpDecorate %s Binding 1
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat2v2float = OpTypeMatrix %v2float 2
+    %u_block = OpTypeStruct %mat2v2float
+%_ptr_StorageBuffer_u_block = OpTypePointer StorageBuffer %u_block
+          %s = OpVariable %_ptr_StorageBuffer_u_block StorageBuffer
+         %10 = OpTypeFunction %mat2v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+%_ptr_StorageBuffer_mat2v2float = OpTypePointer StorageBuffer %mat2v2float
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
+         %42 = OpConstantNull %int
+%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
+         %45 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+%load_u_inner = OpFunction %mat2v2float None %10
+         %12 = OpLabel
+         %18 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %19 = OpLoad %v2float %18
+         %22 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %23 = OpLoad %v2float %22
+         %24 = OpCompositeConstruct %mat2v2float %19 %23
+               OpReturnValue %24
+               OpFunctionEnd
+          %f = OpFunction %void None %25
+         %28 = OpLabel
+         %30 = OpAccessChain %_ptr_StorageBuffer_mat2v2float %s %uint_0
+         %31 = OpFunctionCall %mat2v2float %load_u_inner
+               OpStore %30 %31
+         %35 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1
+         %36 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %37 = OpLoad %v2float %36
+               OpStore %35 %37
+         %38 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1
+         %39 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %40 = OpLoad %v2float %39
+         %41 = OpVectorShuffle %v2float %40 %40 1 0
+               OpStore %38 %41
+         %44 = OpAccessChain %_ptr_StorageBuffer_float %s %uint_0 %42 %int_1
+         %47 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %45
+         %48 = OpLoad %float %47
+               OpStore %44 %48
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.wgsl
new file mode 100644
index 0000000..5693f82
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_storage.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> u : mat2x2<f32>;
+
+@group(0) @binding(1) var<storage, read_write> s : mat2x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  s = u;
+  s[1] = u[0];
+  s[1] = u[0].yx;
+  s[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl
new file mode 100644
index 0000000..429e90f
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl
@@ -0,0 +1,10 @@
+@group(0) @binding(0) var<uniform> u : mat2x2<f32>;
+var<workgroup> w : mat2x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    w = u;
+    w[1] = u[0];
+    w[1] = u[0].yx;
+    w[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..fe32b58
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.dxc.hlsl
@@ -0,0 +1,33 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[1];
+};
+groupshared float2x2 w;
+
+struct tint_symbol_1 {
+  uint local_invocation_index : SV_GroupIndex;
+};
+
+float2x2 tint_symbol_2(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+void f_inner(uint local_invocation_index) {
+  {
+    w = float2x2((0.0f).xx, (0.0f).xx);
+  }
+  GroupMemoryBarrierWithGroupSync();
+  w = tint_symbol_2(u, 0u);
+  w[1] = asfloat(u[0].xy);
+  w[1] = asfloat(u[0].xy).yx;
+  w[0][1] = asfloat(u[0].z);
+}
+
+[numthreads(1, 1, 1)]
+void f(tint_symbol_1 tint_symbol) {
+  f_inner(tint_symbol.local_invocation_index);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..fe32b58
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.fxc.hlsl
@@ -0,0 +1,33 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[1];
+};
+groupshared float2x2 w;
+
+struct tint_symbol_1 {
+  uint local_invocation_index : SV_GroupIndex;
+};
+
+float2x2 tint_symbol_2(uint4 buffer[1], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+}
+
+void f_inner(uint local_invocation_index) {
+  {
+    w = float2x2((0.0f).xx, (0.0f).xx);
+  }
+  GroupMemoryBarrierWithGroupSync();
+  w = tint_symbol_2(u, 0u);
+  w[1] = asfloat(u[0].xy);
+  w[1] = asfloat(u[0].xy).yx;
+  w[0][1] = asfloat(u[0].z);
+}
+
+[numthreads(1, 1, 1)]
+void f(tint_symbol_1 tint_symbol) {
+  f_inner(tint_symbol.local_invocation_index);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.glsl
new file mode 100644
index 0000000..f92860e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.glsl
@@ -0,0 +1,28 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+} u;
+
+shared mat2 w;
+mat2 load_u_inner() {
+  return mat2(u.inner_0, u.inner_1);
+}
+
+void f(uint local_invocation_index) {
+  {
+    w = mat2(vec2(0.0f), vec2(0.0f));
+  }
+  barrier();
+  w = load_u_inner();
+  w[1] = u.inner_0;
+  w[1] = u.inner_0.yx;
+  w[0][1] = u.inner_1[0u];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f(gl_LocalInvocationIndex);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.msl
new file mode 100644
index 0000000..44993bc
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.msl
@@ -0,0 +1,24 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_symbol_5 {
+  float2x2 w;
+};
+
+void f_inner(uint local_invocation_index, threadgroup float2x2* const tint_symbol, const constant float2x2* const tint_symbol_1) {
+  {
+    *(tint_symbol) = float2x2(float2(0.0f), float2(0.0f));
+  }
+  threadgroup_barrier(mem_flags::mem_threadgroup);
+  *(tint_symbol) = *(tint_symbol_1);
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
+  (*(tint_symbol))[1] = float2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+}
+
+kernel void f(const constant float2x2* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+  threadgroup float2x2* const tint_symbol_2 = &((*(tint_symbol_3)).w);
+  f_inner(local_invocation_index, tint_symbol_2, tint_symbol_4);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.spvasm
new file mode 100644
index 0000000..f8352ee
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.spvasm
@@ -0,0 +1,91 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 58
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f" %local_invocation_index_1
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %local_invocation_index_1 "local_invocation_index_1"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpName %u "u"
+               OpName %w "w"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f_inner "f_inner"
+               OpName %local_invocation_index "local_invocation_index"
+               OpName %f "f"
+               OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+       %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat2v2float = OpTypeMatrix %v2float 2
+%_ptr_Workgroup_mat2v2float = OpTypePointer Workgroup %mat2v2float
+          %w = OpVariable %_ptr_Workgroup_mat2v2float Workgroup
+         %12 = OpTypeFunction %mat2v2float
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+       %void = OpTypeVoid
+         %26 = OpTypeFunction %void %uint
+         %31 = OpConstantNull %mat2v2float
+     %uint_2 = OpConstant %uint 2
+   %uint_264 = OpConstant %uint 264
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_Workgroup_v2float = OpTypePointer Workgroup %v2float
+         %46 = OpConstantNull %int
+%_ptr_Workgroup_float = OpTypePointer Workgroup %float
+         %49 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+         %53 = OpTypeFunction %void
+%load_u_inner = OpFunction %mat2v2float None %12
+         %14 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %20 = OpLoad %v2float %19
+         %23 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %24 = OpLoad %v2float %23
+         %25 = OpCompositeConstruct %mat2v2float %20 %24
+               OpReturnValue %25
+               OpFunctionEnd
+    %f_inner = OpFunction %void None %26
+%local_invocation_index = OpFunctionParameter %uint
+         %30 = OpLabel
+               OpStore %w %31
+               OpControlBarrier %uint_2 %uint_2 %uint_264
+         %35 = OpFunctionCall %mat2v2float %load_u_inner
+               OpStore %w %35
+         %39 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1
+         %40 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %41 = OpLoad %v2float %40
+               OpStore %39 %41
+         %42 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1
+         %43 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %44 = OpLoad %v2float %43
+         %45 = OpVectorShuffle %v2float %44 %44 1 0
+               OpStore %42 %45
+         %48 = OpAccessChain %_ptr_Workgroup_float %w %46 %int_1
+         %51 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %49
+         %52 = OpLoad %float %51
+               OpStore %48 %52
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %53
+         %55 = OpLabel
+         %57 = OpLoad %uint %local_invocation_index_1
+         %56 = OpFunctionCall %void %f_inner %57
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.wgsl
new file mode 100644
index 0000000..0a4ef03
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2/to_workgroup.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> u : mat2x2<f32>;
+
+var<workgroup> w : mat2x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  w = u;
+  w[1] = u[0];
+  w[1] = u[0].yx;
+  w[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl
new file mode 100644
index 0000000..6fa268cb
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl
@@ -0,0 +1,13 @@
+@group(0) @binding(0) var<uniform> m : mat3x2<f32>;
+
+var<private> counter = 0;
+fn i() -> i32 { counter++; return counter; }
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m   = &m;
+  let p_m_i = &((*p_m)[i()]);
+
+  let l_m   : mat3x2<f32> = *p_m;
+  let l_m_i : vec2<f32>   = *p_m_i;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..4e7e2c6
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -0,0 +1,29 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[2];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const int p_m_i_save = i();
+  const float3x2 l_m = tint_symbol(m, 0u);
+  const uint scalar_offset_3 = ((8u * uint(p_m_i_save))) / 4;
+  uint4 ubo_load_3 = m[scalar_offset_3 / 4];
+  const float2 l_m_i = asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..4e7e2c6
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -0,0 +1,29 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[2];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const int p_m_i_save = i();
+  const float3x2 l_m = tint_symbol(m, 0u);
+  const uint scalar_offset_3 = ((8u * uint(p_m_i_save))) / 4;
+  uint4 ubo_load_3 = m[scalar_offset_3 / 4];
+  const float2 l_m_i = asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..4a9523d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,52 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform m_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+} m;
+
+int counter = 0;
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+mat3x2 load_m_inner() {
+  return mat3x2(m.inner_0, m.inner_1, m.inner_2);
+}
+
+vec2 load_m_inner_p0(uint p0) {
+  switch(p0) {
+    case 0u: {
+      return m.inner_0;
+      break;
+    }
+    case 1u: {
+      return m.inner_1;
+      break;
+    }
+    case 2u: {
+      return m.inner_2;
+      break;
+    }
+    default: {
+      return vec2(0.0f);
+      break;
+    }
+  }
+}
+
+void f() {
+  mat3x2 p_m = load_m_inner();
+  int tint_symbol = i();
+  vec2 p_m_i = load_m_inner_p0(uint(tint_symbol));
+  mat3x2 l_m = load_m_inner();
+  vec2 l_m_i = load_m_inner_p0(uint(tint_symbol));
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.msl
new file mode 100644
index 0000000..ccda765
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.msl
@@ -0,0 +1,17 @@
+#include <metal_stdlib>
+
+using namespace metal;
+int i() {
+  thread int tint_symbol_1 = 0;
+  tint_symbol_1 = as_type<int>((as_type<uint>(tint_symbol_1) + as_type<uint>(1)));
+  return tint_symbol_1;
+}
+
+kernel void f(const constant float3x2* tint_symbol_2 [[buffer(0)]]) {
+  int const tint_symbol = i();
+  int const p_m_i_save = tint_symbol;
+  float3x2 const l_m = *(tint_symbol_2);
+  float2 const l_m_i = (*(tint_symbol_2))[p_m_i_save];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.spvasm
new file mode 100644
index 0000000..7f537ab
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.spvasm
@@ -0,0 +1,98 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 61
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %m_block_std140 "m_block_std140"
+               OpMemberName %m_block_std140 0 "inner_0"
+               OpMemberName %m_block_std140 1 "inner_1"
+               OpMemberName %m_block_std140 2 "inner_2"
+               OpName %m "m"
+               OpName %counter "counter"
+               OpName %i "i"
+               OpName %load_m_inner "load_m_inner"
+               OpName %load_m_inner_p0 "load_m_inner_p0"
+               OpName %p0 "p0"
+               OpName %f "f"
+               OpDecorate %m_block_std140 Block
+               OpMemberDecorate %m_block_std140 0 Offset 0
+               OpMemberDecorate %m_block_std140 1 Offset 8
+               OpMemberDecorate %m_block_std140 2 Offset 16
+               OpDecorate %m NonWritable
+               OpDecorate %m DescriptorSet 0
+               OpDecorate %m Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%m_block_std140 = OpTypeStruct %v2float %v2float %v2float
+%_ptr_Uniform_m_block_std140 = OpTypePointer Uniform %m_block_std140
+          %m = OpVariable %_ptr_Uniform_m_block_std140 Uniform
+        %int = OpTypeInt 32 1
+          %7 = OpConstantNull %int
+%_ptr_Private_int = OpTypePointer Private %int
+    %counter = OpVariable %_ptr_Private_int Private %7
+         %10 = OpTypeFunction %int
+      %int_1 = OpConstant %int 1
+%mat3v2float = OpTypeMatrix %v2float 3
+         %17 = OpTypeFunction %mat3v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+         %37 = OpTypeFunction %v2float %uint
+         %52 = OpConstantNull %v2float
+       %void = OpTypeVoid
+         %53 = OpTypeFunction %void
+          %i = OpFunction %int None %10
+         %12 = OpLabel
+         %13 = OpLoad %int %counter
+         %15 = OpIAdd %int %13 %int_1
+               OpStore %counter %15
+         %16 = OpLoad %int %counter
+               OpReturnValue %16
+               OpFunctionEnd
+%load_m_inner = OpFunction %mat3v2float None %17
+         %20 = OpLabel
+         %26 = OpAccessChain %_ptr_Uniform_v2float %m %uint_0
+         %27 = OpLoad %v2float %26
+         %30 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %31 = OpLoad %v2float %30
+         %34 = OpAccessChain %_ptr_Uniform_v2float %m %uint_2
+         %35 = OpLoad %v2float %34
+         %36 = OpCompositeConstruct %mat3v2float %27 %31 %35
+               OpReturnValue %36
+               OpFunctionEnd
+%load_m_inner_p0 = OpFunction %v2float None %37
+         %p0 = OpFunctionParameter %uint
+         %40 = OpLabel
+               OpSelectionMerge %41 None
+               OpSwitch %p0 %42 0 %43 1 %44 2 %45
+         %43 = OpLabel
+         %46 = OpAccessChain %_ptr_Uniform_v2float %m %uint_0
+         %47 = OpLoad %v2float %46
+               OpReturnValue %47
+         %44 = OpLabel
+         %48 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %49 = OpLoad %v2float %48
+               OpReturnValue %49
+         %45 = OpLabel
+         %50 = OpAccessChain %_ptr_Uniform_v2float %m %uint_2
+         %51 = OpLoad %v2float %50
+               OpReturnValue %51
+         %42 = OpLabel
+               OpReturnValue %52
+         %41 = OpLabel
+               OpReturnValue %52
+               OpFunctionEnd
+          %f = OpFunction %void None %53
+         %56 = OpLabel
+         %57 = OpFunctionCall %int %i
+         %58 = OpFunctionCall %mat3v2float %load_m_inner
+         %60 = OpBitcast %uint %57
+         %59 = OpFunctionCall %v2float %load_m_inner_p0 %60
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.wgsl
new file mode 100644
index 0000000..a81d554
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/dynamic_index_via_ptr.wgsl.expected.wgsl
@@ -0,0 +1,16 @@
+@group(0) @binding(0) var<uniform> m : mat3x2<f32>;
+
+var<private> counter = 0;
+
+fn i() -> i32 {
+  counter++;
+  return counter;
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m = &(m);
+  let p_m_i = &((*(p_m))[i()]);
+  let l_m : mat3x2<f32> = *(p_m);
+  let l_m_i : vec2<f32> = *(p_m_i);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl
new file mode 100644
index 0000000..5f34576
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl
@@ -0,0 +1,13 @@
+@group(0) @binding(0) var<uniform> m : mat3x2<f32>;
+
+var<private> counter = 0;
+fn i() -> i32 { counter++; return counter; }
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m   = &m;
+  let p_m_1 = &((*p_m)[1]);
+
+  let l_m   : mat3x2<f32> = *p_m;
+  let l_m_1 : vec2<f32>   = *p_m_1;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..fb5623c
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -0,0 +1,26 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[2];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float3x2 l_m = tint_symbol(m, 0u);
+  const float2 l_m_1 = asfloat(m[0].zw);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..fb5623c
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -0,0 +1,26 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[2];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float3x2 l_m = tint_symbol(m, 0u);
+  const float2 l_m_1 = asfloat(m[0].zw);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..19b51d6
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,24 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform m_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+} m;
+
+mat3x2 load_m_inner() {
+  return mat3x2(m.inner_0, m.inner_1, m.inner_2);
+}
+
+void f() {
+  mat3x2 p_m = load_m_inner();
+  vec2 p_m_1 = m.inner_1;
+  mat3x2 l_m = load_m_inner();
+  vec2 l_m_1 = m.inner_1;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.msl
new file mode 100644
index 0000000..df020b7
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.msl
@@ -0,0 +1,15 @@
+#include <metal_stdlib>
+
+using namespace metal;
+int i() {
+  thread int tint_symbol = 0;
+  tint_symbol = as_type<int>((as_type<uint>(tint_symbol) + as_type<uint>(1)));
+  return tint_symbol;
+}
+
+kernel void f(const constant float3x2* tint_symbol_1 [[buffer(0)]]) {
+  float3x2 const l_m = *(tint_symbol_1);
+  float2 const l_m_1 = (*(tint_symbol_1))[1];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.spvasm
new file mode 100644
index 0000000..9635081
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %m_block_std140 "m_block_std140"
+               OpMemberName %m_block_std140 0 "inner_0"
+               OpMemberName %m_block_std140 1 "inner_1"
+               OpMemberName %m_block_std140 2 "inner_2"
+               OpName %m "m"
+               OpName %counter "counter"
+               OpName %i "i"
+               OpName %load_m_inner "load_m_inner"
+               OpName %f "f"
+               OpDecorate %m_block_std140 Block
+               OpMemberDecorate %m_block_std140 0 Offset 0
+               OpMemberDecorate %m_block_std140 1 Offset 8
+               OpMemberDecorate %m_block_std140 2 Offset 16
+               OpDecorate %m NonWritable
+               OpDecorate %m DescriptorSet 0
+               OpDecorate %m Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%m_block_std140 = OpTypeStruct %v2float %v2float %v2float
+%_ptr_Uniform_m_block_std140 = OpTypePointer Uniform %m_block_std140
+          %m = OpVariable %_ptr_Uniform_m_block_std140 Uniform
+        %int = OpTypeInt 32 1
+          %7 = OpConstantNull %int
+%_ptr_Private_int = OpTypePointer Private %int
+    %counter = OpVariable %_ptr_Private_int Private %7
+         %10 = OpTypeFunction %int
+      %int_1 = OpConstant %int 1
+%mat3v2float = OpTypeMatrix %v2float 3
+         %17 = OpTypeFunction %mat3v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+       %void = OpTypeVoid
+         %37 = OpTypeFunction %void
+          %i = OpFunction %int None %10
+         %12 = OpLabel
+         %13 = OpLoad %int %counter
+         %15 = OpIAdd %int %13 %int_1
+               OpStore %counter %15
+         %16 = OpLoad %int %counter
+               OpReturnValue %16
+               OpFunctionEnd
+%load_m_inner = OpFunction %mat3v2float None %17
+         %20 = OpLabel
+         %26 = OpAccessChain %_ptr_Uniform_v2float %m %uint_0
+         %27 = OpLoad %v2float %26
+         %30 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %31 = OpLoad %v2float %30
+         %34 = OpAccessChain %_ptr_Uniform_v2float %m %uint_2
+         %35 = OpLoad %v2float %34
+         %36 = OpCompositeConstruct %mat3v2float %27 %31 %35
+               OpReturnValue %36
+               OpFunctionEnd
+          %f = OpFunction %void None %37
+         %40 = OpLabel
+         %41 = OpFunctionCall %mat3v2float %load_m_inner
+         %42 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %43 = OpLoad %v2float %42
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.wgsl
new file mode 100644
index 0000000..000555e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/static_index_via_ptr.wgsl.expected.wgsl
@@ -0,0 +1,16 @@
+@group(0) @binding(0) var<uniform> m : mat3x2<f32>;
+
+var<private> counter = 0;
+
+fn i() -> i32 {
+  counter++;
+  return counter;
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m = &(m);
+  let p_m_1 = &((*(p_m))[1]);
+  let l_m : mat3x2<f32> = *(p_m);
+  let l_m_1 : vec2<f32> = *(p_m_1);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl
new file mode 100644
index 0000000..373c031
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl
@@ -0,0 +1,8 @@
+@group(0) @binding(0) var<uniform> u : mat3x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    let t = transpose(u);
+    let l = length(u[1]);
+    let a = abs(u[0].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..b94dd86
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.dxc.hlsl
@@ -0,0 +1,21 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+
+float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x3 t = transpose(tint_symbol(u, 0u));
+  const float l = length(asfloat(u[0].zw));
+  const float a = abs(asfloat(u[0].xy).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..b94dd86
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.fxc.hlsl
@@ -0,0 +1,21 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+
+float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x3 t = transpose(tint_symbol(u, 0u));
+  const float l = length(asfloat(u[0].zw));
+  const float a = abs(asfloat(u[0].xy).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.glsl
new file mode 100644
index 0000000..b8b37ba
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.glsl
@@ -0,0 +1,23 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+} u;
+
+mat3x2 load_u_inner() {
+  return mat3x2(u.inner_0, u.inner_1, u.inner_2);
+}
+
+void f() {
+  mat2x3 t = transpose(load_u_inner());
+  float l = length(u.inner_1);
+  float a = abs(u.inner_0.yx[0u]);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.msl
new file mode 100644
index 0000000..009f12e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.msl
@@ -0,0 +1,10 @@
+#include <metal_stdlib>
+
+using namespace metal;
+kernel void f(const constant float3x2* tint_symbol [[buffer(0)]]) {
+  float2x3 const t = transpose(*(tint_symbol));
+  float const l = length((*(tint_symbol))[1]);
+  float const a = fabs(float2((*(tint_symbol))[0]).yx[0]);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.spvasm
new file mode 100644
index 0000000..dedf489
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+               OpCapability Shader
+         %35 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
+               OpName %u "u"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat3v2float = OpTypeMatrix %v2float 3
+          %6 = OpTypeFunction %mat3v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+       %void = OpTypeVoid
+         %26 = OpTypeFunction %void
+    %v3float = OpTypeVector %float 3
+%mat2v3float = OpTypeMatrix %v3float 2
+         %42 = OpConstantNull %uint
+%load_u_inner = OpFunction %mat3v2float None %6
+          %9 = OpLabel
+         %15 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %16 = OpLoad %v2float %15
+         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %20 = OpLoad %v2float %19
+         %23 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %24 = OpLoad %v2float %23
+         %25 = OpCompositeConstruct %mat3v2float %16 %20 %24
+               OpReturnValue %25
+               OpFunctionEnd
+          %f = OpFunction %void None %26
+         %29 = OpLabel
+         %33 = OpFunctionCall %mat3v2float %load_u_inner
+         %30 = OpTranspose %mat2v3float %33
+         %36 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %37 = OpLoad %v2float %36
+         %34 = OpExtInst %float %35 Length %37
+         %39 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %40 = OpLoad %v2float %39
+         %41 = OpVectorShuffle %v2float %40 %40 1 0
+         %43 = OpCompositeExtract %float %41 0
+         %38 = OpExtInst %float %35 FAbs %43
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.wgsl
new file mode 100644
index 0000000..185376d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_builtin.wgsl.expected.wgsl
@@ -0,0 +1,8 @@
+@group(0) @binding(0) var<uniform> u : mat3x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  let t = transpose(u);
+  let l = length(u[1]);
+  let a = abs(u[0].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl
new file mode 100644
index 0000000..e5391c5
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl
@@ -0,0 +1,14 @@
+@group(0) @binding(0) var<uniform> u : mat3x2<f32>;
+
+fn a(m : mat3x2<f32>) {}
+fn b(v : vec2<f32>) {}
+fn c(f : f32) {}
+
+@compute @workgroup_size(1)
+fn f() {
+    a(u);
+    b(u[1]);
+    b(u[1].yx);
+    c(u[1].x);
+    c(u[1].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..029fe0a
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.dxc.hlsl
@@ -0,0 +1,32 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+
+void a(float3x2 m) {
+}
+
+void b(float2 v) {
+}
+
+void c(float f_1) {
+}
+
+float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  a(tint_symbol(u, 0u));
+  b(asfloat(u[0].zw));
+  b(asfloat(u[0].zw).yx);
+  c(asfloat(u[0].z));
+  c(asfloat(u[0].zw).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..029fe0a
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.fxc.hlsl
@@ -0,0 +1,32 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+
+void a(float3x2 m) {
+}
+
+void b(float2 v) {
+}
+
+void c(float f_1) {
+}
+
+float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  a(tint_symbol(u, 0u));
+  b(asfloat(u[0].zw));
+  b(asfloat(u[0].zw).yx);
+  c(asfloat(u[0].z));
+  c(asfloat(u[0].zw).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.glsl
new file mode 100644
index 0000000..f3d607d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.glsl
@@ -0,0 +1,34 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+} u;
+
+void a(mat3x2 m) {
+}
+
+void b(vec2 v) {
+}
+
+void c(float f_1) {
+}
+
+mat3x2 load_u_inner() {
+  return mat3x2(u.inner_0, u.inner_1, u.inner_2);
+}
+
+void f() {
+  a(load_u_inner());
+  b(u.inner_1);
+  b(u.inner_1.yx);
+  c(u.inner_1[0u]);
+  c(u.inner_1.yx[0u]);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.msl
new file mode 100644
index 0000000..278a0f4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.msl
@@ -0,0 +1,21 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void a(float3x2 m) {
+}
+
+void b(float2 v) {
+}
+
+void c(float f_1) {
+}
+
+kernel void f(const constant float3x2* tint_symbol [[buffer(0)]]) {
+  a(*(tint_symbol));
+  b((*(tint_symbol))[1]);
+  b(float2((*(tint_symbol))[1]).yx);
+  c((*(tint_symbol))[1][0]);
+  c(float2((*(tint_symbol))[1]).yx[0]);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.spvasm
new file mode 100644
index 0000000..d602c8d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.spvasm
@@ -0,0 +1,95 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 61
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
+               OpName %u "u"
+               OpName %a "a"
+               OpName %m "m"
+               OpName %b "b"
+               OpName %v "v"
+               OpName %c "c"
+               OpName %f_1 "f_1"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+       %void = OpTypeVoid
+%mat3v2float = OpTypeMatrix %v2float 3
+          %6 = OpTypeFunction %void %mat3v2float
+         %12 = OpTypeFunction %void %v2float
+         %16 = OpTypeFunction %void %float
+         %20 = OpTypeFunction %mat3v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+         %39 = OpTypeFunction %void
+         %52 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+          %a = OpFunction %void None %6
+          %m = OpFunctionParameter %mat3v2float
+         %11 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %b = OpFunction %void None %12
+          %v = OpFunctionParameter %v2float
+         %15 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %c = OpFunction %void None %16
+        %f_1 = OpFunctionParameter %float
+         %19 = OpLabel
+               OpReturn
+               OpFunctionEnd
+%load_u_inner = OpFunction %mat3v2float None %20
+         %22 = OpLabel
+         %28 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %29 = OpLoad %v2float %28
+         %32 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %33 = OpLoad %v2float %32
+         %36 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %37 = OpLoad %v2float %36
+         %38 = OpCompositeConstruct %mat3v2float %29 %33 %37
+               OpReturnValue %38
+               OpFunctionEnd
+          %f = OpFunction %void None %39
+         %41 = OpLabel
+         %43 = OpFunctionCall %mat3v2float %load_u_inner
+         %42 = OpFunctionCall %void %a %43
+         %45 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %46 = OpLoad %v2float %45
+         %44 = OpFunctionCall %void %b %46
+         %48 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %49 = OpLoad %v2float %48
+         %50 = OpVectorShuffle %v2float %49 %49 1 0
+         %47 = OpFunctionCall %void %b %50
+         %54 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %52
+         %55 = OpLoad %float %54
+         %51 = OpFunctionCall %void %c %55
+         %57 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %58 = OpLoad %v2float %57
+         %59 = OpVectorShuffle %v2float %58 %58 1 0
+         %60 = OpCompositeExtract %float %59 0
+         %56 = OpFunctionCall %void %c %60
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.wgsl
new file mode 100644
index 0000000..d5a7a12
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_fn.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+@group(0) @binding(0) var<uniform> u : mat3x2<f32>;
+
+fn a(m : mat3x2<f32>) {
+}
+
+fn b(v : vec2<f32>) {
+}
+
+fn c(f : f32) {
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  a(u);
+  b(u[1]);
+  b(u[1].yx);
+  c(u[1].x);
+  c(u[1].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl
new file mode 100644
index 0000000..a8872a4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl
@@ -0,0 +1,10 @@
+@group(0) @binding(0) var<uniform> u : mat3x2<f32>;
+var<private> p : mat3x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    p = u;
+    p[1] = u[0];
+    p[1] = u[0].yx;
+    p[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..7915694
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.dxc.hlsl
@@ -0,0 +1,23 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+static float3x2 p = float3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+
+float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  p = tint_symbol(u, 0u);
+  p[1] = asfloat(u[0].xy);
+  p[1] = asfloat(u[0].xy).yx;
+  p[0][1] = asfloat(u[0].z);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..7915694
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.fxc.hlsl
@@ -0,0 +1,23 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+static float3x2 p = float3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+
+float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  p = tint_symbol(u, 0u);
+  p[1] = asfloat(u[0].xy);
+  p[1] = asfloat(u[0].xy).yx;
+  p[0][1] = asfloat(u[0].z);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.glsl
new file mode 100644
index 0000000..053233e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.glsl
@@ -0,0 +1,25 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+} u;
+
+mat3x2 p = mat3x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+mat3x2 load_u_inner() {
+  return mat3x2(u.inner_0, u.inner_1, u.inner_2);
+}
+
+void f() {
+  p = load_u_inner();
+  p[1] = u.inner_0;
+  p[1] = u.inner_0.yx;
+  p[0][1] = u.inner_1[0u];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.msl
new file mode 100644
index 0000000..c95e5b0
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.msl
@@ -0,0 +1,12 @@
+#include <metal_stdlib>
+
+using namespace metal;
+kernel void f(const constant float3x2* tint_symbol_1 [[buffer(0)]]) {
+  thread float3x2 tint_symbol = float3x2(0.0f);
+  tint_symbol = *(tint_symbol_1);
+  tint_symbol[1] = (*(tint_symbol_1))[0];
+  tint_symbol[1] = float2((*(tint_symbol_1))[0]).yx;
+  tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.spvasm
new file mode 100644
index 0000000..577ef4f
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.spvasm
@@ -0,0 +1,78 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 51
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
+               OpName %u "u"
+               OpName %p "p"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat3v2float = OpTypeMatrix %v2float 3
+%_ptr_Private_mat3v2float = OpTypePointer Private %mat3v2float
+          %9 = OpConstantNull %mat3v2float
+          %p = OpVariable %_ptr_Private_mat3v2float Private %9
+         %10 = OpTypeFunction %mat3v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+       %void = OpTypeVoid
+         %29 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_Private_v2float = OpTypePointer Private %v2float
+         %44 = OpConstantNull %int
+%_ptr_Private_float = OpTypePointer Private %float
+         %47 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+%load_u_inner = OpFunction %mat3v2float None %10
+         %12 = OpLabel
+         %18 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %19 = OpLoad %v2float %18
+         %22 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %23 = OpLoad %v2float %22
+         %26 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %27 = OpLoad %v2float %26
+         %28 = OpCompositeConstruct %mat3v2float %19 %23 %27
+               OpReturnValue %28
+               OpFunctionEnd
+          %f = OpFunction %void None %29
+         %32 = OpLabel
+         %33 = OpFunctionCall %mat3v2float %load_u_inner
+               OpStore %p %33
+         %37 = OpAccessChain %_ptr_Private_v2float %p %int_1
+         %38 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %39 = OpLoad %v2float %38
+               OpStore %37 %39
+         %40 = OpAccessChain %_ptr_Private_v2float %p %int_1
+         %41 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %42 = OpLoad %v2float %41
+         %43 = OpVectorShuffle %v2float %42 %42 1 0
+               OpStore %40 %43
+         %46 = OpAccessChain %_ptr_Private_float %p %44 %int_1
+         %49 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %47
+         %50 = OpLoad %float %49
+               OpStore %46 %50
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.wgsl
new file mode 100644
index 0000000..8b63b6f
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_private.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> u : mat3x2<f32>;
+
+var<private> p : mat3x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  p = u;
+  p[1] = u[0];
+  p[1] = u[0].yx;
+  p[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl
new file mode 100644
index 0000000..b36b87d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl
@@ -0,0 +1,10 @@
+@group(0) @binding(0) var<uniform> u : mat3x2<f32>;
+@group(0) @binding(1) var<storage, read_write> s : mat3x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    s = u;
+    s[1] = u[0];
+    s[1] = u[0].yx;
+    s[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..f469a95
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.dxc.hlsl
@@ -0,0 +1,29 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+RWByteAddressBuffer s : register(u1, space0);
+
+void tint_symbol(RWByteAddressBuffer buffer, uint offset, float3x2 value) {
+  buffer.Store2((offset + 0u), asuint(value[0u]));
+  buffer.Store2((offset + 8u), asuint(value[1u]));
+  buffer.Store2((offset + 16u), asuint(value[2u]));
+}
+
+float3x2 tint_symbol_2(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  tint_symbol(s, 0u, tint_symbol_2(u, 0u));
+  s.Store2(8u, asuint(asfloat(u[0].xy)));
+  s.Store2(8u, asuint(asfloat(u[0].xy).yx));
+  s.Store(4u, asuint(asfloat(u[0].z)));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..f469a95
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.fxc.hlsl
@@ -0,0 +1,29 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+RWByteAddressBuffer s : register(u1, space0);
+
+void tint_symbol(RWByteAddressBuffer buffer, uint offset, float3x2 value) {
+  buffer.Store2((offset + 0u), asuint(value[0u]));
+  buffer.Store2((offset + 8u), asuint(value[1u]));
+  buffer.Store2((offset + 16u), asuint(value[2u]));
+}
+
+float3x2 tint_symbol_2(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  tint_symbol(s, 0u, tint_symbol_2(u, 0u));
+  s.Store2(8u, asuint(asfloat(u[0].xy)));
+  s.Store2(8u, asuint(asfloat(u[0].xy).yx));
+  s.Store(4u, asuint(asfloat(u[0].z)));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.glsl
new file mode 100644
index 0000000..036b149
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.glsl
@@ -0,0 +1,28 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+} u;
+
+layout(binding = 1, std430) buffer u_block_ssbo {
+  mat3x2 inner;
+} s;
+
+mat3x2 load_u_inner() {
+  return mat3x2(u.inner_0, u.inner_1, u.inner_2);
+}
+
+void f() {
+  s.inner = load_u_inner();
+  s.inner[1] = u.inner_0;
+  s.inner[1] = u.inner_0.yx;
+  s.inner[0][1] = u.inner_1[0u];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.msl
new file mode 100644
index 0000000..2d27746
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.msl
@@ -0,0 +1,11 @@
+#include <metal_stdlib>
+
+using namespace metal;
+kernel void f(device float3x2* tint_symbol [[buffer(1)]], const constant float3x2* tint_symbol_1 [[buffer(0)]]) {
+  *(tint_symbol) = *(tint_symbol_1);
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
+  (*(tint_symbol))[1] = float2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.spvasm
new file mode 100644
index 0000000..4c1c906
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.spvasm
@@ -0,0 +1,88 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 53
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
+               OpName %u "u"
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %s "s"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %s DescriptorSet 0
+               OpDecorate %s Binding 1
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat3v2float = OpTypeMatrix %v2float 3
+    %u_block = OpTypeStruct %mat3v2float
+%_ptr_StorageBuffer_u_block = OpTypePointer StorageBuffer %u_block
+          %s = OpVariable %_ptr_StorageBuffer_u_block StorageBuffer
+         %10 = OpTypeFunction %mat3v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+       %void = OpTypeVoid
+         %29 = OpTypeFunction %void
+%_ptr_StorageBuffer_mat3v2float = OpTypePointer StorageBuffer %mat3v2float
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
+         %46 = OpConstantNull %int
+%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
+         %49 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+%load_u_inner = OpFunction %mat3v2float None %10
+         %12 = OpLabel
+         %18 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %19 = OpLoad %v2float %18
+         %22 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %23 = OpLoad %v2float %22
+         %26 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %27 = OpLoad %v2float %26
+         %28 = OpCompositeConstruct %mat3v2float %19 %23 %27
+               OpReturnValue %28
+               OpFunctionEnd
+          %f = OpFunction %void None %29
+         %32 = OpLabel
+         %34 = OpAccessChain %_ptr_StorageBuffer_mat3v2float %s %uint_0
+         %35 = OpFunctionCall %mat3v2float %load_u_inner
+               OpStore %34 %35
+         %39 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1
+         %40 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %41 = OpLoad %v2float %40
+               OpStore %39 %41
+         %42 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1
+         %43 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %44 = OpLoad %v2float %43
+         %45 = OpVectorShuffle %v2float %44 %44 1 0
+               OpStore %42 %45
+         %48 = OpAccessChain %_ptr_StorageBuffer_float %s %uint_0 %46 %int_1
+         %51 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %49
+         %52 = OpLoad %float %51
+               OpStore %48 %52
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.wgsl
new file mode 100644
index 0000000..8258072
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_storage.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> u : mat3x2<f32>;
+
+@group(0) @binding(1) var<storage, read_write> s : mat3x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  s = u;
+  s[1] = u[0];
+  s[1] = u[0].yx;
+  s[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl
new file mode 100644
index 0000000..53b2d35
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl
@@ -0,0 +1,10 @@
+@group(0) @binding(0) var<uniform> u : mat3x2<f32>;
+var<workgroup> w : mat3x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    w = u;
+    w[1] = u[0];
+    w[1] = u[0].yx;
+    w[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..745a646
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.dxc.hlsl
@@ -0,0 +1,35 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+groupshared float3x2 w;
+
+struct tint_symbol_1 {
+  uint local_invocation_index : SV_GroupIndex;
+};
+
+float3x2 tint_symbol_2(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+void f_inner(uint local_invocation_index) {
+  {
+    w = float3x2((0.0f).xx, (0.0f).xx, (0.0f).xx);
+  }
+  GroupMemoryBarrierWithGroupSync();
+  w = tint_symbol_2(u, 0u);
+  w[1] = asfloat(u[0].xy);
+  w[1] = asfloat(u[0].xy).yx;
+  w[0][1] = asfloat(u[0].z);
+}
+
+[numthreads(1, 1, 1)]
+void f(tint_symbol_1 tint_symbol) {
+  f_inner(tint_symbol.local_invocation_index);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..745a646
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.fxc.hlsl
@@ -0,0 +1,35 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+groupshared float3x2 w;
+
+struct tint_symbol_1 {
+  uint local_invocation_index : SV_GroupIndex;
+};
+
+float3x2 tint_symbol_2(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+}
+
+void f_inner(uint local_invocation_index) {
+  {
+    w = float3x2((0.0f).xx, (0.0f).xx, (0.0f).xx);
+  }
+  GroupMemoryBarrierWithGroupSync();
+  w = tint_symbol_2(u, 0u);
+  w[1] = asfloat(u[0].xy);
+  w[1] = asfloat(u[0].xy).yx;
+  w[0][1] = asfloat(u[0].z);
+}
+
+[numthreads(1, 1, 1)]
+void f(tint_symbol_1 tint_symbol) {
+  f_inner(tint_symbol.local_invocation_index);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.glsl
new file mode 100644
index 0000000..58b1410
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.glsl
@@ -0,0 +1,29 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+} u;
+
+shared mat3x2 w;
+mat3x2 load_u_inner() {
+  return mat3x2(u.inner_0, u.inner_1, u.inner_2);
+}
+
+void f(uint local_invocation_index) {
+  {
+    w = mat3x2(vec2(0.0f), vec2(0.0f), vec2(0.0f));
+  }
+  barrier();
+  w = load_u_inner();
+  w[1] = u.inner_0;
+  w[1] = u.inner_0.yx;
+  w[0][1] = u.inner_1[0u];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f(gl_LocalInvocationIndex);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.msl
new file mode 100644
index 0000000..59f976e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.msl
@@ -0,0 +1,24 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_symbol_5 {
+  float3x2 w;
+};
+
+void f_inner(uint local_invocation_index, threadgroup float3x2* const tint_symbol, const constant float3x2* const tint_symbol_1) {
+  {
+    *(tint_symbol) = float3x2(float2(0.0f), float2(0.0f), float2(0.0f));
+  }
+  threadgroup_barrier(mem_flags::mem_threadgroup);
+  *(tint_symbol) = *(tint_symbol_1);
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
+  (*(tint_symbol))[1] = float2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+}
+
+kernel void f(const constant float3x2* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+  threadgroup float3x2* const tint_symbol_2 = &((*(tint_symbol_3)).w);
+  f_inner(local_invocation_index, tint_symbol_2, tint_symbol_4);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.spvasm
new file mode 100644
index 0000000..998e868
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.spvasm
@@ -0,0 +1,95 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 61
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f" %local_invocation_index_1
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %local_invocation_index_1 "local_invocation_index_1"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
+               OpName %u "u"
+               OpName %w "w"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f_inner "f_inner"
+               OpName %local_invocation_index "local_invocation_index"
+               OpName %f "f"
+               OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+       %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat3v2float = OpTypeMatrix %v2float 3
+%_ptr_Workgroup_mat3v2float = OpTypePointer Workgroup %mat3v2float
+          %w = OpVariable %_ptr_Workgroup_mat3v2float Workgroup
+         %12 = OpTypeFunction %mat3v2float
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+       %void = OpTypeVoid
+         %30 = OpTypeFunction %void %uint
+         %35 = OpConstantNull %mat3v2float
+   %uint_264 = OpConstant %uint 264
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_Workgroup_v2float = OpTypePointer Workgroup %v2float
+         %49 = OpConstantNull %int
+%_ptr_Workgroup_float = OpTypePointer Workgroup %float
+         %52 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+         %56 = OpTypeFunction %void
+%load_u_inner = OpFunction %mat3v2float None %12
+         %14 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %20 = OpLoad %v2float %19
+         %23 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %24 = OpLoad %v2float %23
+         %27 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %28 = OpLoad %v2float %27
+         %29 = OpCompositeConstruct %mat3v2float %20 %24 %28
+               OpReturnValue %29
+               OpFunctionEnd
+    %f_inner = OpFunction %void None %30
+%local_invocation_index = OpFunctionParameter %uint
+         %34 = OpLabel
+               OpStore %w %35
+               OpControlBarrier %uint_2 %uint_2 %uint_264
+         %38 = OpFunctionCall %mat3v2float %load_u_inner
+               OpStore %w %38
+         %42 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1
+         %43 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %44 = OpLoad %v2float %43
+               OpStore %42 %44
+         %45 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1
+         %46 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %47 = OpLoad %v2float %46
+         %48 = OpVectorShuffle %v2float %47 %47 1 0
+               OpStore %45 %48
+         %51 = OpAccessChain %_ptr_Workgroup_float %w %49 %int_1
+         %54 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %52
+         %55 = OpLoad %float %54
+               OpStore %51 %55
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %56
+         %58 = OpLabel
+         %60 = OpLoad %uint %local_invocation_index_1
+         %59 = OpFunctionCall %void %f_inner %60
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.wgsl
new file mode 100644
index 0000000..ef00924
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2/to_workgroup.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> u : mat3x2<f32>;
+
+var<workgroup> w : mat3x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  w = u;
+  w[1] = u[0];
+  w[1] = u[0].yx;
+  w[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl
new file mode 100644
index 0000000..cddfe9e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl
@@ -0,0 +1,13 @@
+@group(0) @binding(0) var<uniform> m : mat4x2<f32>;
+
+var<private> counter = 0;
+fn i() -> i32 { counter++; return counter; }
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m   = &m;
+  let p_m_i = &((*p_m)[i()]);
+
+  let l_m   : mat4x2<f32> = *p_m;
+  let l_m_i : vec2<f32>   = *p_m_i;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..1f128d5
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -0,0 +1,31 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[2];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float4x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const int p_m_i_save = i();
+  const float4x2 l_m = tint_symbol(m, 0u);
+  const uint scalar_offset_4 = ((8u * uint(p_m_i_save))) / 4;
+  uint4 ubo_load_4 = m[scalar_offset_4 / 4];
+  const float2 l_m_i = asfloat(((scalar_offset_4 & 2) ? ubo_load_4.zw : ubo_load_4.xy));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..1f128d5
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -0,0 +1,31 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[2];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float4x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const int p_m_i_save = i();
+  const float4x2 l_m = tint_symbol(m, 0u);
+  const uint scalar_offset_4 = ((8u * uint(p_m_i_save))) / 4;
+  uint4 ubo_load_4 = m[scalar_offset_4 / 4];
+  const float2 l_m_i = asfloat(((scalar_offset_4 & 2) ? ubo_load_4.zw : ubo_load_4.xy));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..3d6190b
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,57 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform m_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+  vec2 inner_3;
+} m;
+
+int counter = 0;
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+mat4x2 load_m_inner() {
+  return mat4x2(m.inner_0, m.inner_1, m.inner_2, m.inner_3);
+}
+
+vec2 load_m_inner_p0(uint p0) {
+  switch(p0) {
+    case 0u: {
+      return m.inner_0;
+      break;
+    }
+    case 1u: {
+      return m.inner_1;
+      break;
+    }
+    case 2u: {
+      return m.inner_2;
+      break;
+    }
+    case 3u: {
+      return m.inner_3;
+      break;
+    }
+    default: {
+      return vec2(0.0f);
+      break;
+    }
+  }
+}
+
+void f() {
+  mat4x2 p_m = load_m_inner();
+  int tint_symbol = i();
+  vec2 p_m_i = load_m_inner_p0(uint(tint_symbol));
+  mat4x2 l_m = load_m_inner();
+  vec2 l_m_i = load_m_inner_p0(uint(tint_symbol));
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl
new file mode 100644
index 0000000..ba9e110
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.msl
@@ -0,0 +1,17 @@
+#include <metal_stdlib>
+
+using namespace metal;
+int i() {
+  thread int tint_symbol_1 = 0;
+  tint_symbol_1 = as_type<int>((as_type<uint>(tint_symbol_1) + as_type<uint>(1)));
+  return tint_symbol_1;
+}
+
+kernel void f(const constant float4x2* tint_symbol_2 [[buffer(0)]]) {
+  int const tint_symbol = i();
+  int const p_m_i_save = tint_symbol;
+  float4x2 const l_m = *(tint_symbol_2);
+  float2 const l_m_i = (*(tint_symbol_2))[p_m_i_save];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm
new file mode 100644
index 0000000..3be1b15
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.spvasm
@@ -0,0 +1,107 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 68
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %m_block_std140 "m_block_std140"
+               OpMemberName %m_block_std140 0 "inner_0"
+               OpMemberName %m_block_std140 1 "inner_1"
+               OpMemberName %m_block_std140 2 "inner_2"
+               OpMemberName %m_block_std140 3 "inner_3"
+               OpName %m "m"
+               OpName %counter "counter"
+               OpName %i "i"
+               OpName %load_m_inner "load_m_inner"
+               OpName %load_m_inner_p0 "load_m_inner_p0"
+               OpName %p0 "p0"
+               OpName %f "f"
+               OpDecorate %m_block_std140 Block
+               OpMemberDecorate %m_block_std140 0 Offset 0
+               OpMemberDecorate %m_block_std140 1 Offset 8
+               OpMemberDecorate %m_block_std140 2 Offset 16
+               OpMemberDecorate %m_block_std140 3 Offset 24
+               OpDecorate %m NonWritable
+               OpDecorate %m DescriptorSet 0
+               OpDecorate %m Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%m_block_std140 = OpTypeStruct %v2float %v2float %v2float %v2float
+%_ptr_Uniform_m_block_std140 = OpTypePointer Uniform %m_block_std140
+          %m = OpVariable %_ptr_Uniform_m_block_std140 Uniform
+        %int = OpTypeInt 32 1
+          %7 = OpConstantNull %int
+%_ptr_Private_int = OpTypePointer Private %int
+    %counter = OpVariable %_ptr_Private_int Private %7
+         %10 = OpTypeFunction %int
+      %int_1 = OpConstant %int 1
+%mat4v2float = OpTypeMatrix %v2float 4
+         %17 = OpTypeFunction %mat4v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+         %41 = OpTypeFunction %v2float %uint
+         %59 = OpConstantNull %v2float
+       %void = OpTypeVoid
+         %60 = OpTypeFunction %void
+          %i = OpFunction %int None %10
+         %12 = OpLabel
+         %13 = OpLoad %int %counter
+         %15 = OpIAdd %int %13 %int_1
+               OpStore %counter %15
+         %16 = OpLoad %int %counter
+               OpReturnValue %16
+               OpFunctionEnd
+%load_m_inner = OpFunction %mat4v2float None %17
+         %20 = OpLabel
+         %26 = OpAccessChain %_ptr_Uniform_v2float %m %uint_0
+         %27 = OpLoad %v2float %26
+         %30 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %31 = OpLoad %v2float %30
+         %34 = OpAccessChain %_ptr_Uniform_v2float %m %uint_2
+         %35 = OpLoad %v2float %34
+         %38 = OpAccessChain %_ptr_Uniform_v2float %m %uint_3
+         %39 = OpLoad %v2float %38
+         %40 = OpCompositeConstruct %mat4v2float %27 %31 %35 %39
+               OpReturnValue %40
+               OpFunctionEnd
+%load_m_inner_p0 = OpFunction %v2float None %41
+         %p0 = OpFunctionParameter %uint
+         %44 = OpLabel
+               OpSelectionMerge %45 None
+               OpSwitch %p0 %46 0 %47 1 %48 2 %49 3 %50
+         %47 = OpLabel
+         %51 = OpAccessChain %_ptr_Uniform_v2float %m %uint_0
+         %52 = OpLoad %v2float %51
+               OpReturnValue %52
+         %48 = OpLabel
+         %53 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %54 = OpLoad %v2float %53
+               OpReturnValue %54
+         %49 = OpLabel
+         %55 = OpAccessChain %_ptr_Uniform_v2float %m %uint_2
+         %56 = OpLoad %v2float %55
+               OpReturnValue %56
+         %50 = OpLabel
+         %57 = OpAccessChain %_ptr_Uniform_v2float %m %uint_3
+         %58 = OpLoad %v2float %57
+               OpReturnValue %58
+         %46 = OpLabel
+               OpReturnValue %59
+         %45 = OpLabel
+               OpReturnValue %59
+               OpFunctionEnd
+          %f = OpFunction %void None %60
+         %63 = OpLabel
+         %64 = OpFunctionCall %int %i
+         %65 = OpFunctionCall %mat4v2float %load_m_inner
+         %67 = OpBitcast %uint %64
+         %66 = OpFunctionCall %v2float %load_m_inner_p0 %67
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl
new file mode 100644
index 0000000..bab27eb
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/dynamic_index_via_ptr.wgsl.expected.wgsl
@@ -0,0 +1,16 @@
+@group(0) @binding(0) var<uniform> m : mat4x2<f32>;
+
+var<private> counter = 0;
+
+fn i() -> i32 {
+  counter++;
+  return counter;
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m = &(m);
+  let p_m_i = &((*(p_m))[i()]);
+  let l_m : mat4x2<f32> = *(p_m);
+  let l_m_i : vec2<f32> = *(p_m_i);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl
new file mode 100644
index 0000000..24aa2ea
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl
@@ -0,0 +1,13 @@
+@group(0) @binding(0) var<uniform> m : mat4x2<f32>;
+
+var<private> counter = 0;
+fn i() -> i32 { counter++; return counter; }
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m   = &m;
+  let p_m_1 = &((*p_m)[1]);
+
+  let l_m   : mat4x2<f32> = *p_m;
+  let l_m_1 : vec2<f32>   = *p_m_1;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..db46be5
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.dxc.hlsl
@@ -0,0 +1,28 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[2];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float4x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float4x2 l_m = tint_symbol(m, 0u);
+  const float2 l_m_1 = asfloat(m[0].zw);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..db46be5
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.fxc.hlsl
@@ -0,0 +1,28 @@
+cbuffer cbuffer_m : register(b0, space0) {
+  uint4 m[2];
+};
+static int counter = 0;
+
+int i() {
+  counter = (counter + 1);
+  return counter;
+}
+
+float4x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float4x2 l_m = tint_symbol(m, 0u);
+  const float2 l_m_1 = asfloat(m[0].zw);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.glsl
new file mode 100644
index 0000000..4b55c69
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.glsl
@@ -0,0 +1,25 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform m_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+  vec2 inner_3;
+} m;
+
+mat4x2 load_m_inner() {
+  return mat4x2(m.inner_0, m.inner_1, m.inner_2, m.inner_3);
+}
+
+void f() {
+  mat4x2 p_m = load_m_inner();
+  vec2 p_m_1 = m.inner_1;
+  mat4x2 l_m = load_m_inner();
+  vec2 l_m_1 = m.inner_1;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.msl
new file mode 100644
index 0000000..7bc8919
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.msl
@@ -0,0 +1,15 @@
+#include <metal_stdlib>
+
+using namespace metal;
+int i() {
+  thread int tint_symbol = 0;
+  tint_symbol = as_type<int>((as_type<uint>(tint_symbol) + as_type<uint>(1)));
+  return tint_symbol;
+}
+
+kernel void f(const constant float4x2* tint_symbol_1 [[buffer(0)]]) {
+  float4x2 const l_m = *(tint_symbol_1);
+  float2 const l_m_1 = (*(tint_symbol_1))[1];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.spvasm
new file mode 100644
index 0000000..7b65bbb5
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %m_block_std140 "m_block_std140"
+               OpMemberName %m_block_std140 0 "inner_0"
+               OpMemberName %m_block_std140 1 "inner_1"
+               OpMemberName %m_block_std140 2 "inner_2"
+               OpMemberName %m_block_std140 3 "inner_3"
+               OpName %m "m"
+               OpName %counter "counter"
+               OpName %i "i"
+               OpName %load_m_inner "load_m_inner"
+               OpName %f "f"
+               OpDecorate %m_block_std140 Block
+               OpMemberDecorate %m_block_std140 0 Offset 0
+               OpMemberDecorate %m_block_std140 1 Offset 8
+               OpMemberDecorate %m_block_std140 2 Offset 16
+               OpMemberDecorate %m_block_std140 3 Offset 24
+               OpDecorate %m NonWritable
+               OpDecorate %m DescriptorSet 0
+               OpDecorate %m Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%m_block_std140 = OpTypeStruct %v2float %v2float %v2float %v2float
+%_ptr_Uniform_m_block_std140 = OpTypePointer Uniform %m_block_std140
+          %m = OpVariable %_ptr_Uniform_m_block_std140 Uniform
+        %int = OpTypeInt 32 1
+          %7 = OpConstantNull %int
+%_ptr_Private_int = OpTypePointer Private %int
+    %counter = OpVariable %_ptr_Private_int Private %7
+         %10 = OpTypeFunction %int
+      %int_1 = OpConstant %int 1
+%mat4v2float = OpTypeMatrix %v2float 4
+         %17 = OpTypeFunction %mat4v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+         %41 = OpTypeFunction %void
+          %i = OpFunction %int None %10
+         %12 = OpLabel
+         %13 = OpLoad %int %counter
+         %15 = OpIAdd %int %13 %int_1
+               OpStore %counter %15
+         %16 = OpLoad %int %counter
+               OpReturnValue %16
+               OpFunctionEnd
+%load_m_inner = OpFunction %mat4v2float None %17
+         %20 = OpLabel
+         %26 = OpAccessChain %_ptr_Uniform_v2float %m %uint_0
+         %27 = OpLoad %v2float %26
+         %30 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %31 = OpLoad %v2float %30
+         %34 = OpAccessChain %_ptr_Uniform_v2float %m %uint_2
+         %35 = OpLoad %v2float %34
+         %38 = OpAccessChain %_ptr_Uniform_v2float %m %uint_3
+         %39 = OpLoad %v2float %38
+         %40 = OpCompositeConstruct %mat4v2float %27 %31 %35 %39
+               OpReturnValue %40
+               OpFunctionEnd
+          %f = OpFunction %void None %41
+         %44 = OpLabel
+         %45 = OpFunctionCall %mat4v2float %load_m_inner
+         %46 = OpAccessChain %_ptr_Uniform_v2float %m %uint_1
+         %47 = OpLoad %v2float %46
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.wgsl
new file mode 100644
index 0000000..862956f
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/static_index_via_ptr.wgsl.expected.wgsl
@@ -0,0 +1,16 @@
+@group(0) @binding(0) var<uniform> m : mat4x2<f32>;
+
+var<private> counter = 0;
+
+fn i() -> i32 {
+  counter++;
+  return counter;
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  let p_m = &(m);
+  let p_m_1 = &((*(p_m))[1]);
+  let l_m : mat4x2<f32> = *(p_m);
+  let l_m_1 : vec2<f32> = *(p_m_1);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl
new file mode 100644
index 0000000..4f0d8fc
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl
@@ -0,0 +1,8 @@
+@group(0) @binding(0) var<uniform> u : mat4x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    let t = transpose(u);
+    let l = length(u[1]);
+    let a = abs(u[0].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..051e093
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.dxc.hlsl
@@ -0,0 +1,23 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+
+float4x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x4 t = transpose(tint_symbol(u, 0u));
+  const float l = length(asfloat(u[0].zw));
+  const float a = abs(asfloat(u[0].xy).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..051e093
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.fxc.hlsl
@@ -0,0 +1,23 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+
+float4x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  const float2x4 t = transpose(tint_symbol(u, 0u));
+  const float l = length(asfloat(u[0].zw));
+  const float a = abs(asfloat(u[0].xy).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.glsl
new file mode 100644
index 0000000..06e62f2
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.glsl
@@ -0,0 +1,24 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+  vec2 inner_3;
+} u;
+
+mat4x2 load_u_inner() {
+  return mat4x2(u.inner_0, u.inner_1, u.inner_2, u.inner_3);
+}
+
+void f() {
+  mat2x4 t = transpose(load_u_inner());
+  float l = length(u.inner_1);
+  float a = abs(u.inner_0.yx[0u]);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.msl
new file mode 100644
index 0000000..175bd3e
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.msl
@@ -0,0 +1,10 @@
+#include <metal_stdlib>
+
+using namespace metal;
+kernel void f(const constant float4x2* tint_symbol [[buffer(0)]]) {
+  float2x4 const t = transpose(*(tint_symbol));
+  float const l = length((*(tint_symbol))[1]);
+  float const a = fabs(float2((*(tint_symbol))[0]).yx[0]);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.spvasm
new file mode 100644
index 0000000..031760b
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+               OpCapability Shader
+         %39 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
+               OpMemberName %u_block_std140 3 "inner_3"
+               OpName %u "u"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
+               OpMemberDecorate %u_block_std140 3 Offset 24
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat4v2float = OpTypeMatrix %v2float 4
+          %6 = OpTypeFunction %mat4v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+         %30 = OpTypeFunction %void
+    %v4float = OpTypeVector %float 4
+%mat2v4float = OpTypeMatrix %v4float 2
+         %46 = OpConstantNull %uint
+%load_u_inner = OpFunction %mat4v2float None %6
+          %9 = OpLabel
+         %15 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %16 = OpLoad %v2float %15
+         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %20 = OpLoad %v2float %19
+         %23 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %24 = OpLoad %v2float %23
+         %27 = OpAccessChain %_ptr_Uniform_v2float %u %uint_3
+         %28 = OpLoad %v2float %27
+         %29 = OpCompositeConstruct %mat4v2float %16 %20 %24 %28
+               OpReturnValue %29
+               OpFunctionEnd
+          %f = OpFunction %void None %30
+         %33 = OpLabel
+         %37 = OpFunctionCall %mat4v2float %load_u_inner
+         %34 = OpTranspose %mat2v4float %37
+         %40 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %41 = OpLoad %v2float %40
+         %38 = OpExtInst %float %39 Length %41
+         %43 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %44 = OpLoad %v2float %43
+         %45 = OpVectorShuffle %v2float %44 %44 1 0
+         %47 = OpCompositeExtract %float %45 0
+         %42 = OpExtInst %float %39 FAbs %47
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.wgsl
new file mode 100644
index 0000000..ac19e9c
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_builtin.wgsl.expected.wgsl
@@ -0,0 +1,8 @@
+@group(0) @binding(0) var<uniform> u : mat4x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  let t = transpose(u);
+  let l = length(u[1]);
+  let a = abs(u[0].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl
new file mode 100644
index 0000000..0e099a9
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl
@@ -0,0 +1,14 @@
+@group(0) @binding(0) var<uniform> u : mat4x2<f32>;
+
+fn a(m : mat4x2<f32>) {}
+fn b(v : vec2<f32>) {}
+fn c(f : f32) {}
+
+@compute @workgroup_size(1)
+fn f() {
+    a(u);
+    b(u[1]);
+    b(u[1].yx);
+    c(u[1].x);
+    c(u[1].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..9629f1d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.dxc.hlsl
@@ -0,0 +1,34 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+
+void a(float4x2 m) {
+}
+
+void b(float2 v) {
+}
+
+void c(float f_1) {
+}
+
+float4x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  a(tint_symbol(u, 0u));
+  b(asfloat(u[0].zw));
+  b(asfloat(u[0].zw).yx);
+  c(asfloat(u[0].z));
+  c(asfloat(u[0].zw).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..9629f1d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.fxc.hlsl
@@ -0,0 +1,34 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+
+void a(float4x2 m) {
+}
+
+void b(float2 v) {
+}
+
+void c(float f_1) {
+}
+
+float4x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  a(tint_symbol(u, 0u));
+  b(asfloat(u[0].zw));
+  b(asfloat(u[0].zw).yx);
+  c(asfloat(u[0].z));
+  c(asfloat(u[0].zw).yx.x);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.glsl
new file mode 100644
index 0000000..7443601
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.glsl
@@ -0,0 +1,35 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+  vec2 inner_3;
+} u;
+
+void a(mat4x2 m) {
+}
+
+void b(vec2 v) {
+}
+
+void c(float f_1) {
+}
+
+mat4x2 load_u_inner() {
+  return mat4x2(u.inner_0, u.inner_1, u.inner_2, u.inner_3);
+}
+
+void f() {
+  a(load_u_inner());
+  b(u.inner_1);
+  b(u.inner_1.yx);
+  c(u.inner_1[0u]);
+  c(u.inner_1.yx[0u]);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.msl
new file mode 100644
index 0000000..4cec493
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.msl
@@ -0,0 +1,21 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void a(float4x2 m) {
+}
+
+void b(float2 v) {
+}
+
+void c(float f_1) {
+}
+
+kernel void f(const constant float4x2* tint_symbol [[buffer(0)]]) {
+  a(*(tint_symbol));
+  b((*(tint_symbol))[1]);
+  b(float2((*(tint_symbol))[1]).yx);
+  c((*(tint_symbol))[1][0]);
+  c(float2((*(tint_symbol))[1]).yx[0]);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.spvasm
new file mode 100644
index 0000000..921369d
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.spvasm
@@ -0,0 +1,100 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 65
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
+               OpMemberName %u_block_std140 3 "inner_3"
+               OpName %u "u"
+               OpName %a "a"
+               OpName %m "m"
+               OpName %b "b"
+               OpName %v "v"
+               OpName %c "c"
+               OpName %f_1 "f_1"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
+               OpMemberDecorate %u_block_std140 3 Offset 24
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+       %void = OpTypeVoid
+%mat4v2float = OpTypeMatrix %v2float 4
+          %6 = OpTypeFunction %void %mat4v2float
+         %12 = OpTypeFunction %void %v2float
+         %16 = OpTypeFunction %void %float
+         %20 = OpTypeFunction %mat4v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+         %43 = OpTypeFunction %void
+         %56 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+          %a = OpFunction %void None %6
+          %m = OpFunctionParameter %mat4v2float
+         %11 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %b = OpFunction %void None %12
+          %v = OpFunctionParameter %v2float
+         %15 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %c = OpFunction %void None %16
+        %f_1 = OpFunctionParameter %float
+         %19 = OpLabel
+               OpReturn
+               OpFunctionEnd
+%load_u_inner = OpFunction %mat4v2float None %20
+         %22 = OpLabel
+         %28 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %29 = OpLoad %v2float %28
+         %32 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %33 = OpLoad %v2float %32
+         %36 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %37 = OpLoad %v2float %36
+         %40 = OpAccessChain %_ptr_Uniform_v2float %u %uint_3
+         %41 = OpLoad %v2float %40
+         %42 = OpCompositeConstruct %mat4v2float %29 %33 %37 %41
+               OpReturnValue %42
+               OpFunctionEnd
+          %f = OpFunction %void None %43
+         %45 = OpLabel
+         %47 = OpFunctionCall %mat4v2float %load_u_inner
+         %46 = OpFunctionCall %void %a %47
+         %49 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %50 = OpLoad %v2float %49
+         %48 = OpFunctionCall %void %b %50
+         %52 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %53 = OpLoad %v2float %52
+         %54 = OpVectorShuffle %v2float %53 %53 1 0
+         %51 = OpFunctionCall %void %b %54
+         %58 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %56
+         %59 = OpLoad %float %58
+         %55 = OpFunctionCall %void %c %59
+         %61 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %62 = OpLoad %v2float %61
+         %63 = OpVectorShuffle %v2float %62 %62 1 0
+         %64 = OpCompositeExtract %float %63 0
+         %60 = OpFunctionCall %void %c %64
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.wgsl
new file mode 100644
index 0000000..2bbc927
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_fn.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+@group(0) @binding(0) var<uniform> u : mat4x2<f32>;
+
+fn a(m : mat4x2<f32>) {
+}
+
+fn b(v : vec2<f32>) {
+}
+
+fn c(f : f32) {
+}
+
+@compute @workgroup_size(1)
+fn f() {
+  a(u);
+  b(u[1]);
+  b(u[1].yx);
+  c(u[1].x);
+  c(u[1].yx.x);
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl
new file mode 100644
index 0000000..49dd616
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl
@@ -0,0 +1,10 @@
+@group(0) @binding(0) var<uniform> u : mat4x2<f32>;
+var<private> p : mat4x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    p = u;
+    p[1] = u[0];
+    p[1] = u[0].yx;
+    p[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..15f91ac
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.dxc.hlsl
@@ -0,0 +1,25 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+static float4x2 p = float4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+
+float4x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  p = tint_symbol(u, 0u);
+  p[1] = asfloat(u[0].xy);
+  p[1] = asfloat(u[0].xy).yx;
+  p[0][1] = asfloat(u[0].z);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..15f91ac
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.fxc.hlsl
@@ -0,0 +1,25 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+static float4x2 p = float4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+
+float4x2 tint_symbol(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  p = tint_symbol(u, 0u);
+  p[1] = asfloat(u[0].xy);
+  p[1] = asfloat(u[0].xy).yx;
+  p[0][1] = asfloat(u[0].z);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.glsl
new file mode 100644
index 0000000..434a6b7
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.glsl
@@ -0,0 +1,26 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+  vec2 inner_3;
+} u;
+
+mat4x2 p = mat4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+mat4x2 load_u_inner() {
+  return mat4x2(u.inner_0, u.inner_1, u.inner_2, u.inner_3);
+}
+
+void f() {
+  p = load_u_inner();
+  p[1] = u.inner_0;
+  p[1] = u.inner_0.yx;
+  p[0][1] = u.inner_1[0u];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.msl
new file mode 100644
index 0000000..b2d3c55
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.msl
@@ -0,0 +1,12 @@
+#include <metal_stdlib>
+
+using namespace metal;
+kernel void f(const constant float4x2* tint_symbol_1 [[buffer(0)]]) {
+  thread float4x2 tint_symbol = float4x2(0.0f);
+  tint_symbol = *(tint_symbol_1);
+  tint_symbol[1] = (*(tint_symbol_1))[0];
+  tint_symbol[1] = float2((*(tint_symbol_1))[0]).yx;
+  tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.spvasm
new file mode 100644
index 0000000..075f83f
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.spvasm
@@ -0,0 +1,83 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 55
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
+               OpMemberName %u_block_std140 3 "inner_3"
+               OpName %u "u"
+               OpName %p "p"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
+               OpMemberDecorate %u_block_std140 3 Offset 24
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat4v2float = OpTypeMatrix %v2float 4
+%_ptr_Private_mat4v2float = OpTypePointer Private %mat4v2float
+          %9 = OpConstantNull %mat4v2float
+          %p = OpVariable %_ptr_Private_mat4v2float Private %9
+         %10 = OpTypeFunction %mat4v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+         %33 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_Private_v2float = OpTypePointer Private %v2float
+         %48 = OpConstantNull %int
+%_ptr_Private_float = OpTypePointer Private %float
+         %51 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+%load_u_inner = OpFunction %mat4v2float None %10
+         %12 = OpLabel
+         %18 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %19 = OpLoad %v2float %18
+         %22 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %23 = OpLoad %v2float %22
+         %26 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %27 = OpLoad %v2float %26
+         %30 = OpAccessChain %_ptr_Uniform_v2float %u %uint_3
+         %31 = OpLoad %v2float %30
+         %32 = OpCompositeConstruct %mat4v2float %19 %23 %27 %31
+               OpReturnValue %32
+               OpFunctionEnd
+          %f = OpFunction %void None %33
+         %36 = OpLabel
+         %37 = OpFunctionCall %mat4v2float %load_u_inner
+               OpStore %p %37
+         %41 = OpAccessChain %_ptr_Private_v2float %p %int_1
+         %42 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %43 = OpLoad %v2float %42
+               OpStore %41 %43
+         %44 = OpAccessChain %_ptr_Private_v2float %p %int_1
+         %45 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %46 = OpLoad %v2float %45
+         %47 = OpVectorShuffle %v2float %46 %46 1 0
+               OpStore %44 %47
+         %50 = OpAccessChain %_ptr_Private_float %p %48 %int_1
+         %53 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %51
+         %54 = OpLoad %float %53
+               OpStore %50 %54
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.wgsl
new file mode 100644
index 0000000..d0a63c8
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_private.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> u : mat4x2<f32>;
+
+var<private> p : mat4x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  p = u;
+  p[1] = u[0];
+  p[1] = u[0].yx;
+  p[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl
new file mode 100644
index 0000000..333e3dc
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl
@@ -0,0 +1,10 @@
+@group(0) @binding(0) var<uniform> u : mat4x2<f32>;
+@group(0) @binding(1) var<storage, read_write> s : mat4x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    s = u;
+    s[1] = u[0];
+    s[1] = u[0].yx;
+    s[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..466fdc4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.dxc.hlsl
@@ -0,0 +1,32 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+RWByteAddressBuffer s : register(u1, space0);
+
+void tint_symbol(RWByteAddressBuffer buffer, uint offset, float4x2 value) {
+  buffer.Store2((offset + 0u), asuint(value[0u]));
+  buffer.Store2((offset + 8u), asuint(value[1u]));
+  buffer.Store2((offset + 16u), asuint(value[2u]));
+  buffer.Store2((offset + 24u), asuint(value[3u]));
+}
+
+float4x2 tint_symbol_2(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  tint_symbol(s, 0u, tint_symbol_2(u, 0u));
+  s.Store2(8u, asuint(asfloat(u[0].xy)));
+  s.Store2(8u, asuint(asfloat(u[0].xy).yx));
+  s.Store(4u, asuint(asfloat(u[0].z)));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..466fdc4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.fxc.hlsl
@@ -0,0 +1,32 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+RWByteAddressBuffer s : register(u1, space0);
+
+void tint_symbol(RWByteAddressBuffer buffer, uint offset, float4x2 value) {
+  buffer.Store2((offset + 0u), asuint(value[0u]));
+  buffer.Store2((offset + 8u), asuint(value[1u]));
+  buffer.Store2((offset + 16u), asuint(value[2u]));
+  buffer.Store2((offset + 24u), asuint(value[3u]));
+}
+
+float4x2 tint_symbol_2(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+[numthreads(1, 1, 1)]
+void f() {
+  tint_symbol(s, 0u, tint_symbol_2(u, 0u));
+  s.Store2(8u, asuint(asfloat(u[0].xy)));
+  s.Store2(8u, asuint(asfloat(u[0].xy).yx));
+  s.Store(4u, asuint(asfloat(u[0].z)));
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.glsl
new file mode 100644
index 0000000..6370442
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.glsl
@@ -0,0 +1,29 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+  vec2 inner_3;
+} u;
+
+layout(binding = 1, std430) buffer u_block_ssbo {
+  mat4x2 inner;
+} s;
+
+mat4x2 load_u_inner() {
+  return mat4x2(u.inner_0, u.inner_1, u.inner_2, u.inner_3);
+}
+
+void f() {
+  s.inner = load_u_inner();
+  s.inner[1] = u.inner_0;
+  s.inner[1] = u.inner_0.yx;
+  s.inner[0][1] = u.inner_1[0u];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f();
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.msl
new file mode 100644
index 0000000..fab0f86
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.msl
@@ -0,0 +1,11 @@
+#include <metal_stdlib>
+
+using namespace metal;
+kernel void f(device float4x2* tint_symbol [[buffer(1)]], const constant float4x2* tint_symbol_1 [[buffer(0)]]) {
+  *(tint_symbol) = *(tint_symbol_1);
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
+  (*(tint_symbol))[1] = float2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.spvasm
new file mode 100644
index 0000000..bea1c14
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.spvasm
@@ -0,0 +1,93 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 57
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f"
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
+               OpMemberName %u_block_std140 3 "inner_3"
+               OpName %u "u"
+               OpName %u_block "u_block"
+               OpMemberName %u_block 0 "inner"
+               OpName %s "s"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f "f"
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
+               OpMemberDecorate %u_block_std140 3 Offset 24
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+               OpDecorate %u_block Block
+               OpMemberDecorate %u_block 0 Offset 0
+               OpMemberDecorate %u_block 0 ColMajor
+               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %s DescriptorSet 0
+               OpDecorate %s Binding 1
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat4v2float = OpTypeMatrix %v2float 4
+    %u_block = OpTypeStruct %mat4v2float
+%_ptr_StorageBuffer_u_block = OpTypePointer StorageBuffer %u_block
+          %s = OpVariable %_ptr_StorageBuffer_u_block StorageBuffer
+         %10 = OpTypeFunction %mat4v2float
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+         %33 = OpTypeFunction %void
+%_ptr_StorageBuffer_mat4v2float = OpTypePointer StorageBuffer %mat4v2float
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
+         %50 = OpConstantNull %int
+%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float
+         %53 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+%load_u_inner = OpFunction %mat4v2float None %10
+         %12 = OpLabel
+         %18 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %19 = OpLoad %v2float %18
+         %22 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %23 = OpLoad %v2float %22
+         %26 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %27 = OpLoad %v2float %26
+         %30 = OpAccessChain %_ptr_Uniform_v2float %u %uint_3
+         %31 = OpLoad %v2float %30
+         %32 = OpCompositeConstruct %mat4v2float %19 %23 %27 %31
+               OpReturnValue %32
+               OpFunctionEnd
+          %f = OpFunction %void None %33
+         %36 = OpLabel
+         %38 = OpAccessChain %_ptr_StorageBuffer_mat4v2float %s %uint_0
+         %39 = OpFunctionCall %mat4v2float %load_u_inner
+               OpStore %38 %39
+         %43 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1
+         %44 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %45 = OpLoad %v2float %44
+               OpStore %43 %45
+         %46 = OpAccessChain %_ptr_StorageBuffer_v2float %s %uint_0 %int_1
+         %47 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %48 = OpLoad %v2float %47
+         %49 = OpVectorShuffle %v2float %48 %48 1 0
+               OpStore %46 %49
+         %52 = OpAccessChain %_ptr_StorageBuffer_float %s %uint_0 %50 %int_1
+         %55 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %53
+         %56 = OpLoad %float %55
+               OpStore %52 %56
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.wgsl
new file mode 100644
index 0000000..e248951
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_storage.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> u : mat4x2<f32>;
+
+@group(0) @binding(1) var<storage, read_write> s : mat4x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  s = u;
+  s[1] = u[0];
+  s[1] = u[0].yx;
+  s[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl
new file mode 100644
index 0000000..2055f76
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl
@@ -0,0 +1,10 @@
+@group(0) @binding(0) var<uniform> u : mat4x2<f32>;
+var<workgroup> w : mat4x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+    w = u;
+    w[1] = u[0];
+    w[1] = u[0].yx;
+    w[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.dxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..f665fb4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.dxc.hlsl
@@ -0,0 +1,37 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+groupshared float4x2 w;
+
+struct tint_symbol_1 {
+  uint local_invocation_index : SV_GroupIndex;
+};
+
+float4x2 tint_symbol_2(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+void f_inner(uint local_invocation_index) {
+  {
+    w = float4x2((0.0f).xx, (0.0f).xx, (0.0f).xx, (0.0f).xx);
+  }
+  GroupMemoryBarrierWithGroupSync();
+  w = tint_symbol_2(u, 0u);
+  w[1] = asfloat(u[0].xy);
+  w[1] = asfloat(u[0].xy).yx;
+  w[0][1] = asfloat(u[0].z);
+}
+
+[numthreads(1, 1, 1)]
+void f(tint_symbol_1 tint_symbol) {
+  f_inner(tint_symbol.local_invocation_index);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.fxc.hlsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..f665fb4
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.fxc.hlsl
@@ -0,0 +1,37 @@
+cbuffer cbuffer_u : register(b0, space0) {
+  uint4 u[2];
+};
+groupshared float4x2 w;
+
+struct tint_symbol_1 {
+  uint local_invocation_index : SV_GroupIndex;
+};
+
+float4x2 tint_symbol_2(uint4 buffer[2], uint offset) {
+  const uint scalar_offset = ((offset + 0u)) / 4;
+  uint4 ubo_load = buffer[scalar_offset / 4];
+  const uint scalar_offset_1 = ((offset + 8u)) / 4;
+  uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+  const uint scalar_offset_2 = ((offset + 16u)) / 4;
+  uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+  const uint scalar_offset_3 = ((offset + 24u)) / 4;
+  uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+  return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+}
+
+void f_inner(uint local_invocation_index) {
+  {
+    w = float4x2((0.0f).xx, (0.0f).xx, (0.0f).xx, (0.0f).xx);
+  }
+  GroupMemoryBarrierWithGroupSync();
+  w = tint_symbol_2(u, 0u);
+  w[1] = asfloat(u[0].xy);
+  w[1] = asfloat(u[0].xy).yx;
+  w[0][1] = asfloat(u[0].z);
+}
+
+[numthreads(1, 1, 1)]
+void f(tint_symbol_1 tint_symbol) {
+  f_inner(tint_symbol.local_invocation_index);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.glsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.glsl
new file mode 100644
index 0000000..46f60b3
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.glsl
@@ -0,0 +1,30 @@
+#version 310 es
+
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
+  vec2 inner_3;
+} u;
+
+shared mat4x2 w;
+mat4x2 load_u_inner() {
+  return mat4x2(u.inner_0, u.inner_1, u.inner_2, u.inner_3);
+}
+
+void f(uint local_invocation_index) {
+  {
+    w = mat4x2(vec2(0.0f), vec2(0.0f), vec2(0.0f), vec2(0.0f));
+  }
+  barrier();
+  w = load_u_inner();
+  w[1] = u.inner_0;
+  w[1] = u.inner_0.yx;
+  w[0][1] = u.inner_1[0u];
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f(gl_LocalInvocationIndex);
+  return;
+}
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.msl
new file mode 100644
index 0000000..6db4db2
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.msl
@@ -0,0 +1,24 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_symbol_5 {
+  float4x2 w;
+};
+
+void f_inner(uint local_invocation_index, threadgroup float4x2* const tint_symbol, const constant float4x2* const tint_symbol_1) {
+  {
+    *(tint_symbol) = float4x2(float2(0.0f), float2(0.0f), float2(0.0f), float2(0.0f));
+  }
+  threadgroup_barrier(mem_flags::mem_threadgroup);
+  *(tint_symbol) = *(tint_symbol_1);
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
+  (*(tint_symbol))[1] = float2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+}
+
+kernel void f(const constant float4x2* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+  threadgroup float4x2* const tint_symbol_2 = &((*(tint_symbol_3)).w);
+  f_inner(local_invocation_index, tint_symbol_2, tint_symbol_4);
+  return;
+}
+
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.spvasm b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.spvasm
new file mode 100644
index 0000000..996a343
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.spvasm
@@ -0,0 +1,100 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 65
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %f "f" %local_invocation_index_1
+               OpExecutionMode %f LocalSize 1 1 1
+               OpName %local_invocation_index_1 "local_invocation_index_1"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
+               OpMemberName %u_block_std140 3 "inner_3"
+               OpName %u "u"
+               OpName %w "w"
+               OpName %load_u_inner "load_u_inner"
+               OpName %f_inner "f_inner"
+               OpName %local_invocation_index "local_invocation_index"
+               OpName %f "f"
+               OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
+               OpMemberDecorate %u_block_std140 3 Offset 24
+               OpDecorate %u NonWritable
+               OpDecorate %u DescriptorSet 0
+               OpDecorate %u Binding 0
+       %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
+%mat4v2float = OpTypeMatrix %v2float 4
+%_ptr_Workgroup_mat4v2float = OpTypePointer Workgroup %mat4v2float
+          %w = OpVariable %_ptr_Workgroup_mat4v2float Workgroup
+         %12 = OpTypeFunction %mat4v2float
+     %uint_0 = OpConstant %uint 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+       %void = OpTypeVoid
+         %34 = OpTypeFunction %void %uint
+         %39 = OpConstantNull %mat4v2float
+   %uint_264 = OpConstant %uint 264
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+%_ptr_Workgroup_v2float = OpTypePointer Workgroup %v2float
+         %53 = OpConstantNull %int
+%_ptr_Workgroup_float = OpTypePointer Workgroup %float
+         %56 = OpConstantNull %uint
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+         %60 = OpTypeFunction %void
+%load_u_inner = OpFunction %mat4v2float None %12
+         %14 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %20 = OpLoad %v2float %19
+         %23 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %24 = OpLoad %v2float %23
+         %27 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %28 = OpLoad %v2float %27
+         %31 = OpAccessChain %_ptr_Uniform_v2float %u %uint_3
+         %32 = OpLoad %v2float %31
+         %33 = OpCompositeConstruct %mat4v2float %20 %24 %28 %32
+               OpReturnValue %33
+               OpFunctionEnd
+    %f_inner = OpFunction %void None %34
+%local_invocation_index = OpFunctionParameter %uint
+         %38 = OpLabel
+               OpStore %w %39
+               OpControlBarrier %uint_2 %uint_2 %uint_264
+         %42 = OpFunctionCall %mat4v2float %load_u_inner
+               OpStore %w %42
+         %46 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1
+         %47 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %48 = OpLoad %v2float %47
+               OpStore %46 %48
+         %49 = OpAccessChain %_ptr_Workgroup_v2float %w %int_1
+         %50 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %51 = OpLoad %v2float %50
+         %52 = OpVectorShuffle %v2float %51 %51 1 0
+               OpStore %49 %52
+         %55 = OpAccessChain %_ptr_Workgroup_float %w %53 %int_1
+         %58 = OpAccessChain %_ptr_Uniform_float %u %uint_1 %56
+         %59 = OpLoad %float %58
+               OpStore %55 %59
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %60
+         %62 = OpLabel
+         %64 = OpLoad %uint %local_invocation_index_1
+         %63 = OpFunctionCall %void %f_inner %64
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.wgsl b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.wgsl
new file mode 100644
index 0000000..1579614
--- /dev/null
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2/to_workgroup.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+@group(0) @binding(0) var<uniform> u : mat4x2<f32>;
+
+var<workgroup> w : mat4x2<f32>;
+
+@compute @workgroup_size(1)
+fn f() {
+  w = u;
+  w[1] = u[0];
+  w[1] = u[0].yx;
+  w[0][1] = u[1][0];
+}
diff --git a/test/tint/buffer/uniform/types/mat2x2.wgsl.expected.glsl b/test/tint/buffer/uniform/types/mat2x2.wgsl.expected.glsl
index ae3c014..4263f9a 100644
--- a/test/tint/buffer/uniform/types/mat2x2.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/types/mat2x2.wgsl.expected.glsl
@@ -1,11 +1,16 @@
 #version 310 es
 
-layout(binding = 0, std140) uniform u_block_ubo {
-  mat2 inner;
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
 } u;
 
+mat2 load_u_inner() {
+  return mat2(u.inner_0, u.inner_1);
+}
+
 void tint_symbol() {
-  mat2 x = u.inner;
+  mat2 x = load_u_inner();
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/buffer/uniform/types/mat2x2.wgsl.expected.spvasm b/test/tint/buffer/uniform/types/mat2x2.wgsl.expected.spvasm
index dd16f09..8194735 100644
--- a/test/tint/buffer/uniform/types/mat2x2.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/types/mat2x2.wgsl.expected.spvasm
@@ -1,42 +1,48 @@
-SKIP: FAILED
-
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 16
+; Bound: 27
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %main "main"
                OpExecutionMode %main LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
                OpName %u "u"
+               OpName %load_u_inner "load_u_inner"
                OpName %main "main"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
-               OpMemberDecorate %u_block 0 ColMajor
-               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
                OpDecorate %u NonWritable
                OpDecorate %u DescriptorSet 0
                OpDecorate %u Binding 0
       %float = OpTypeFloat 32
     %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat2v2float = OpTypeMatrix %v2float 2
-    %u_block = OpTypeStruct %mat2v2float
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
-       %void = OpTypeVoid
-          %7 = OpTypeFunction %void
+          %6 = OpTypeFunction %mat2v2float
        %uint = OpTypeInt 32 0
      %uint_0 = OpConstant %uint 0
-%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
-       %main = OpFunction %void None %7
-         %10 = OpLabel
-         %14 = OpAccessChain %_ptr_Uniform_mat2v2float %u %uint_0
-         %15 = OpLoad %mat2v2float %14
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+       %void = OpTypeVoid
+         %22 = OpTypeFunction %void
+%load_u_inner = OpFunction %mat2v2float None %6
+          %9 = OpLabel
+         %15 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %16 = OpLoad %v2float %15
+         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %20 = OpLoad %v2float %19
+         %21 = OpCompositeConstruct %mat2v2float %16 %20
+               OpReturnValue %21
+               OpFunctionEnd
+       %main = OpFunction %void None %22
+         %25 = OpLabel
+         %26 = OpFunctionCall %mat2v2float %load_u_inner
                OpReturn
                OpFunctionEnd
-1:1: Structure id 3 decorated as Block for variable in Uniform storage class must follow relaxed uniform buffer layout rules: member 0 is a matrix with stride 8 not satisfying alignment to 16
-  %u_block = OpTypeStruct %mat2v2float
-
diff --git a/test/tint/buffer/uniform/types/mat3x2.wgsl.expected.glsl b/test/tint/buffer/uniform/types/mat3x2.wgsl.expected.glsl
index 06a0a60..85312c9c 100644
--- a/test/tint/buffer/uniform/types/mat3x2.wgsl.expected.glsl
+++ b/test/tint/buffer/uniform/types/mat3x2.wgsl.expected.glsl
@@ -1,11 +1,17 @@
 #version 310 es
 
-layout(binding = 0, std140) uniform u_block_ubo {
-  mat3x2 inner;
+layout(binding = 0, std140) uniform u_block_std140_ubo {
+  vec2 inner_0;
+  vec2 inner_1;
+  vec2 inner_2;
 } u;
 
+mat3x2 load_u_inner() {
+  return mat3x2(u.inner_0, u.inner_1, u.inner_2);
+}
+
 void tint_symbol() {
-  mat3x2 x = u.inner;
+  mat3x2 x = load_u_inner();
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/buffer/uniform/types/mat3x2.wgsl.expected.spvasm b/test/tint/buffer/uniform/types/mat3x2.wgsl.expected.spvasm
index efa01c7..98050d5 100644
--- a/test/tint/buffer/uniform/types/mat3x2.wgsl.expected.spvasm
+++ b/test/tint/buffer/uniform/types/mat3x2.wgsl.expected.spvasm
@@ -1,42 +1,53 @@
-SKIP: FAILED
-
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 16
+; Bound: 31
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint GLCompute %main "main"
                OpExecutionMode %main LocalSize 1 1 1
-               OpName %u_block "u_block"
-               OpMemberName %u_block 0 "inner"
+               OpName %u_block_std140 "u_block_std140"
+               OpMemberName %u_block_std140 0 "inner_0"
+               OpMemberName %u_block_std140 1 "inner_1"
+               OpMemberName %u_block_std140 2 "inner_2"
                OpName %u "u"
+               OpName %load_u_inner "load_u_inner"
                OpName %main "main"
-               OpDecorate %u_block Block
-               OpMemberDecorate %u_block 0 Offset 0
-               OpMemberDecorate %u_block 0 ColMajor
-               OpMemberDecorate %u_block 0 MatrixStride 8
+               OpDecorate %u_block_std140 Block
+               OpMemberDecorate %u_block_std140 0 Offset 0
+               OpMemberDecorate %u_block_std140 1 Offset 8
+               OpMemberDecorate %u_block_std140 2 Offset 16
                OpDecorate %u NonWritable
                OpDecorate %u DescriptorSet 0
                OpDecorate %u Binding 0
       %float = OpTypeFloat 32
     %v2float = OpTypeVector %float 2
+%u_block_std140 = OpTypeStruct %v2float %v2float %v2float
+%_ptr_Uniform_u_block_std140 = OpTypePointer Uniform %u_block_std140
+          %u = OpVariable %_ptr_Uniform_u_block_std140 Uniform
 %mat3v2float = OpTypeMatrix %v2float 3
-    %u_block = OpTypeStruct %mat3v2float
-%_ptr_Uniform_u_block = OpTypePointer Uniform %u_block
-          %u = OpVariable %_ptr_Uniform_u_block Uniform
-       %void = OpTypeVoid
-          %7 = OpTypeFunction %void
+          %6 = OpTypeFunction %mat3v2float
        %uint = OpTypeInt 32 0
      %uint_0 = OpConstant %uint 0
-%_ptr_Uniform_mat3v2float = OpTypePointer Uniform %mat3v2float
-       %main = OpFunction %void None %7
-         %10 = OpLabel
-         %14 = OpAccessChain %_ptr_Uniform_mat3v2float %u %uint_0
-         %15 = OpLoad %mat3v2float %14
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+       %void = OpTypeVoid
+         %26 = OpTypeFunction %void
+%load_u_inner = OpFunction %mat3v2float None %6
+          %9 = OpLabel
+         %15 = OpAccessChain %_ptr_Uniform_v2float %u %uint_0
+         %16 = OpLoad %v2float %15
+         %19 = OpAccessChain %_ptr_Uniform_v2float %u %uint_1
+         %20 = OpLoad %v2float %19
+         %23 = OpAccessChain %_ptr_Uniform_v2float %u %uint_2
+         %24 = OpLoad %v2float %23
+         %25 = OpCompositeConstruct %mat3v2float %16 %20 %24
+               OpReturnValue %25
+               OpFunctionEnd
+       %main = OpFunction %void None %26
+         %29 = OpLabel
+         %30 = OpFunctionCall %mat3v2float %load_u_inner
                OpReturn
                OpFunctionEnd
-1:1: Structure id 3 decorated as Block for variable in Uniform storage class must follow relaxed uniform buffer layout rules: member 0 is a matrix with stride 8 not satisfying alignment to 16
-  %u_block = OpTypeStruct %mat3v2float
-
diff --git a/test/tint/bug/tint/403.wgsl.expected.glsl b/test/tint/bug/tint/403.wgsl.expected.glsl
index 38d12ca..76fc2c6 100644
--- a/test/tint/bug/tint/403.wgsl.expected.glsl
+++ b/test/tint/bug/tint/403.wgsl.expected.glsl
@@ -1,13 +1,5 @@
 #version 310 es
 
-struct vertexUniformBuffer1 {
-  mat2 transform1;
-};
-
-struct vertexUniformBuffer2 {
-  mat2 transform2;
-};
-
 layout(binding = 0, std140) uniform vertexUniformBuffer1_std140_ubo {
   vec2 transform1_0;
   vec2 transform1_1;
diff --git a/test/tint/bug/tint/403.wgsl.expected.spvasm b/test/tint/bug/tint/403.wgsl.expected.spvasm
index 5e79202..623c850 100644
--- a/test/tint/bug/tint/403.wgsl.expected.spvasm
+++ b/test/tint/bug/tint/403.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 76
+; Bound: 82
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
@@ -62,66 +62,66 @@
      %uint_0 = OpConstant %uint 0
 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
      %uint_1 = OpConstant %uint 1
-         %38 = OpTypeFunction %v4float %uint
+         %44 = OpTypeFunction %v4float %uint
      %uint_3 = OpConstant %uint 3
 %_arr_v2float_uint_3 = OpTypeArray %v2float %uint_3
 %_ptr_Function__arr_v2float_uint_3 = OpTypePointer Function %_arr_v2float_uint_3
-         %46 = OpConstantNull %_arr_v2float_uint_3
+         %52 = OpConstantNull %_arr_v2float_uint_3
    %float_n1 = OpConstant %float -1
     %float_1 = OpConstant %float 1
-         %51 = OpConstantComposite %v2float %float_n1 %float_1
-         %52 = OpConstantComposite %v2float %float_1 %float_1
-         %53 = OpConstantComposite %v2float %float_n1 %float_n1
-         %54 = OpConstantComposite %_arr_v2float_uint_3 %51 %52 %53
+         %57 = OpConstantComposite %v2float %float_n1 %float_1
+         %58 = OpConstantComposite %v2float %float_1 %float_1
+         %59 = OpConstantComposite %v2float %float_n1 %float_n1
+         %60 = OpConstantComposite %_arr_v2float_uint_3 %57 %58 %59
 %_ptr_Function_v2float = OpTypePointer Function %v2float
-         %58 = OpConstantNull %uint
+         %64 = OpConstantNull %uint
        %void = OpTypeVoid
-         %70 = OpTypeFunction %void
+         %76 = OpTypeFunction %void
 %load_x_20_transform1 = OpFunction %mat2v2float None %19
          %22 = OpLabel
-         %25 = OpAccessChain %_ptr_Uniform_v2float %x_20 %uint_0
-         %26 = OpLoad %v2float %25
-         %28 = OpAccessChain %_ptr_Uniform_v2float %x_20 %uint_1
-         %29 = OpLoad %v2float %28
-         %30 = OpCompositeConstruct %mat2v2float %26 %29
-               OpReturnValue %30
+         %27 = OpAccessChain %_ptr_Uniform_v2float %x_20 %uint_0
+         %28 = OpLoad %v2float %27
+         %31 = OpAccessChain %_ptr_Uniform_v2float %x_20 %uint_1
+         %32 = OpLoad %v2float %31
+         %33 = OpCompositeConstruct %mat2v2float %28 %32
+               OpReturnValue %33
                OpFunctionEnd
 %load_x_26_transform2 = OpFunction %mat2v2float None %19
-         %32 = OpLabel
-         %33 = OpAccessChain %_ptr_Uniform_v2float %x_26 %uint_0
-         %34 = OpLoad %v2float %33
-         %35 = OpAccessChain %_ptr_Uniform_v2float %x_26 %uint_1
-         %36 = OpLoad %v2float %35
-         %37 = OpCompositeConstruct %mat2v2float %34 %36
-               OpReturnValue %37
+         %35 = OpLabel
+         %38 = OpAccessChain %_ptr_Uniform_v2float %x_26 %uint_0
+         %39 = OpLoad %v2float %38
+         %41 = OpAccessChain %_ptr_Uniform_v2float %x_26 %uint_1
+         %42 = OpLoad %v2float %41
+         %43 = OpCompositeConstruct %mat2v2float %39 %42
+               OpReturnValue %43
                OpFunctionEnd
- %main_inner = OpFunction %v4float None %38
+ %main_inner = OpFunction %v4float None %44
 %gl_VertexIndex = OpFunctionParameter %uint
-         %41 = OpLabel
-  %indexable = OpVariable %_ptr_Function__arr_v2float_uint_3 Function %46
-         %47 = OpFunctionCall %mat2v2float %load_x_20_transform1
-         %48 = OpFunctionCall %mat2v2float %load_x_26_transform2
-               OpStore %indexable %54
-         %56 = OpAccessChain %_ptr_Function_v2float %indexable %gl_VertexIndex
-         %57 = OpLoad %v2float %56
-         %59 = OpCompositeExtract %v2float %47 0
-         %60 = OpCompositeExtract %v2float %48 0
-         %61 = OpFAdd %v2float %59 %60
-         %62 = OpCompositeExtract %v2float %47 1
-         %63 = OpCompositeExtract %v2float %48 1
-         %64 = OpFAdd %v2float %62 %63
-         %65 = OpCompositeConstruct %mat2v2float %61 %64
-         %66 = OpMatrixTimesVector %v2float %65 %57
-         %67 = OpCompositeExtract %float %66 0
-         %68 = OpCompositeExtract %float %66 1
-         %69 = OpCompositeConstruct %v4float %67 %68 %11 %float_1
-               OpReturnValue %69
+         %47 = OpLabel
+  %indexable = OpVariable %_ptr_Function__arr_v2float_uint_3 Function %52
+         %53 = OpFunctionCall %mat2v2float %load_x_20_transform1
+         %54 = OpFunctionCall %mat2v2float %load_x_26_transform2
+               OpStore %indexable %60
+         %62 = OpAccessChain %_ptr_Function_v2float %indexable %gl_VertexIndex
+         %63 = OpLoad %v2float %62
+         %65 = OpCompositeExtract %v2float %53 0
+         %66 = OpCompositeExtract %v2float %54 0
+         %67 = OpFAdd %v2float %65 %66
+         %68 = OpCompositeExtract %v2float %53 1
+         %69 = OpCompositeExtract %v2float %54 1
+         %70 = OpFAdd %v2float %68 %69
+         %71 = OpCompositeConstruct %mat2v2float %67 %70
+         %72 = OpMatrixTimesVector %v2float %71 %63
+         %73 = OpCompositeExtract %float %72 0
+         %74 = OpCompositeExtract %float %72 1
+         %75 = OpCompositeConstruct %v4float %73 %74 %11 %float_1
+               OpReturnValue %75
                OpFunctionEnd
-       %main = OpFunction %void None %70
-         %73 = OpLabel
-         %75 = OpLoad %uint %gl_VertexIndex_1
-         %74 = OpFunctionCall %v4float %main_inner %75
-               OpStore %value %74
+       %main = OpFunction %void None %76
+         %79 = OpLabel
+         %81 = OpLoad %uint %gl_VertexIndex_1
+         %80 = OpFunctionCall %v4float %main_inner %81
+               OpStore %value %80
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.glsl b/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.glsl
index 8193622..808bc8f 100644
--- a/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.glsl
@@ -1,11 +1,6 @@
 #version 310 es
 precision mediump float;
 
-struct S {
-  mat3x2 matrix;
-  vec3 vector;
-};
-
 layout(binding = 0, std140) uniform S_std140_ubo {
   vec2 matrix_0;
   vec2 matrix_1;
diff --git a/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.spvasm b/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.spvasm
index 79f9c49..574781ee 100644
--- a/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.spvasm
+++ b/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 33
+; Bound: 37
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
@@ -37,25 +37,25 @@
      %uint_1 = OpConstant %uint 1
      %uint_2 = OpConstant %uint 2
        %void = OpTypeVoid
-         %23 = OpTypeFunction %void
+         %27 = OpTypeFunction %void
      %uint_3 = OpConstant %uint 3
 %_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
 %load_data_matrix = OpFunction %mat3v2float None %7
          %10 = OpLabel
-         %14 = OpAccessChain %_ptr_Uniform_v2float %data %uint_0
-         %15 = OpLoad %v2float %14
-         %17 = OpAccessChain %_ptr_Uniform_v2float %data %uint_1
-         %18 = OpLoad %v2float %17
-         %20 = OpAccessChain %_ptr_Uniform_v2float %data %uint_2
+         %16 = OpAccessChain %_ptr_Uniform_v2float %data %uint_0
+         %17 = OpLoad %v2float %16
+         %20 = OpAccessChain %_ptr_Uniform_v2float %data %uint_1
          %21 = OpLoad %v2float %20
-         %22 = OpCompositeConstruct %mat3v2float %15 %18 %21
-               OpReturnValue %22
+         %24 = OpAccessChain %_ptr_Uniform_v2float %data %uint_2
+         %25 = OpLoad %v2float %24
+         %26 = OpCompositeConstruct %mat3v2float %17 %21 %25
+               OpReturnValue %26
                OpFunctionEnd
-       %main = OpFunction %void None %23
-         %26 = OpLabel
-         %27 = OpFunctionCall %mat3v2float %load_data_matrix
-         %30 = OpAccessChain %_ptr_Uniform_v3float %data %uint_3
-         %31 = OpLoad %v3float %30
-         %32 = OpMatrixTimesVector %v2float %27 %31
+       %main = OpFunction %void None %27
+         %30 = OpLabel
+         %31 = OpFunctionCall %mat3v2float %load_data_matrix
+         %34 = OpAccessChain %_ptr_Uniform_v3float %data %uint_3
+         %35 = OpLoad %v3float %34
+         %36 = OpMatrixTimesVector %v2float %31 %35
                OpReturn
                OpFunctionEnd