tint: spir-v writer: Fix matrix constructor from matrix variable

Bug: tint:1603
Change-Id: I580a450daa9392316cb628ceeb16490ec591deba
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94860
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index 9d0d613..ab8952e 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -1362,6 +1362,15 @@
         }
     }
 
+    if (auto* res_mat = result_type->As<sem::Matrix>()) {
+        auto* value_type = args[0]->Type()->UnwrapRef();
+        if (auto* val_mat = value_type->As<sem::Matrix>()) {
+            // Generate passthrough for matrices of the same type
+            can_cast_or_copy =
+                (res_mat->columns() == val_mat->columns()) && (res_mat->rows() == val_mat->rows());
+        }
+    }
+
     if (can_cast_or_copy) {
         return GenerateCastOrCopyOrPassthrough(result_type, args[0]->Declaration(), global_var);
     }
@@ -1607,6 +1616,8 @@
         }
 
         return result_id;
+    } else if (from_type->Is<sem::Matrix>()) {
+        return val_id;
     } else {
         TINT_ICE(Writer, builder_.Diagnostics()) << "Invalid from_type";
     }
diff --git a/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl
new file mode 100644
index 0000000..0d79135
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+    var m = mat2x2<f32>();
+    let m_1 = mat2x2(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.glsl b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.glsl
new file mode 100644
index 0000000..ee78c72
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.glsl
@@ -0,0 +1,11 @@
+#version 310 es
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void unused_entry_point() {
+  return;
+}
+void f() {
+  mat2 m = mat2(vec2(0.0f), vec2(0.0f));
+  mat2 m_1 = mat2(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.hlsl b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.hlsl
new file mode 100644
index 0000000..b737fd2
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.hlsl
@@ -0,0 +1,9 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+void f() {
+  float2x2 m = float2x2((0.0f).xx, (0.0f).xx);
+  const float2x2 m_1 = float2x2(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.msl b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.msl
new file mode 100644
index 0000000..091d06a
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.msl
@@ -0,0 +1,8 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void f() {
+  float2x2 m = float2x2(float2(0.0f), float2(0.0f));
+  float2x2 const m_1 = float2x2(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.spvasm b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.spvasm
new file mode 100644
index 0000000..853903c
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.spvasm
@@ -0,0 +1,30 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %m "m"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat2v2float = OpTypeMatrix %v2float 2
+         %10 = OpConstantNull %mat2v2float
+%_ptr_Function_mat2v2float = OpTypePointer Function %mat2v2float
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %1
+          %6 = OpLabel
+          %m = OpVariable %_ptr_Function_mat2v2float Function %10
+               OpStore %m %10
+         %14 = OpLoad %mat2v2float %m
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.wgsl b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.wgsl
new file mode 100644
index 0000000..a7b8f43
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x2/load/f32.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+  var m = mat2x2<f32>();
+  let m_1 = mat2x2(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl
new file mode 100644
index 0000000..61ba845
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+    var m = mat2x3<f32>();
+    let m_1 = mat2x3(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.glsl b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.glsl
new file mode 100644
index 0000000..a6d4fef
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.glsl
@@ -0,0 +1,11 @@
+#version 310 es
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void unused_entry_point() {
+  return;
+}
+void f() {
+  mat2x3 m = mat2x3(vec3(0.0f), vec3(0.0f));
+  mat2x3 m_1 = mat2x3(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.hlsl b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.hlsl
new file mode 100644
index 0000000..488b65c
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.hlsl
@@ -0,0 +1,9 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+void f() {
+  float2x3 m = float2x3((0.0f).xxx, (0.0f).xxx);
+  const float2x3 m_1 = float2x3(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.msl b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.msl
new file mode 100644
index 0000000..62720d7
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.msl
@@ -0,0 +1,8 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void f() {
+  float2x3 m = float2x3(float3(0.0f), float3(0.0f));
+  float2x3 const m_1 = float2x3(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.spvasm b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.spvasm
new file mode 100644
index 0000000..7545cbd
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.spvasm
@@ -0,0 +1,30 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %m "m"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v3float = OpTypeVector %float 3
+%mat2v3float = OpTypeMatrix %v3float 2
+         %10 = OpConstantNull %mat2v3float
+%_ptr_Function_mat2v3float = OpTypePointer Function %mat2v3float
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %1
+          %6 = OpLabel
+          %m = OpVariable %_ptr_Function_mat2v3float Function %10
+               OpStore %m %10
+         %14 = OpLoad %mat2v3float %m
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.wgsl b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.wgsl
new file mode 100644
index 0000000..bdd3075
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x3/load/f32.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+  var m = mat2x3<f32>();
+  let m_1 = mat2x3(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl
new file mode 100644
index 0000000..a4a11f6
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+    var m = mat2x4<f32>();
+    let m_1 = mat2x4(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.glsl b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.glsl
new file mode 100644
index 0000000..f05ce0b
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.glsl
@@ -0,0 +1,11 @@
+#version 310 es
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void unused_entry_point() {
+  return;
+}
+void f() {
+  mat2x4 m = mat2x4(vec4(0.0f), vec4(0.0f));
+  mat2x4 m_1 = mat2x4(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.hlsl b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.hlsl
new file mode 100644
index 0000000..17da42a
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.hlsl
@@ -0,0 +1,9 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+void f() {
+  float2x4 m = float2x4((0.0f).xxxx, (0.0f).xxxx);
+  const float2x4 m_1 = float2x4(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.msl b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.msl
new file mode 100644
index 0000000..46b1478
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.msl
@@ -0,0 +1,8 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void f() {
+  float2x4 m = float2x4(float4(0.0f), float4(0.0f));
+  float2x4 const m_1 = float2x4(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.spvasm b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.spvasm
new file mode 100644
index 0000000..121e516
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.spvasm
@@ -0,0 +1,30 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %m "m"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%mat2v4float = OpTypeMatrix %v4float 2
+         %10 = OpConstantNull %mat2v4float
+%_ptr_Function_mat2v4float = OpTypePointer Function %mat2v4float
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %1
+          %6 = OpLabel
+          %m = OpVariable %_ptr_Function_mat2v4float Function %10
+               OpStore %m %10
+         %14 = OpLoad %mat2v4float %m
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.wgsl b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.wgsl
new file mode 100644
index 0000000..0cd645c
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat2x4/load/f32.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+  var m = mat2x4<f32>();
+  let m_1 = mat2x4(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl
new file mode 100644
index 0000000..07073d9
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+    var m = mat3x2<f32>();
+    let m_1 = mat3x2(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.glsl b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.glsl
new file mode 100644
index 0000000..018f1f2
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.glsl
@@ -0,0 +1,11 @@
+#version 310 es
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void unused_entry_point() {
+  return;
+}
+void f() {
+  mat3x2 m = mat3x2(vec2(0.0f), vec2(0.0f), vec2(0.0f));
+  mat3x2 m_1 = mat3x2(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.hlsl b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.hlsl
new file mode 100644
index 0000000..5ea45e8
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.hlsl
@@ -0,0 +1,9 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+void f() {
+  float3x2 m = float3x2((0.0f).xx, (0.0f).xx, (0.0f).xx);
+  const float3x2 m_1 = float3x2(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.msl b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.msl
new file mode 100644
index 0000000..b27479c
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.msl
@@ -0,0 +1,8 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void f() {
+  float3x2 m = float3x2(float2(0.0f), float2(0.0f), float2(0.0f));
+  float3x2 const m_1 = float3x2(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.spvasm b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.spvasm
new file mode 100644
index 0000000..6e73ae3
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.spvasm
@@ -0,0 +1,30 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %m "m"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat3v2float = OpTypeMatrix %v2float 3
+         %10 = OpConstantNull %mat3v2float
+%_ptr_Function_mat3v2float = OpTypePointer Function %mat3v2float
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %1
+          %6 = OpLabel
+          %m = OpVariable %_ptr_Function_mat3v2float Function %10
+               OpStore %m %10
+         %14 = OpLoad %mat3v2float %m
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.wgsl b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.wgsl
new file mode 100644
index 0000000..03b3213
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x2/load/f32.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+  var m = mat3x2<f32>();
+  let m_1 = mat3x2(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl
new file mode 100644
index 0000000..0fcea29
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+    var m = mat3x3<f32>();
+    let m_1 = mat3x3(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.glsl b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.glsl
new file mode 100644
index 0000000..640c151
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.glsl
@@ -0,0 +1,11 @@
+#version 310 es
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void unused_entry_point() {
+  return;
+}
+void f() {
+  mat3 m = mat3(vec3(0.0f), vec3(0.0f), vec3(0.0f));
+  mat3 m_1 = mat3(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.hlsl b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.hlsl
new file mode 100644
index 0000000..b8f5f60
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.hlsl
@@ -0,0 +1,9 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+void f() {
+  float3x3 m = float3x3((0.0f).xxx, (0.0f).xxx, (0.0f).xxx);
+  const float3x3 m_1 = float3x3(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.msl b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.msl
new file mode 100644
index 0000000..f7cc4fc
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.msl
@@ -0,0 +1,8 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void f() {
+  float3x3 m = float3x3(float3(0.0f), float3(0.0f), float3(0.0f));
+  float3x3 const m_1 = float3x3(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.spvasm b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.spvasm
new file mode 100644
index 0000000..7d55f41
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.spvasm
@@ -0,0 +1,30 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %m "m"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v3float = OpTypeVector %float 3
+%mat3v3float = OpTypeMatrix %v3float 3
+         %10 = OpConstantNull %mat3v3float
+%_ptr_Function_mat3v3float = OpTypePointer Function %mat3v3float
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %1
+          %6 = OpLabel
+          %m = OpVariable %_ptr_Function_mat3v3float Function %10
+               OpStore %m %10
+         %14 = OpLoad %mat3v3float %m
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.wgsl b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.wgsl
new file mode 100644
index 0000000..c38fae6
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x3/load/f32.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+  var m = mat3x3<f32>();
+  let m_1 = mat3x3(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl
new file mode 100644
index 0000000..385ba60
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+    var m = mat3x4<f32>();
+    let m_1 = mat3x4(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.glsl b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.glsl
new file mode 100644
index 0000000..73df09c
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.glsl
@@ -0,0 +1,11 @@
+#version 310 es
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void unused_entry_point() {
+  return;
+}
+void f() {
+  mat3x4 m = mat3x4(vec4(0.0f), vec4(0.0f), vec4(0.0f));
+  mat3x4 m_1 = mat3x4(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.hlsl b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.hlsl
new file mode 100644
index 0000000..0aa5662
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.hlsl
@@ -0,0 +1,9 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+void f() {
+  float3x4 m = float3x4((0.0f).xxxx, (0.0f).xxxx, (0.0f).xxxx);
+  const float3x4 m_1 = float3x4(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.msl b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.msl
new file mode 100644
index 0000000..2dc900e
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.msl
@@ -0,0 +1,8 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void f() {
+  float3x4 m = float3x4(float4(0.0f), float4(0.0f), float4(0.0f));
+  float3x4 const m_1 = float3x4(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.spvasm b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.spvasm
new file mode 100644
index 0000000..e2ef020
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.spvasm
@@ -0,0 +1,30 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %m "m"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%mat3v4float = OpTypeMatrix %v4float 3
+         %10 = OpConstantNull %mat3v4float
+%_ptr_Function_mat3v4float = OpTypePointer Function %mat3v4float
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %1
+          %6 = OpLabel
+          %m = OpVariable %_ptr_Function_mat3v4float Function %10
+               OpStore %m %10
+         %14 = OpLoad %mat3v4float %m
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.wgsl b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.wgsl
new file mode 100644
index 0000000..9d22dea
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat3x4/load/f32.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+  var m = mat3x4<f32>();
+  let m_1 = mat3x4(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl
new file mode 100644
index 0000000..9651287
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+    var m = mat4x2<f32>();
+    let m_1 = mat4x2(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.glsl b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.glsl
new file mode 100644
index 0000000..ae6ce5f
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.glsl
@@ -0,0 +1,11 @@
+#version 310 es
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void unused_entry_point() {
+  return;
+}
+void f() {
+  mat4x2 m = mat4x2(vec2(0.0f), vec2(0.0f), vec2(0.0f), vec2(0.0f));
+  mat4x2 m_1 = mat4x2(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.hlsl b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.hlsl
new file mode 100644
index 0000000..92ac9a0
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.hlsl
@@ -0,0 +1,9 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+void f() {
+  float4x2 m = float4x2((0.0f).xx, (0.0f).xx, (0.0f).xx, (0.0f).xx);
+  const float4x2 m_1 = float4x2(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.msl b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.msl
new file mode 100644
index 0000000..2f4e0c3
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.msl
@@ -0,0 +1,8 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void f() {
+  float4x2 m = float4x2(float2(0.0f), float2(0.0f), float2(0.0f), float2(0.0f));
+  float4x2 const m_1 = float4x2(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.spvasm b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.spvasm
new file mode 100644
index 0000000..66dbb32
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.spvasm
@@ -0,0 +1,30 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %m "m"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v2float = OpTypeVector %float 2
+%mat4v2float = OpTypeMatrix %v2float 4
+         %10 = OpConstantNull %mat4v2float
+%_ptr_Function_mat4v2float = OpTypePointer Function %mat4v2float
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %1
+          %6 = OpLabel
+          %m = OpVariable %_ptr_Function_mat4v2float Function %10
+               OpStore %m %10
+         %14 = OpLoad %mat4v2float %m
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.wgsl b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.wgsl
new file mode 100644
index 0000000..8c94760
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x2/load/f32.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+  var m = mat4x2<f32>();
+  let m_1 = mat4x2(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl
new file mode 100644
index 0000000..8ac728c
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+    var m = mat4x3<f32>();
+    let m_1 = mat4x3(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.glsl b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.glsl
new file mode 100644
index 0000000..13bad68
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.glsl
@@ -0,0 +1,11 @@
+#version 310 es
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void unused_entry_point() {
+  return;
+}
+void f() {
+  mat4x3 m = mat4x3(vec3(0.0f), vec3(0.0f), vec3(0.0f), vec3(0.0f));
+  mat4x3 m_1 = mat4x3(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.hlsl b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.hlsl
new file mode 100644
index 0000000..16edf13
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.hlsl
@@ -0,0 +1,9 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+void f() {
+  float4x3 m = float4x3((0.0f).xxx, (0.0f).xxx, (0.0f).xxx, (0.0f).xxx);
+  const float4x3 m_1 = float4x3(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.msl b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.msl
new file mode 100644
index 0000000..e5a0c7d
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.msl
@@ -0,0 +1,8 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void f() {
+  float4x3 m = float4x3(float3(0.0f), float3(0.0f), float3(0.0f), float3(0.0f));
+  float4x3 const m_1 = float4x3(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.spvasm b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.spvasm
new file mode 100644
index 0000000..220eba0
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.spvasm
@@ -0,0 +1,30 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %m "m"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v3float = OpTypeVector %float 3
+%mat4v3float = OpTypeMatrix %v3float 4
+         %10 = OpConstantNull %mat4v3float
+%_ptr_Function_mat4v3float = OpTypePointer Function %mat4v3float
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %1
+          %6 = OpLabel
+          %m = OpVariable %_ptr_Function_mat4v3float Function %10
+               OpStore %m %10
+         %14 = OpLoad %mat4v3float %m
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.wgsl b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.wgsl
new file mode 100644
index 0000000..a3186e8
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x3/load/f32.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+  var m = mat4x3<f32>();
+  let m_1 = mat4x3(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl
new file mode 100644
index 0000000..b361a63
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+    var m = mat4x4<f32>();
+    let m_1 = mat4x4(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.glsl b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.glsl
new file mode 100644
index 0000000..aa36f7c
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.glsl
@@ -0,0 +1,11 @@
+#version 310 es
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void unused_entry_point() {
+  return;
+}
+void f() {
+  mat4 m = mat4(vec4(0.0f), vec4(0.0f), vec4(0.0f), vec4(0.0f));
+  mat4 m_1 = mat4(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.hlsl b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.hlsl
new file mode 100644
index 0000000..03e51e9
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.hlsl
@@ -0,0 +1,9 @@
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+  return;
+}
+
+void f() {
+  float4x4 m = float4x4((0.0f).xxxx, (0.0f).xxxx, (0.0f).xxxx, (0.0f).xxxx);
+  const float4x4 m_1 = float4x4(m);
+}
diff --git a/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.msl b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.msl
new file mode 100644
index 0000000..019e73b
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.msl
@@ -0,0 +1,8 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void f() {
+  float4x4 m = float4x4(float4(0.0f), float4(0.0f), float4(0.0f), float4(0.0f));
+  float4x4 const m_1 = float4x4(m);
+}
+
diff --git a/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.spvasm b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.spvasm
new file mode 100644
index 0000000..373458c
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.spvasm
@@ -0,0 +1,30 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 15
+; Schema: 0
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+               OpExecutionMode %unused_entry_point LocalSize 1 1 1
+               OpName %unused_entry_point "unused_entry_point"
+               OpName %f "f"
+               OpName %m "m"
+       %void = OpTypeVoid
+          %1 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%mat4v4float = OpTypeMatrix %v4float 4
+         %10 = OpConstantNull %mat4v4float
+%_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
+%unused_entry_point = OpFunction %void None %1
+          %4 = OpLabel
+               OpReturn
+               OpFunctionEnd
+          %f = OpFunction %void None %1
+          %6 = OpLabel
+          %m = OpVariable %_ptr_Function_mat4v4float Function %10
+               OpStore %m %10
+         %14 = OpLoad %mat4v4float %m
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.wgsl b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.wgsl
new file mode 100644
index 0000000..6fabb6a
--- /dev/null
+++ b/test/tint/expressions/type_ctor/mat4x4/load/f32.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+fn f() {
+  var m = mat4x4<f32>();
+  let m_1 = mat4x4(m);
+}