tint/msl: Preserve trailing vec3 padding

In order to preserve padding properly for MSL, we need to use its
packed_vec type for all vec3 types in storage buffers, not just struct
members. This commit includes a complete rewrite of the PackedVec3
transform to achieve this. The key details are:

* An internal `__packed_vec3<>` type was added, which corresponds to a
  `type::Vector` with an additional flag to indicate that it will be
  emitted as packed vector.

* The `PackedVec3` transform replaces all vec3 types used in
  host-shareable address spaces with the internal `__packed_vec3`
  type. This includes vec3 types that appear as the store type of a
  pointer.

* When used as an array element, these `__packed_vec3` types are
  wrapped in a struct that contains a single `__packed_vec3`
  member. This allows us to add an `@align()` attribute that ensures
  that `array<vec3<T>>` still has the correct array element stride.

* When the `vec3<T>` appears as a struct member in the input program,
  we apply the `@align()` to that member to ensure that we do not
  change its offset.

* Matrix types with three rows that are used in memory are replaced
  with an array of columns, where each column uses a `__packed_vec3`
  inside an aligned wrapper structure as above.

* Accesses to host-shareable memory that involve any of these types
  invoke a "pack" or "unpack" helper function to convert them to the
  equivalent type that uses `__packed_vec3` or a regular `vec3` as
  required.

* The `chromium_internal_relaxed_uniform_layout` extension is used to
  avoid issues where modifying a type in the uniform address space
  triggers stricter layout validation rules.

Bug: tint:1571
Fixed: tint:1837
Change-Id: Idaf2da2f5bcb2be00c85ec657edfb614186476bb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121200
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/builtin/builtin.cc b/src/tint/builtin/builtin.cc
index 60449b5..dc608d0a 100644
--- a/src/tint/builtin/builtin.cc
+++ b/src/tint/builtin/builtin.cc
@@ -28,6 +28,9 @@
 /// @param str the string to parse
 /// @returns the parsed enum, or Builtin::kUndefined if the string could not be parsed.
 Builtin ParseBuiltin(std::string_view str) {
+    if (str == "__packed_vec3") {
+        return Builtin::kPackedVec3;
+    }
     if (str == "array") {
         return Builtin::kArray;
     }
@@ -242,6 +245,8 @@
     switch (value) {
         case Builtin::kUndefined:
             return out << "undefined";
+        case Builtin::kPackedVec3:
+            return out << "__packed_vec3";
         case Builtin::kArray:
             return out << "array";
         case Builtin::kAtomic:
diff --git a/src/tint/builtin/builtin.h b/src/tint/builtin/builtin.h
index f514109..25bac8b 100644
--- a/src/tint/builtin/builtin.h
+++ b/src/tint/builtin/builtin.h
@@ -30,6 +30,7 @@
 /// An enumerator of builtin builtin.
 enum class Builtin {
     kUndefined,
+    kPackedVec3,
     kArray,
     kAtomic,
     kBool,
@@ -112,6 +113,7 @@
 Builtin ParseBuiltin(std::string_view str);
 
 constexpr const char* kBuiltinStrings[] = {
+    "__packed_vec3",
     "array",
     "atomic",
     "bool",
diff --git a/src/tint/builtin/builtin_bench.cc b/src/tint/builtin/builtin_bench.cc
index 3c3134d..1f309f5 100644
--- a/src/tint/builtin/builtin_bench.cc
+++ b/src/tint/builtin/builtin_bench.cc
@@ -31,489 +31,496 @@
 
 void BuiltinParser(::benchmark::State& state) {
     const char* kStrings[] = {
-        "arccy",
-        "3a",
-        "aVray",
+        "__acked_veccc",
+        "_pac3ed_v3",
+        "__packeV_vec3",
+        "__packed_vec3",
+        "__pa1ked_vec3",
+        "_qqJcked_vec3",
+        "__pack77d_vllc3",
+        "arqHapp",
+        "vy",
+        "Grby",
         "array",
-        "arra1",
-        "qqrJy",
-        "arrll7y",
-        "atppmHHc",
-        "cto",
-        "abGmi",
+        "arviay",
+        "ar8WWy",
+        "Mxxra",
+        "atXggi",
+        "Xoic",
+        "ato3ic",
         "atomic",
-        "atvmiii",
-        "atWWm8c",
-        "xxtomc",
-        "bXgg",
-        "Xu",
-        "b3ol",
+        "aEomic",
+        "toTTiPP",
+        "ddtoxxi",
+        "44ool",
+        "VVSSol",
+        "RoRl",
         "bool",
-        "booE",
-        "TTPol",
-        "xxool",
-        "4416",
-        "fSVV6",
-        "RR2",
+        "oFl",
+        "boo",
+        "ORVHl",
+        "y1",
+        "l77rrn6",
+        "4016",
         "f16",
-        "96",
-        "f1",
-        "VOR6",
-        "y3",
-        "l77rrn2",
-        "4032",
-        "f32",
         "5",
-        "u377",
-        "kk2",
-        "ii",
-        "i3XX",
+        "u16",
+        "f",
+        "f3kk",
+        "fi",
+        "f3XX",
+        "f32",
         "55399II",
-        "i32",
-        "irSSHHa",
+        "frSSHHa",
         "U",
         "jV3",
-        "ax2",
-        "t2SGG",
-        "q2x2",
-        "mat2x2",
-        "at2",
-        "majjx",
+        "",
+        "GG",
+        "i32",
+        "2",
+        "",
+        "jj",
         "a2xrf",
-        "mat2xjf",
-        "mNNw2x28",
-        "matx2f",
-        "mat2x2f",
-        "mrrt2x2f",
-        "Gat2x2f",
+        "mat2j2",
+        "m82wNN2",
+        "mat2x2",
+        "mt2x2",
+        "rrat2x2",
+        "mGt2x2",
         "mat2x2FF",
-        "at2h",
-        "marrx2h",
-        "t2x2h",
-        "mat2x2h",
-        "Da2xJJh",
+        "at2f",
+        "marrx2f",
+        "mat2x2f",
+        "t2x2f",
+        "Da2xJJf",
         "ma82",
         "m11k2",
-        "matx3",
-        "maJx3",
-        "cat2x3",
-        "mat2x3",
-        "mat2O3",
-        "ttKavv2x__",
+        "matx2h",
+        "maJx2h",
+        "mat2x2h",
+        "mat2c2h",
+        "mat2x2O",
+        "KK_atvvtt2h",
         "5txxx8",
-        "__qatF3",
-        "matqx3f",
-        "33atOx3f",
-        "mat2x3f",
-        "mtt62x9oQQ",
-        "ma2x66f",
+        "a__xqq",
+        "maqq2x",
+        "mat2x3",
+        "ma32x66",
+        "mttQQo2x3",
+        "mat66x",
         "mtOxzz66",
-        "mat2yy3h",
+        "mat2yy3f",
         "ZaHH3Z",
-        "4WWt2q3h",
-        "mat2x3h",
-        "mOO2x3h",
-        "oatY3h",
+        "mat2x3f",
+        "4WWt2q3f",
+        "mOO2x3f",
+        "oatY3f",
         "matx",
-        "ma2x4",
-        "matw4",
-        "ma2Gf",
-        "mat2x4",
-        "qatKKx4",
-        "mmmt2x4",
+        "ma2xFh",
+        "at2x3w",
+        "mat2x3h",
+        "fGtxKh",
+        "matqKx3h",
+        "matmmxFh",
         "at2x4",
-        "mt2x4q",
-        "mat2xbb",
-        "mi2x4f",
-        "mat2x4f",
-        "maOO2xq",
-        "matTvvx4f",
+        "matxq",
+        "mb2bb4",
+        "mat2x4",
+        "it2x4",
+        "mOO2xq",
+        "mat2Tvv4",
         "maFF2x4f",
-        "Pa00xQh",
-        "mPt2x4h",
+        "Pa00xQf",
+        "mPt2x4f",
+        "mat2x4f",
         "ma772xss",
-        "mat2x4h",
-        "RRCbb2x4h",
-        "mXXt2x4h",
+        "RRCbb2x4f",
+        "mXXt2x4f",
         "qaCC2xOOh",
-        "mtsuL",
-        "mat3xX",
-        "mat3x",
-        "mat3x2",
-        "qqt2",
-        "mat3x22",
+        "ma2s4L",
+        "mXt2x4h",
+        "mat2x4h",
+        "mat24h",
+        "qa2O4",
+        "mat2x22h",
         "mzzyt3x",
-        "matVViP",
-        "mannC2f",
-        "atx2AHHq",
+        "atiVP2",
+        "mt3Cnn",
+        "mat3x2",
+        "AtqqHH2",
+        "at3x2",
+        "mafKK",
+        "ltgg2f",
+        "mat3xf",
+        "NTTtcx4f",
         "mat3x2f",
-        "may3x2",
-        "aOOOZZf",
-        "Vt12f",
-        "mff__3x2h",
-        "qaTMMl4h",
+        "ma7ppl2f",
         "mNNt3xg",
-        "mat3x2h",
-        "uub3XX2h",
+        "uub3XX2f",
         "matx2h",
         "Qt882h",
-        "maqx3",
-        "mat3113",
-        "Ft3xi22",
-        "mat3x3",
-        "m7t3x3",
+        "mt9q2h",
+        "mat3x2h",
+        "m11t3x2h",
+        "22at3iih",
+        "at3x277",
         "NNa323",
         "VVat3x3",
-        "FaWW3w11f",
-        "mawwx3f",
-        "Dat3x3f",
-        "mat3x3f",
-        "mt3x3K",
+        "ma11F3w3",
+        "mat3x3",
+        "matww3",
+        "mat3D3",
+        "maKx3",
         "mat31PPhf",
         "mat33f",
-        "mYYt3x3h",
+        "mYYt3x3f",
+        "mat3x3f",
         "mttHH3kk",
-        "mat3rr3h",
-        "mat3x3h",
-        "WWas3x3h",
+        "mat3rr3f",
+        "WWas3x3f",
         "Yt3x3h",
         "mt3qfh",
-        "vvafu224",
-        "mt34",
-        "maY34",
-        "mat3x4",
-        "YYa7y3E4",
+        "mav223xuh",
+        "mat3x3h",
+        "t3x3h",
+        "YYat3h",
+        "may3x3EYY",
         "Moatd4",
         "mt3xMM",
-        "mat3x55f",
-        "maN34",
-        "ma3Ox33",
+        "m55t3x4",
+        "mat3x4",
+        "maN4",
+        "ma33x4",
+        "mt3x3",
+        "mm66Issf",
+        "mat3x1f",
+        "Xt3x4",
         "mat3x4f",
-        "m3t3x4f",
-        "mam3xI",
-        "mnnt3r4K",
-        "m3XX",
-        "LatIx4h",
-        "at3fh",
-        "mat3x4h",
+        "LatIx4f",
+        "at3ff",
         "mYtURD4",
         "mah3x4h",
         "uuIqt3x",
-        "mat4xH",
-        "at4Qvv",
-        "66ate",
-        "mat4x2",
-        "mat7x",
+        "maH3x4h",
+        "mat3x4h",
+        "at3QQvv",
+        "at66eh",
+        "ma7O4h",
         "m0t55DD2",
         "IIaH4x2",
-        "at4x2",
-        "rat4x299",
-        "mGtt41W2f",
-        "mat4x2f",
-        "yatx2",
+        "mat4x",
+        "mat4x2",
+        "mt4r2",
+        "mat4xl",
+        "mGttx2",
+        "mat4y2",
         "mt4x2f",
         "IIaBB4x2f",
+        "mat4x2f",
         "TTat4x833",
-        "ddUUnntYYx2h",
+        "ddUUnntYYx2f",
         "m5CCxxdZ",
-        "mat4x2h",
         "matkkq2h",
         "005itpxh",
         "maIInnx2h",
-        "ccaKx",
-        "mtKK",
-        "ma664x3",
-        "mat4x3",
+        "mat4x2h",
+        "Ka4Wcc",
+        "m42KK",
+        "mat66x2h",
         "mKKtPx",
         "maxx43",
         "matqx3",
-        "MMayySrxf",
-        "mat3f",
-        "tx3f",
-        "mat4x3f",
+        "mat4x3",
+        "rMtyyxSS",
+        "uat4",
+        "tx3",
         "ma5F4x3f",
         "rra444z3f",
         "matWW",
-        "CatZJXx3h",
-        "maPPx3h",
-        "mat4c3h",
-        "mat4x3h",
+        "mat4x3f",
+        "CatZJXx3f",
+        "maPPx3f",
+        "mat4c3f",
         "matPPll6h",
         "mat993yy",
         "mat4JKKh",
-        "ma_x4",
-        "a4K4",
-        "kVt4xz",
-        "mat4x4",
+        "mat4x3h",
+        "mat4_h",
+        "ayK3h",
+        "mzt4V3k",
         "qaSKx4",
         "mat44",
         "ma4xVV",
-        "AAatIxUf",
-        "mbj4f",
-        "YY444x",
-        "mat4x4f",
+        "mat4x4",
+        "mAAt4xI",
+        "jb44",
+        "t4YYx",
         "mao4x4",
         "mtx114f",
         "mtmxccf",
-        "aJJ4x4h",
+        "mat4x4f",
+        "aJJ4x4f",
         "fCCDD4x4U",
-        "mgt4x4h",
-        "mat4x4h",
+        "mgt4x4f",
         "CCx4h",
         "mat4x66",
         "maN4M4h",
-        "pt",
-        "KW",
-        "pzzee",
-        "ptr",
+        "mat4x4h",
+        "mattth",
+        "maKWxh",
+        "mateezx4h",
         "",
         "w9",
         "4tnn",
-        "sllDler",
-        "oamp4er",
-        "wEaggler",
-        "sampler",
+        "ptr",
+        "tll",
+        "4to",
+        "wEgg",
         "gamler",
         "spleS",
         "aampl",
-        "sampZcRTr_comparison",
-        "sampler_88TmparisOn",
-        "sampler_comparim00n",
-        "sampler_comparison",
+        "sampler",
+        "TamplZRRr",
+        "sa8TplOr",
+        "m0ampler",
         "sampler_Bmomparison",
         "Mamper_ppomarison",
         "samper_compOOrison",
-        "teGtGre_1d",
-        "tex11ureHH1d",
-        "6exeeur_1FF",
-        "texture_1d",
+        "sampler_comparison",
+        "sampler_compGrGGon",
+        "sHHm11ler_comparison",
+        "sa6ler_FFeemparison",
         "texure_1",
         "tKiilure_1d",
         "exture_1d",
-        "99etvIIre_2d",
+        "texture_1d",
+        "99etvIIre_1d",
         "texture_d",
         "texture_hd",
-        "texture_2d",
         "llxzzure_PPd",
         "exue2d",
         "tffqqtre_2d",
-        "texJJre_2dd_arWay",
-        "teXXzzre_2darray",
-        "textu2_2d_array",
-        "texture_2d_array",
+        "texture_2d",
+        "texturJdd_d",
+        "trXXtu_2zz",
+        "textu2e2d",
         "tNyyture_2d_array",
         "txture_2d_rOOa",
         "textureErduaZPay",
-        "22lxtredd3ee",
-        "texVVe93d",
-        "teture_I1d",
-        "texture_3d",
+        "texture_2d_array",
+        "exl22re_2dd_areeay",
+        "mextureVV_ar9ay",
+        "teIItu1_2d_array",
         "tebture_3d",
         "ie7ure3d",
         "teotiire_3d",
-        "entre_cube",
-        "texturScube",
-        "tex22r_cube",
-        "texture_cube",
+        "texture_3d",
+        "extre_35",
+        "textre_iS",
+        "t22xtur_3",
         "teC711recuGe",
         "texture8cffbe",
         "textue_cue",
-        "tJJxture_SSube_array",
-        "texture_9ue_arry",
-        "TbbJJxture_cube_array",
-        "texture_cube_array",
+        "texture_cube",
+        "texture_SSJJbe",
+        "textrecu9e",
+        "TTeJJbture_cube",
         "t66ture_cube_aray",
         "textur66_cubu_arra",
         "textureWubeyarray",
-        "texture_deth_d",
-        "texture_epth_2d",
-        "texture_derth_2d",
-        "texture_depth_2d",
+        "texture_cube_array",
+        "texture_cube_ara",
+        "texture_ube_array",
+        "rexture_cube_array",
         "tex2ure_depth_2B",
         "texture_dpBBh_2d",
         "texture_dpth_RRd",
-        "tLLxture_deptVV0darray",
-        "textuOOe_dethKK2d_arra",
-        "textuwe_ggepth_2d_rray",
-        "texture_depth_2d_array",
+        "texture_depth_2d",
+        "tLL0Vure_deth_2d",
+        "tetKKredOOpth_2d",
+        "textgwre_dpth_2d",
         "textue_depthLh2d_arpay",
         "texture_depEh2diiKrray",
         "texture_dept_2d_array",
-        "textuUUe88dept_cbe",
-        "texrrure_depvvh_cube",
-        "texure_wepmmh_ube",
-        "texture_depth_cube",
+        "texture_depth_2d_array",
+        "t88xtuUUe_deph_2d_rray",
+        "texrruvve_depth_2d_array",
+        "texture_depmm_2d_wray",
         "tjture_d44pth_cube",
         "texture_depth_cXbe",
         "t8xture_depth_cube",
-        "textre_depth_cubeEEarrvvy",
-        "tzzture_d9pth_cuie_array",
-        "teAture_depth_QQube_GGrrJJy",
-        "texture_depth_cube_array",
+        "texture_depth_cube",
+        "textur_devvth_cubEE",
+        "tzxturi99epth_cube",
+        "teQQtuJJGe_nepth_cuAe",
         "texture_depth_cusse_array",
         "texture_Pepth_cKbe_array",
         "texture_dppp_cube_attray",
-        "texture_depth_multisample_2",
-        "texture_depth_multisamplMMd_2d",
-        "texJJure_de0th_multisampled_2d",
-        "texture_depth_multisampled_2d",
+        "texture_depth_cube_array",
+        "exture_deth_cube_array",
+        "texture_depth_MMube_array",
+        "tJJxture_depth_cube_a0ray",
         "textu8_dpth_mulisampled_2V",
         "texture_dhhpth_mKltisggmpled_2d",
         "texture_depth_multisampledf2d",
-        "tex77ure_exQernal",
-        "tYYxture_externa",
-        "tektur_exterSal",
-        "texture_external",
+        "texture_depth_multisampled_2d",
+        "te77ture_depth_multisamQled_2d",
+        "teture_depthYYmultisampled_2d",
+        "texture_deptk_multiampled_Sd",
         "txturn_ext2rnal",
         "txture_FFternal",
         "texUPPIre_GGxuernal",
-        "txtuEEe_mulaisFmpledv2d",
-        "ddexBBure_mltDDeampled_2d",
-        "teMture_EEulccisam55led_2",
-        "texture_multisampled_2d",
+        "texture_external",
+        "taxtuvEE_externl",
+        "textureexBddernDDl",
+        "tEEMtur_e55tccrnal",
         "texturemuKKtisample_d",
         "texture_multisRmpled_2d",
         "texturemulDisampl9d_2d",
-        "texturestorage_1d",
-        "textIre_storaa_1d",
-        "texture_sto77age_1d",
-        "texture_storage_1d",
+        "texture_multisampled_2d",
+        "teture_multisampled_2d",
+        "textuIa_multisampld_2d",
+        "texture_multisamp77ed_2d",
         "texIure_storage_1d",
         "texture_storagedd",
         "texture_storae_1d",
+        "texture_storage_1d",
         "texture_strate_d",
-        "texture33stoXXcge_2d",
-        "texturestorage_2E",
-        "texture_storage_2d",
+        "texture33stoXXcge_1d",
+        "texturestorage_1E",
         "textuXXestorage_2d",
         "texture_stoBaxxe_2d",
         "texte_storWge_2G",
-        "texture_storage_2d_ar66ay",
-        "t0xTTr_storave_2d_array",
-        "kexure_orage_2d_rray",
-        "texture_storage_2d_array",
+        "texture_storage_2d",
+        "texture_s66orage_2d",
+        "textvTr_so0age_2d",
+        "textureorgek2d",
         "textppre_stoae_2d_array",
         "textre_stora11e_d_array",
         "textureystorBEgeJ2d_array",
-        "textqreIImtxrage_3d",
-        "texture_toFage_3d",
-        "exture_Ytorage_3d",
-        "texture_storage_3d",
+        "texture_storage_2d_array",
+        "texture_mtorage_2dxIqrray",
+        "teture_storageF2d_array",
+        "textur_Ytorage_2d_array",
         "heDture_sHHorage_3d",
         "texturstorage23H",
         "teture_strage_3d",
-        "u2",
-        "u2",
-        "dd32",
-        "u32",
+        "texture_storage_3d",
+        "texture_storage_d",
+        "texturestorage_3d",
+        "ddexture_storage_3d",
         "uPO",
         "ba",
         "u02",
-        "veh2",
-        "vgY2",
-        "Oec2",
-        "vec2",
+        "u32",
+        "h32",
+        "gYY",
+        "O32",
         "eh",
         "ppfe2",
         "vev",
-        "vc2zz",
-        "vaac2",
-        "Ouuicf",
-        "vec2f",
+        "vec2",
+        "vzz2",
+        "vc2",
+        "OOii",
         "vGc2f",
         "22ecTTf",
         "dlc2f",
-        "vecbh",
+        "vec2f",
+        "vecbf",
         "ec2BB",
         "IIScXPP",
-        "vec2h",
         "jjec2h",
         "cc_c2h",
         "zz6xx2h",
+        "vec2h",
         "c2",
         "4xx2N",
-        "p0AAei",
-        "vec2i",
+        "p0AAeh",
         "vey2",
         "vbWW0i",
         "meMMtti",
-        "du",
+        "vec2i",
+        "di",
         "vvc_",
-        "VEEc2u",
-        "vec2u",
+        "VEEc2i",
         "vec24",
         "VVeX2u",
         "veVou",
-        "vec",
-        "KKc3",
-        "G",
-        "vec3",
+        "vec2u",
+        "ve2u",
+        "ecKKt",
+        "eG",
         "ea3",
         "OOc",
         "G",
-        "v5c3f",
-        "99jcfff",
-        "XXvYY3R",
-        "vec3f",
+        "vec3",
+        "ve53",
+        "9fjec3",
+        "vvXcRY",
         "ccf",
         "v8XX5",
         "ec3",
+        "vec3f",
         "ppc3cc",
-        "vecvh",
+        "vecvf",
         "eEE3SS",
-        "vec3h",
         "vec",
         "eh",
         "ec3ww",
-        "vecd99i",
+        "vec3h",
+        "vecd99h",
         "ve99P",
         "KKec3",
-        "vec3i",
         "ooMcDD",
         "vei",
         "vqi",
+        "vec3i",
         "veL30",
         "vncvv66",
         "vrrn3",
-        "vec3u",
         "vxxce",
         "NCCOc3u",
         "vc3u",
-        "veca",
-        "veNNN",
-        "vec",
-        "vec4",
+        "vec3u",
+        "aec4u",
+        "NNc3NN",
+        "ve3u",
         "vc",
         "vAYS4",
         "vec0",
-        "vecaaf",
-        "vmm4f",
-        "ec4f",
-        "vec4f",
+        "vec4",
+        "vecaa",
+        "mmcq",
+        "vc4",
         "vE4U",
         "veKD4",
         "v0t4__",
+        "vec4f",
         "cpA",
-        "ec4h",
-        "vBBc4h",
-        "vec4h",
+        "ec4f",
+        "vBBc4f",
         "vbnn99",
         "EEcAAh",
         "v5c66h",
-        "vHc4i",
-        "vecxi",
+        "vec4h",
+        "vHc4h",
+        "vecxh",
         "vzyn40",
-        "vec4i",
         "ve4i",
         "kH4i",
         "veci",
+        "vec4i",
         "oo4rr",
         "JJc4",
         "vcCC0",
-        "vec4u",
         "xAA99F",
         "veccu",
         "vec4S",
+        "vec4u",
+        "vocBB",
+        "ec4u",
+        "veemm",
     };
     for (auto _ : state) {
         for (auto* str : kStrings) {
diff --git a/src/tint/builtin/builtin_test.cc b/src/tint/builtin/builtin_test.cc
index 2908bc2..9ff8d99 100644
--- a/src/tint/builtin/builtin_test.cc
+++ b/src/tint/builtin/builtin_test.cc
@@ -43,6 +43,7 @@
 }
 
 static constexpr Case kValidCases[] = {
+    {"__packed_vec3", Builtin::kPackedVec3},
     {"array", Builtin::kArray},
     {"atomic", Builtin::kAtomic},
     {"bool", Builtin::kBool},
@@ -115,213 +116,216 @@
 };
 
 static constexpr Case kInvalidCases[] = {
-    {"arccy", Builtin::kUndefined},
-    {"3a", Builtin::kUndefined},
-    {"aVray", Builtin::kUndefined},
-    {"1tomic", Builtin::kUndefined},
-    {"aoqqic", Builtin::kUndefined},
-    {"atomll77", Builtin::kUndefined},
-    {"ppqooH", Builtin::kUndefined},
-    {"c", Builtin::kUndefined},
-    {"bGo", Builtin::kUndefined},
-    {"f1vi", Builtin::kUndefined},
-    {"f8WW", Builtin::kUndefined},
-    {"fxx", Builtin::kUndefined},
+    {"__acked_veccc", Builtin::kUndefined},
+    {"_pac3ed_v3", Builtin::kUndefined},
+    {"__packeV_vec3", Builtin::kUndefined},
+    {"arra1", Builtin::kUndefined},
+    {"qqrJy", Builtin::kUndefined},
+    {"arrll7y", Builtin::kUndefined},
+    {"atppmHHc", Builtin::kUndefined},
+    {"cto", Builtin::kUndefined},
+    {"abGmi", Builtin::kUndefined},
+    {"bovii", Builtin::kUndefined},
+    {"boWWl", Builtin::kUndefined},
+    {"Mxxl", Builtin::kUndefined},
     {"fgg", Builtin::kUndefined},
     {"X", Builtin::kUndefined},
-    {"332", Builtin::kUndefined},
-    {"iE2", Builtin::kUndefined},
-    {"iPTT", Builtin::kUndefined},
+    {"316", Builtin::kUndefined},
+    {"fE2", Builtin::kUndefined},
+    {"fPTT", Builtin::kUndefined},
     {"dxx2", Builtin::kUndefined},
-    {"44at2x2", Builtin::kUndefined},
-    {"mSSVV2x2", Builtin::kUndefined},
-    {"mat2R2", Builtin::kUndefined},
-    {"mF2x9f", Builtin::kUndefined},
-    {"matx2f", Builtin::kUndefined},
-    {"VOORRH2f", Builtin::kUndefined},
-    {"ma2xyh", Builtin::kUndefined},
-    {"llnarr2772h", Builtin::kUndefined},
+    {"4432", Builtin::kUndefined},
+    {"iSVV2", Builtin::kUndefined},
+    {"RR2", Builtin::kUndefined},
+    {"at292", Builtin::kUndefined},
+    {"mat2x", Builtin::kUndefined},
+    {"Vat2OR2", Builtin::kUndefined},
+    {"ma2xyf", Builtin::kUndefined},
+    {"llnarr2772f", Builtin::kUndefined},
     {"mat24200", Builtin::kUndefined},
-    {"m2oo", Builtin::kUndefined},
-    {"atzz3", Builtin::kUndefined},
-    {"1it2xpp", Builtin::kUndefined},
-    {"mat2xXXf", Builtin::kUndefined},
-    {"9II5ann2x3f", Builtin::kUndefined},
-    {"mataSSrHHYf", Builtin::kUndefined},
-    {"makkh", Builtin::kUndefined},
+    {"a2ooh", Builtin::kUndefined},
+    {"zz2x2h", Builtin::kUndefined},
+    {"miitppx1", Builtin::kUndefined},
+    {"maXX2x3", Builtin::kUndefined},
+    {"55IIt2nn99", Builtin::kUndefined},
+    {"aHHrrt2xSS", Builtin::kUndefined},
+    {"makkf", Builtin::kUndefined},
     {"jatgRx", Builtin::kUndefined},
     {"mb2x3", Builtin::kUndefined},
-    {"mat2j4", Builtin::kUndefined},
-    {"mt2x4", Builtin::kUndefined},
-    {"m2q4", Builtin::kUndefined},
-    {"matNN4f", Builtin::kUndefined},
-    {"at24vv", Builtin::kUndefined},
-    {"QQt2x4f", Builtin::kUndefined},
-    {"maffxr", Builtin::kUndefined},
     {"mat2xjh", Builtin::kUndefined},
+    {"at2x3h", Builtin::kUndefined},
+    {"q2x3h", Builtin::kUndefined},
+    {"mNN2x4", Builtin::kUndefined},
+    {"mavv4", Builtin::kUndefined},
+    {"maQQx4", Builtin::kUndefined},
+    {"maffxr", Builtin::kUndefined},
+    {"mat2xjf", Builtin::kUndefined},
     {"mNNw2x48", Builtin::kUndefined},
-    {"mt3x2", Builtin::kUndefined},
-    {"rrat3x2", Builtin::kUndefined},
-    {"mGt3x2", Builtin::kUndefined},
-    {"mat3x2FF", Builtin::kUndefined},
-    {"at3f", Builtin::kUndefined},
-    {"marrx2f", Builtin::kUndefined},
-    {"t3x2h", Builtin::kUndefined},
-    {"Da3xJJh", Builtin::kUndefined},
+    {"matx4h", Builtin::kUndefined},
+    {"mrrt2x4h", Builtin::kUndefined},
+    {"Gat2x4h", Builtin::kUndefined},
+    {"matFFx2", Builtin::kUndefined},
+    {"mtx", Builtin::kUndefined},
+    {"mrrt3x", Builtin::kUndefined},
+    {"t3x2f", Builtin::kUndefined},
+    {"Da3xJJf", Builtin::kUndefined},
     {"ma82", Builtin::kUndefined},
-    {"1k33", Builtin::kUndefined},
-    {"matx3", Builtin::kUndefined},
-    {"maJx3", Builtin::kUndefined},
-    {"mat3c3f", Builtin::kUndefined},
-    {"mat3x3O", Builtin::kUndefined},
-    {"KK_atvvtt3f", Builtin::kUndefined},
-    {"xx83x3h", Builtin::kUndefined},
+    {"m11k2", Builtin::kUndefined},
+    {"matx2h", Builtin::kUndefined},
+    {"maJx2h", Builtin::kUndefined},
+    {"cat3x3", Builtin::kUndefined},
+    {"mat3O3", Builtin::kUndefined},
+    {"ttKavv3x__", Builtin::kUndefined},
+    {"xx83x3f", Builtin::kUndefined},
     {"__qatF3", Builtin::kUndefined},
-    {"matqx3h", Builtin::kUndefined},
-    {"ma33x66", Builtin::kUndefined},
-    {"mttQQo3x4", Builtin::kUndefined},
-    {"mat66x", Builtin::kUndefined},
-    {"mtOxzz66", Builtin::kUndefined},
-    {"mat3yy4f", Builtin::kUndefined},
-    {"ZaHH4Z", Builtin::kUndefined},
-    {"4WWt3q4h", Builtin::kUndefined},
-    {"mOO3x4h", Builtin::kUndefined},
-    {"oatY4h", Builtin::kUndefined},
-    {"ax2", Builtin::kUndefined},
-    {"ma4x2", Builtin::kUndefined},
-    {"matw2", Builtin::kUndefined},
-    {"fGtxKf", Builtin::kUndefined},
-    {"matqKx2f", Builtin::kUndefined},
-    {"matmmxFf", Builtin::kUndefined},
-    {"at4x2h", Builtin::kUndefined},
+    {"matqx3f", Builtin::kUndefined},
+    {"33atOx3h", Builtin::kUndefined},
+    {"mtt63x9oQQ", Builtin::kUndefined},
+    {"ma3x66h", Builtin::kUndefined},
+    {"66aOzx4", Builtin::kUndefined},
+    {"myyt3x4", Builtin::kUndefined},
+    {"HHZx4", Builtin::kUndefined},
+    {"4WWt3q4f", Builtin::kUndefined},
+    {"mOO3x4f", Builtin::kUndefined},
+    {"oatY4f", Builtin::kUndefined},
+    {"matx", Builtin::kUndefined},
+    {"ma3xFh", Builtin::kUndefined},
+    {"at3x4w", Builtin::kUndefined},
+    {"ma4Gf", Builtin::kUndefined},
+    {"qatKKx2", Builtin::kUndefined},
+    {"mmmt4x2", Builtin::kUndefined},
+    {"at4x2f", Builtin::kUndefined},
     {"mt4x2q", Builtin::kUndefined},
     {"mat4xbb", Builtin::kUndefined},
-    {"it4x3", Builtin::kUndefined},
-    {"mOO4xq", Builtin::kUndefined},
-    {"mat4Tvv3", Builtin::kUndefined},
-    {"maFF4x3f", Builtin::kUndefined},
-    {"Pa00xQf", Builtin::kUndefined},
-    {"mPt4x3f", Builtin::kUndefined},
+    {"mi4x2h", Builtin::kUndefined},
+    {"maOO4xq", Builtin::kUndefined},
+    {"matTvvx2h", Builtin::kUndefined},
+    {"mat4FF3", Builtin::kUndefined},
+    {"mtQ00P", Builtin::kUndefined},
+    {"maP4x3", Builtin::kUndefined},
     {"ma774xss", Builtin::kUndefined},
-    {"RRCbb4x3h", Builtin::kUndefined},
-    {"mXXt4x3h", Builtin::kUndefined},
-    {"CCt4OOOO", Builtin::kUndefined},
-    {"mtsuL", Builtin::kUndefined},
-    {"mat4xX", Builtin::kUndefined},
-    {"mat44f", Builtin::kUndefined},
-    {"qa4O4", Builtin::kUndefined},
-    {"mat4x22f", Builtin::kUndefined},
+    {"RRCbb4x3f", Builtin::kUndefined},
+    {"mXXt4x3f", Builtin::kUndefined},
+    {"qaCC4xOOh", Builtin::kUndefined},
+    {"ma4s3L", Builtin::kUndefined},
+    {"mXt4x3h", Builtin::kUndefined},
+    {"mat4x", Builtin::kUndefined},
+    {"qqt4", Builtin::kUndefined},
+    {"mat4x22", Builtin::kUndefined},
     {"myzz40XX", Builtin::kUndefined},
     {"matVViP", Builtin::kUndefined},
-    {"mannC4h", Builtin::kUndefined},
-    {"pHAq", Builtin::kUndefined},
-    {"tr", Builtin::kUndefined},
-    {"Kf", Builtin::kUndefined},
-    {"lmgger", Builtin::kUndefined},
-    {"samplr", Builtin::kUndefined},
-    {"NTTmcl4r", Builtin::kUndefined},
-    {"sampler_clmppri77on", Builtin::kUndefined},
-    {"samplg_czzmparNNso", Builtin::kUndefined},
-    {"smpleuuXXomparibbon", Builtin::kUndefined},
-    {"texture_1", Builtin::kUndefined},
-    {"t88tueQ1K", Builtin::kUndefined},
-    {"texturq9d", Builtin::kUndefined},
-    {"text11re_2d", Builtin::kUndefined},
-    {"teiiu22eF2d", Builtin::kUndefined},
-    {"tex77ur_2d", Builtin::kUndefined},
-    {"textNNr2_d_array", Builtin::kUndefined},
-    {"textVVre_2d_array", Builtin::kUndefined},
-    {"texwure_WWF_11rray", Builtin::kUndefined},
-    {"txture_3ww", Builtin::kUndefined},
-    {"texturD_3d", Builtin::kUndefined},
-    {"teKture_d", Builtin::kUndefined},
-    {"11exPPufe_cubh", Builtin::kUndefined},
-    {"textue_cube", Builtin::kUndefined},
-    {"texture_cubYY", Builtin::kUndefined},
-    {"texttr_cube_HHkkVay", Builtin::kUndefined},
-    {"texture_crrbe_array", Builtin::kUndefined},
-    {"texturesscubeWWaray", Builtin::kUndefined},
-    {"texture_deptY_d", Builtin::kUndefined},
-    {"teLturq_defh_2d", Builtin::kUndefined},
-    {"texvvre_duu22th_2d", Builtin::kUndefined},
-    {"texure_deth_2d_array", Builtin::kUndefined},
-    {"texturYY_depth_2daray", Builtin::kUndefined},
-    {"texturE_77epth_2d_aryYay", Builtin::kUndefined},
-    {"Mexdoore_depth_cue", Builtin::kUndefined},
-    {"texturedepMMh_cube", Builtin::kUndefined},
-    {"texture55depth_cube", Builtin::kUndefined},
-    {"textue_depth_cbe_aNray", Builtin::kUndefined},
-    {"texture_dpth_c33be_array", Builtin::kUndefined},
-    {"texture_depth_cub3_array", Builtin::kUndefined},
-    {"texIure_mepth_mulisampled_2d", Builtin::kUndefined},
-    {"texture_depthrmKltisampled_2nn", Builtin::kUndefined},
-    {"textur_depth_multismXld_2d", Builtin::kUndefined},
-    {"texpure_exLLeIna", Builtin::kUndefined},
-    {"txture_exfrnal", Builtin::kUndefined},
-    {"teUture_extYRRDl", Builtin::kUndefined},
-    {"texturehmultisampled_2d", Builtin::kUndefined},
-    {"texturqmultsIImuuled_2d", Builtin::kUndefined},
-    {"Hexture_multisampled_2d", Builtin::kUndefined},
-    {"texQQur_storge_vvd", Builtin::kUndefined},
-    {"texeure_66oage_1d", Builtin::kUndefined},
-    {"texture_stoage71d", Builtin::kUndefined},
-    {"texture_s55or0ge_2DD", Builtin::kUndefined},
-    {"teHture_storIIge_2d", Builtin::kUndefined},
-    {"textue_storage_2d", Builtin::kUndefined},
-    {"texturestorage_2d_rrray", Builtin::kUndefined},
-    {"textule_storage_2d_array", Builtin::kUndefined},
-    {"tetture_JJtorage_Gd_arra", Builtin::kUndefined},
-    {"yexture_storage3d", Builtin::kUndefined},
-    {"texturestorage_3d", Builtin::kUndefined},
-    {"texture_IItorBBge_3d", Builtin::kUndefined},
-    {"TTK33", Builtin::kUndefined},
-    {"nnUYdSS2", Builtin::kUndefined},
-    {"x5dZ", Builtin::kUndefined},
-    {"veckq", Builtin::kUndefined},
-    {"ii500", Builtin::kUndefined},
-    {"vecIIn", Builtin::kUndefined},
-    {"cceW", Builtin::kUndefined},
-    {"cKK", Builtin::kUndefined},
-    {"vec66f", Builtin::kUndefined},
-    {"vePPK", Builtin::kUndefined},
-    {"vexxh", Builtin::kUndefined},
-    {"qec2h", Builtin::kUndefined},
+    {"mannC4f", Builtin::kUndefined},
+    {"atx4AHHq", Builtin::kUndefined},
+    {"may4x4", Builtin::kUndefined},
+    {"aOOOZZh", Builtin::kUndefined},
+    {"V", Builtin::kUndefined},
+    {"ptf__", Builtin::kUndefined},
+    {"4lMT", Builtin::kUndefined},
+    {"sNNmplg", Builtin::kUndefined},
+    {"uubpXXer", Builtin::kUndefined},
+    {"samler", Builtin::kUndefined},
+    {"m88ler_cQmparisoK", Builtin::kUndefined},
+    {"qa9ler_comparison", Builtin::kUndefined},
+    {"sampler_comparis11n", Builtin::kUndefined},
+    {"teiiu22eF1d", Builtin::kUndefined},
+    {"tex77ur_1d", Builtin::kUndefined},
+    {"te2urNN_1d", Builtin::kUndefined},
+    {"texturVV_2d", Builtin::kUndefined},
+    {"WWFxtu11e_wd", Builtin::kUndefined},
+    {"txture_2ww", Builtin::kUndefined},
+    {"texture_2d_arrDy", Builtin::kUndefined},
+    {"teKtre_2d_array", Builtin::kUndefined},
+    {"texhure_2fra11raPP", Builtin::kUndefined},
+    {"texture3d", Builtin::kUndefined},
+    {"texture_3YY", Builtin::kUndefined},
+    {"HHtxtrkk_3d", Builtin::kUndefined},
+    {"texrrure_cube", Builtin::kUndefined},
+    {"tssxturWW_cue", Builtin::kUndefined},
+    {"teYure_cube", Builtin::kUndefined},
+    {"txture_Lufe_arraq", Builtin::kUndefined},
+    {"te22ture_uuubevvfray", Builtin::kUndefined},
+    {"texturecube_aray", Builtin::kUndefined},
+    {"texture_Yepth_2", Builtin::kUndefined},
+    {"teytYYEe_77epth_2d", Builtin::kUndefined},
+    {"teMture_deootd2d", Builtin::kUndefined},
+    {"texMMre_depth_2d_array", Builtin::kUndefined},
+    {"texture_depth_2d_arra55", Builtin::kUndefined},
+    {"texture_deh_2d_aNray", Builtin::kUndefined},
+    {"te3ture_dpth_cO3be", Builtin::kUndefined},
+    {"texture_depth_cub3", Builtin::kUndefined},
+    {"Iexturedepth_cume", Builtin::kUndefined},
+    {"texture_depthnncube_Krrry", Builtin::kUndefined},
+    {"texture_dth_XXube_rra", Builtin::kUndefined},
+    {"textIre_depph_ubeLLarray", Builtin::kUndefined},
+    {"txtfre_depthmultisampled_2d", Builtin::kUndefined},
+    {"texURuYe_Depthmultisampled_2d", Builtin::kUndefined},
+    {"texture_depth_multisamphed_2d", Builtin::kUndefined},
+    {"teqtureuIIextnal", Builtin::kUndefined},
+    {"texture_externaH", Builtin::kUndefined},
+    {"texre_externaQvv", Builtin::kUndefined},
+    {"textureemultismp66ed_d", Builtin::kUndefined},
+    {"tW7trO_multisampled_2d", Builtin::kUndefined},
+    {"texture_mult550ampled_2DD", Builtin::kUndefined},
+    {"teHture_storIIge_1d", Builtin::kUndefined},
+    {"textue_storage_1d", Builtin::kUndefined},
+    {"rexture_storae_1d", Builtin::kUndefined},
+    {"texture_stolage_2d", Builtin::kUndefined},
+    {"txture_JJtGrgtt_2d", Builtin::kUndefined},
+    {"yexture_storage2d", Builtin::kUndefined},
+    {"texture_storage_2d_rray", Builtin::kUndefined},
+    {"texture_IItorage_2d_BBrray", Builtin::kUndefined},
+    {"33exture_TTtorge_Kd_ar88ay", Builtin::kUndefined},
+    {"texSnnYUUure_storage_3d", Builtin::kUndefined},
+    {"textuxe_5torCCdZ_3d", Builtin::kUndefined},
+    {"tkkxture_storaqe_3d", Builtin::kUndefined},
+    {"5i00", Builtin::kUndefined},
+    {"unII2", Builtin::kUndefined},
+    {"cc", Builtin::kUndefined},
+    {"KK", Builtin::kUndefined},
+    {"66ec2", Builtin::kUndefined},
+    {"PPEK", Builtin::kUndefined},
+    {"vexxf", Builtin::kUndefined},
+    {"qec2f", Builtin::kUndefined},
     {"veSyMMr", Builtin::kUndefined},
     {"v2u", Builtin::kUndefined},
     {"ec", Builtin::kUndefined},
-    {"5eFF2u", Builtin::kUndefined},
+    {"5eFF2h", Builtin::kUndefined},
     {"rrecz44", Builtin::kUndefined},
     {"vWW", Builtin::kUndefined},
-    {"ZJJCcX", Builtin::kUndefined},
-    {"vcPP", Builtin::kUndefined},
-    {"vec", Builtin::kUndefined},
-    {"3Le003f", Builtin::kUndefined},
-    {"MMec3RR", Builtin::kUndefined},
-    {"vec39K", Builtin::kUndefined},
-    {"yyecm", Builtin::kUndefined},
-    {"v__cD", Builtin::kUndefined},
-    {"vec3U", Builtin::kUndefined},
-    {"ze333i", Builtin::kUndefined},
-    {"eKti", Builtin::kUndefined},
-    {"ve3V", Builtin::kUndefined},
-    {"jbR3K", Builtin::kUndefined},
-    {"e44344", Builtin::kUndefined},
-    {"00u", Builtin::kUndefined},
-    {"WK4", Builtin::kUndefined},
-    {"m", Builtin::kUndefined},
-    {"vJJ", Builtin::kUndefined},
-    {"lDDcUfC", Builtin::kUndefined},
-    {"vec4g", Builtin::kUndefined},
-    {"CCe", Builtin::kUndefined},
-    {"ec4h", Builtin::kUndefined},
-    {"vIc__h", Builtin::kUndefined},
+    {"XJecCZZ", Builtin::kUndefined},
+    {"vePP2", Builtin::kUndefined},
+    {"vec2c", Builtin::kUndefined},
+    {"ve6ll2u", Builtin::kUndefined},
+    {"vey99", Builtin::kUndefined},
+    {"vKKc3", Builtin::kUndefined},
+    {"x_3", Builtin::kUndefined},
+    {"Ky3", Builtin::kUndefined},
+    {"zek3f", Builtin::kUndefined},
+    {"veKSf", Builtin::kUndefined},
+    {"vc3h", Builtin::kUndefined},
+    {"ec3VV", Builtin::kUndefined},
+    {"IAAc3h", Builtin::kUndefined},
+    {"jbR", Builtin::kUndefined},
+    {"veY4", Builtin::kUndefined},
+    {"ec3i", Builtin::kUndefined},
+    {"vc911", Builtin::kUndefined},
+    {"mmccu", Builtin::kUndefined},
+    {"vJJcu", Builtin::kUndefined},
+    {"lDCfcU", Builtin::kUndefined},
+    {"veg4", Builtin::kUndefined},
+    {"CC", Builtin::kUndefined},
+    {"ec4f", Builtin::kUndefined},
+    {"vIc__f", Builtin::kUndefined},
     {"ePPtt", Builtin::kUndefined},
-    {"v3dc4i", Builtin::kUndefined},
-    {"vcyyi", Builtin::kUndefined},
+    {"v3dc4h", Builtin::kUndefined},
+    {"vcyyh", Builtin::kUndefined},
     {"u4", Builtin::kUndefined},
-    {"v03nnu", Builtin::kUndefined},
+    {"v03nni", Builtin::kUndefined},
     {"Cuuecnv", Builtin::kUndefined},
     {"vX4ll", Builtin::kUndefined},
+    {"vocppu", Builtin::kUndefined},
+    {"vwwc4", Builtin::kUndefined},
+    {"veuug", Builtin::kUndefined},
 };
 
 using BuiltinParseTest = testing::TestWithParam<Case>;
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index 4b85f3f..7a5334f 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -211,6 +211,9 @@
   texture_storage_3d
   // https://www.w3.org/TR/WGSL/#external-texture-type
   texture_external
+
+  // Internal types.
+  __packed_vec3
 }
 
 // https://gpuweb.github.io/gpuweb/wgsl/#attributes
@@ -289,6 +292,7 @@
 type texture_storage_2d_array<F: texel_format, A: access>
 type texture_storage_3d<F: texel_format, A: access>
 type texture_external
+type packedVec3<T>
 
 @display("__modf_result_{T}")        type __modf_result<T>
 @display("__modf_result_vec{N}_{T}") type __modf_result_vec<N: num, T>
@@ -1001,6 +1005,9 @@
 @must_use @const conv mat4x4<T: f16>(mat4x4<f32>) -> mat4x4<f16>
 @must_use @const conv mat4x4<T: f32>(mat4x4<f16>) -> mat4x4<f32>
 
+// Conversion from vec3 to internal __packed_vec3 type.
+@must_use @const conv packedVec3<T: concrete_scalar>(vec3<T>) -> packedVec3<T>
+
 ////////////////////////////////////////////////////////////////////////////////
 // Operators                                                                  //
 //                                                                            //
diff --git a/src/tint/resolver/ctor_conv_intrinsic.cc b/src/tint/resolver/ctor_conv_intrinsic.cc
index 3ac3a67..1609e49 100644
--- a/src/tint/resolver/ctor_conv_intrinsic.cc
+++ b/src/tint/resolver/ctor_conv_intrinsic.cc
@@ -62,6 +62,8 @@
             return "mat4x3";
         case CtorConvIntrinsic::kMat4x4:
             return "mat4x4";
+        case CtorConvIntrinsic::kPackedVec3:
+            return "packedVec3";
     }
     return "<unknown>";
 }
diff --git a/src/tint/resolver/ctor_conv_intrinsic.h b/src/tint/resolver/ctor_conv_intrinsic.h
index 4ee1c79..f294394 100644
--- a/src/tint/resolver/ctor_conv_intrinsic.h
+++ b/src/tint/resolver/ctor_conv_intrinsic.h
@@ -48,6 +48,7 @@
     kMat4x2,
     kMat4x3,
     kMat4x4,
+    kPackedVec3,
 };
 
 /// @returns the name of the type.
diff --git a/src/tint/resolver/intrinsic_table.cc b/src/tint/resolver/intrinsic_table.cc
index 17927db..623c08b 100644
--- a/src/tint/resolver/intrinsic_table.cc
+++ b/src/tint/resolver/intrinsic_table.cc
@@ -456,6 +456,25 @@
 constexpr auto build_vec3 = build_vec<3>;
 constexpr auto build_vec4 = build_vec<4>;
 
+bool match_packedVec3(MatchState&, const type::Type* ty, const type::Type*& T) {
+    if (ty->Is<Any>()) {
+        T = ty;
+        return true;
+    }
+
+    if (auto* v = ty->As<type::Vector>()) {
+        if (v->Packed()) {
+            T = v->type();
+            return true;
+        }
+    }
+    return false;
+}
+
+const type::Vector* build_packedVec3(MatchState& state, const type::Type* el) {
+    return state.builder.create<type::Vector>(el, 3u, /* packed */ true);
+}
+
 bool match_mat(MatchState&, const type::Type* ty, Number& M, Number& N, const type::Type*& T) {
     if (ty->Is<Any>()) {
         M = Number::any;
diff --git a/src/tint/resolver/intrinsic_table.inl b/src/tint/resolver/intrinsic_table.inl
index a4b5e14..1143d98 100644
--- a/src/tint/resolver/intrinsic_table.inl
+++ b/src/tint/resolver/intrinsic_table.inl
@@ -1370,6 +1370,38 @@
   return "texture_external";
 }
 
+/// TypeMatcher for 'type packedVec3'
+class PackedVec3 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const type::Type* Match(MatchState& state,
+                         const type::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const type::Type* PackedVec3::Match(MatchState& state, const type::Type* ty) const {
+  const type::Type* T = nullptr;
+  if (!match_packedVec3(state, ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_packedVec3(state, T);
+}
+
+std::string PackedVec3::String(MatchState* state) const {
+  const std::string T = state->TypeName();
+  return "packedVec3<" + T + ">";
+}
+
 /// TypeMatcher for 'type __modf_result'
 class ModfResult : public TypeMatcher {
  public:
@@ -2667,6 +2699,7 @@
   TextureStorage2DArray TextureStorage2DArray_;
   TextureStorage3D TextureStorage3D_;
   TextureExternal TextureExternal_;
+  PackedVec3 PackedVec3_;
   ModfResult ModfResult_;
   ModfResultVec ModfResultVec_;
   FrexpResult FrexpResult_;
@@ -2709,7 +2742,7 @@
   ~Matchers();
 
   /// The template types, types, and type matchers
-  TypeMatcher const* const type[72] = {
+  TypeMatcher const* const type[73] = {
     /* [0] */ &template_type_0_,
     /* [1] */ &template_type_1_,
     /* [2] */ &template_type_2_,
@@ -2757,31 +2790,32 @@
     /* [44] */ &TextureStorage2DArray_,
     /* [45] */ &TextureStorage3D_,
     /* [46] */ &TextureExternal_,
-    /* [47] */ &ModfResult_,
-    /* [48] */ &ModfResultVec_,
-    /* [49] */ &FrexpResult_,
-    /* [50] */ &FrexpResultVec_,
-    /* [51] */ &AtomicCompareExchangeResult_,
-    /* [52] */ &Scalar_,
-    /* [53] */ &ConcreteScalar_,
-    /* [54] */ &ScalarNoF32_,
-    /* [55] */ &ScalarNoF16_,
-    /* [56] */ &ScalarNoI32_,
-    /* [57] */ &ScalarNoU32_,
-    /* [58] */ &ScalarNoBool_,
-    /* [59] */ &FiaFiu32F16_,
-    /* [60] */ &FiaFi32F16_,
-    /* [61] */ &FiaFiu32_,
-    /* [62] */ &FaF32_,
-    /* [63] */ &FaF32F16_,
-    /* [64] */ &IaIu32_,
-    /* [65] */ &IaI32_,
-    /* [66] */ &Fiu32F16_,
-    /* [67] */ &Fiu32_,
-    /* [68] */ &Fi32F16_,
-    /* [69] */ &Fi32_,
-    /* [70] */ &F32F16_,
-    /* [71] */ &Iu32_,
+    /* [47] */ &PackedVec3_,
+    /* [48] */ &ModfResult_,
+    /* [49] */ &ModfResultVec_,
+    /* [50] */ &FrexpResult_,
+    /* [51] */ &FrexpResultVec_,
+    /* [52] */ &AtomicCompareExchangeResult_,
+    /* [53] */ &Scalar_,
+    /* [54] */ &ConcreteScalar_,
+    /* [55] */ &ScalarNoF32_,
+    /* [56] */ &ScalarNoF16_,
+    /* [57] */ &ScalarNoI32_,
+    /* [58] */ &ScalarNoU32_,
+    /* [59] */ &ScalarNoBool_,
+    /* [60] */ &FiaFiu32F16_,
+    /* [61] */ &FiaFi32F16_,
+    /* [62] */ &FiaFiu32_,
+    /* [63] */ &FaF32_,
+    /* [64] */ &FaF32F16_,
+    /* [65] */ &IaIu32_,
+    /* [66] */ &IaI32_,
+    /* [67] */ &Fiu32F16_,
+    /* [68] */ &Fiu32_,
+    /* [69] */ &Fi32F16_,
+    /* [70] */ &Fi32_,
+    /* [71] */ &F32F16_,
+    /* [72] */ &Iu32_,
   };
 
   /// The template numbers, and number matchers
@@ -2848,13 +2882,13 @@
   /* [40] */ 23,
   /* [41] */ 0,
   /* [42] */ 9,
-  /* [43] */ 50,
+  /* [43] */ 51,
   /* [44] */ 0,
   /* [45] */ 0,
   /* [46] */ 23,
   /* [47] */ 0,
   /* [48] */ 1,
-  /* [49] */ 48,
+  /* [49] */ 49,
   /* [50] */ 0,
   /* [51] */ 0,
   /* [52] */ 42,
@@ -2913,9 +2947,9 @@
   /* [105] */ 8,
   /* [106] */ 12,
   /* [107] */ 0,
-  /* [108] */ 49,
+  /* [108] */ 50,
   /* [109] */ 0,
-  /* [110] */ 47,
+  /* [110] */ 48,
   /* [111] */ 0,
   /* [112] */ 11,
   /* [113] */ 9,
@@ -2967,7 +3001,7 @@
   /* [159] */ 1,
   /* [160] */ 12,
   /* [161] */ 1,
-  /* [162] */ 51,
+  /* [162] */ 52,
   /* [163] */ 0,
   /* [164] */ 11,
   /* [165] */ 10,
@@ -3037,14 +3071,16 @@
   /* [229] */ 9,
   /* [230] */ 22,
   /* [231] */ 10,
-  /* [232] */ 37,
-  /* [233] */ 38,
-  /* [234] */ 39,
-  /* [235] */ 40,
-  /* [236] */ 41,
-  /* [237] */ 46,
-  /* [238] */ 28,
-  /* [239] */ 29,
+  /* [232] */ 47,
+  /* [233] */ 0,
+  /* [234] */ 37,
+  /* [235] */ 38,
+  /* [236] */ 39,
+  /* [237] */ 40,
+  /* [238] */ 41,
+  /* [239] */ 46,
+  /* [240] */ 28,
+  /* [241] */ 29,
 };
 
 // Assert that the MatcherIndex is big enough to index all the matchers, plus
@@ -3387,7 +3423,7 @@
   {
     /* [66] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [67] */
@@ -3427,7 +3463,7 @@
   {
     /* [74] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [75] */
@@ -3447,12 +3483,12 @@
   {
     /* [78] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [79] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [80] */
@@ -3482,7 +3518,7 @@
   {
     /* [85] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [86] */
@@ -3507,12 +3543,12 @@
   {
     /* [90] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [91] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [92] */
@@ -3537,12 +3573,12 @@
   {
     /* [96] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [97] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [98] */
@@ -3572,7 +3608,7 @@
   {
     /* [103] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [104] */
@@ -3602,7 +3638,7 @@
   {
     /* [109] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [110] */
@@ -3632,7 +3668,7 @@
   {
     /* [115] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [116] */
@@ -3662,7 +3698,7 @@
   {
     /* [121] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [122] */
@@ -3692,7 +3728,7 @@
   {
     /* [127] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [128] */
@@ -3717,12 +3753,12 @@
   {
     /* [132] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [133] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [134] */
@@ -3817,7 +3853,7 @@
   {
     /* [152] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [153] */
@@ -3842,7 +3878,7 @@
   {
     /* [157] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [158] */
@@ -3867,7 +3903,7 @@
   {
     /* [162] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [163] */
@@ -3882,12 +3918,12 @@
   {
     /* [165] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [166] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [167] */
@@ -3907,12 +3943,12 @@
   {
     /* [170] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [171] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [172] */
@@ -3932,12 +3968,12 @@
   {
     /* [175] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [176] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [177] */
@@ -3957,12 +3993,12 @@
   {
     /* [180] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[235],
+    /* matcher indices */ &kMatcherIndices[237],
   },
   {
     /* [181] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [182] */
@@ -3987,7 +4023,7 @@
   {
     /* [186] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [187] */
@@ -4007,12 +4043,12 @@
   {
     /* [190] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [191] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [192] */
@@ -4037,7 +4073,7 @@
   {
     /* [196] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [197] */
@@ -4062,7 +4098,7 @@
   {
     /* [201] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [202] */
@@ -4087,7 +4123,7 @@
   {
     /* [206] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [207] */
@@ -4112,7 +4148,7 @@
   {
     /* [211] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [212] */
@@ -4132,12 +4168,12 @@
   {
     /* [215] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [216] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [217] */
@@ -4157,12 +4193,12 @@
   {
     /* [220] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [221] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [222] */
@@ -4182,12 +4218,12 @@
   {
     /* [225] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[235],
+    /* matcher indices */ &kMatcherIndices[237],
   },
   {
     /* [226] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [227] */
@@ -4207,12 +4243,12 @@
   {
     /* [230] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [231] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [232] */
@@ -4232,12 +4268,12 @@
   {
     /* [235] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [236] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [237] */
@@ -4257,12 +4293,12 @@
   {
     /* [240] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[235],
+    /* matcher indices */ &kMatcherIndices[237],
   },
   {
     /* [241] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [242] */
@@ -4287,7 +4323,7 @@
   {
     /* [246] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [247] */
@@ -4312,7 +4348,7 @@
   {
     /* [251] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [252] */
@@ -4337,7 +4373,7 @@
   {
     /* [256] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [257] */
@@ -4362,7 +4398,7 @@
   {
     /* [261] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [262] */
@@ -4387,7 +4423,7 @@
   {
     /* [266] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [267] */
@@ -4412,7 +4448,7 @@
   {
     /* [271] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [272] */
@@ -4437,7 +4473,7 @@
   {
     /* [276] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [277] */
@@ -4457,12 +4493,12 @@
   {
     /* [280] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [281] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [282] */
@@ -4482,12 +4518,12 @@
   {
     /* [285] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [286] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [287] */
@@ -4507,12 +4543,12 @@
   {
     /* [290] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[235],
+    /* matcher indices */ &kMatcherIndices[237],
   },
   {
     /* [291] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [292] */
@@ -4582,7 +4618,7 @@
   {
     /* [305] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [306] */
@@ -4602,7 +4638,7 @@
   {
     /* [309] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [310] */
@@ -4612,12 +4648,12 @@
   {
     /* [311] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [312] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [313] */
@@ -4632,12 +4668,12 @@
   {
     /* [315] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [316] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [317] */
@@ -4652,12 +4688,12 @@
   {
     /* [319] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[235],
+    /* matcher indices */ &kMatcherIndices[237],
   },
   {
     /* [320] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [321] */
@@ -4672,12 +4708,12 @@
   {
     /* [323] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [324] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [325] */
@@ -4692,12 +4728,12 @@
   {
     /* [327] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[234],
+    /* matcher indices */ &kMatcherIndices[236],
   },
   {
     /* [328] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [329] */
@@ -4717,7 +4753,7 @@
   {
     /* [332] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [333] */
@@ -4737,7 +4773,7 @@
   {
     /* [336] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [337] */
@@ -4757,7 +4793,7 @@
   {
     /* [340] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [341] */
@@ -4777,7 +4813,7 @@
   {
     /* [344] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [345] */
@@ -4792,12 +4828,12 @@
   {
     /* [347] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [348] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [349] */
@@ -4812,12 +4848,12 @@
   {
     /* [351] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [352] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [353] */
@@ -4832,12 +4868,12 @@
   {
     /* [355] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[235],
+    /* matcher indices */ &kMatcherIndices[237],
   },
   {
     /* [356] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [357] */
@@ -4857,7 +4893,7 @@
   {
     /* [360] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [361] */
@@ -4877,7 +4913,7 @@
   {
     /* [364] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [365] */
@@ -4897,7 +4933,7 @@
   {
     /* [368] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [369] */
@@ -4912,12 +4948,12 @@
   {
     /* [371] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [372] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [373] */
@@ -4932,12 +4968,12 @@
   {
     /* [375] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[234],
+    /* matcher indices */ &kMatcherIndices[236],
   },
   {
     /* [376] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [377] */
@@ -4952,12 +4988,12 @@
   {
     /* [379] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [380] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [381] */
@@ -4972,12 +5008,12 @@
   {
     /* [383] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[234],
+    /* matcher indices */ &kMatcherIndices[236],
   },
   {
     /* [384] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[239],
+    /* matcher indices */ &kMatcherIndices[241],
   },
   {
     /* [385] */
@@ -4997,7 +5033,7 @@
   {
     /* [388] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [389] */
@@ -5017,7 +5053,7 @@
   {
     /* [392] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [393] */
@@ -5037,7 +5073,7 @@
   {
     /* [396] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [397] */
@@ -5052,12 +5088,12 @@
   {
     /* [399] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [400] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [401] */
@@ -5072,12 +5108,12 @@
   {
     /* [403] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[234],
+    /* matcher indices */ &kMatcherIndices[236],
   },
   {
     /* [404] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [405] */
@@ -5172,7 +5208,7 @@
   {
     /* [423] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [424] */
@@ -5532,12 +5568,12 @@
   {
     /* [495] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [496] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [497] */
@@ -5547,12 +5583,12 @@
   {
     /* [498] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[234],
+    /* matcher indices */ &kMatcherIndices[236],
   },
   {
     /* [499] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [500] */
@@ -5567,7 +5603,7 @@
   {
     /* [502] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [503] */
@@ -5582,7 +5618,7 @@
   {
     /* [505] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [506] */
@@ -5597,7 +5633,7 @@
   {
     /* [508] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [509] */
@@ -5612,7 +5648,7 @@
   {
     /* [511] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [512] */
@@ -5622,12 +5658,12 @@
   {
     /* [513] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [514] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [515] */
@@ -5637,12 +5673,12 @@
   {
     /* [516] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[234],
+    /* matcher indices */ &kMatcherIndices[236],
   },
   {
     /* [517] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [518] */
@@ -5657,7 +5693,7 @@
   {
     /* [520] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [521] */
@@ -5667,12 +5703,12 @@
   {
     /* [522] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[237],
+    /* matcher indices */ &kMatcherIndices[239],
   },
   {
     /* [523] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[238],
+    /* matcher indices */ &kMatcherIndices[240],
   },
   {
     /* [524] */
@@ -5877,7 +5913,7 @@
   {
     /* [564] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [565] */
@@ -5892,7 +5928,7 @@
   {
     /* [567] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[236],
+    /* matcher indices */ &kMatcherIndices[238],
   },
   {
     /* [568] */
@@ -6277,7 +6313,7 @@
   {
     /* [644] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [645] */
@@ -6287,7 +6323,7 @@
   {
     /* [646] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [647] */
@@ -6297,7 +6333,7 @@
   {
     /* [648] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[234],
+    /* matcher indices */ &kMatcherIndices[236],
   },
   {
     /* [649] */
@@ -6307,7 +6343,7 @@
   {
     /* [650] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[235],
+    /* matcher indices */ &kMatcherIndices[237],
   },
   {
     /* [651] */
@@ -6317,7 +6353,7 @@
   {
     /* [652] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[237],
+    /* matcher indices */ &kMatcherIndices[239],
   },
   {
     /* [653] */
@@ -7657,27 +7693,27 @@
   {
     /* [920] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [921] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [922] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[234],
+    /* matcher indices */ &kMatcherIndices[236],
   },
   {
     /* [923] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[235],
+    /* matcher indices */ &kMatcherIndices[237],
   },
   {
     /* [924] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[236],
+    /* matcher indices */ &kMatcherIndices[238],
   },
   {
     /* [925] */
@@ -7702,7 +7738,7 @@
   {
     /* [929] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[237],
+    /* matcher indices */ &kMatcherIndices[239],
   },
   {
     /* [930] */
@@ -7717,12 +7753,12 @@
   {
     /* [932] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [933] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[235],
+    /* matcher indices */ &kMatcherIndices[237],
   },
   {
     /* [934] */
@@ -7762,22 +7798,22 @@
   {
     /* [941] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[232],
+    /* matcher indices */ &kMatcherIndices[234],
   },
   {
     /* [942] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[233],
+    /* matcher indices */ &kMatcherIndices[235],
   },
   {
     /* [943] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[234],
+    /* matcher indices */ &kMatcherIndices[236],
   },
   {
     /* [944] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[235],
+    /* matcher indices */ &kMatcherIndices[237],
   },
   {
     /* [945] */
@@ -7787,7 +7823,7 @@
   {
     /* [946] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[236],
+    /* matcher indices */ &kMatcherIndices[238],
   },
   {
     /* [947] */
@@ -8119,78 +8155,83 @@
     /* usage */ ParameterUsage::kNone,
     /* matcher indices */ &kMatcherIndices[230],
   },
+  {
+    /* [1013] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[106],
+  },
 };
 
 constexpr TemplateTypeInfo kTemplateTypes[] = {
   {
     /* [0] */
     /* name */ "T",
-    /* matcher index */ 67,
+    /* matcher index */ 68,
   },
   {
     /* [1] */
     /* name */ "C",
-    /* matcher index */ 71,
+    /* matcher index */ 72,
   },
   {
     /* [2] */
     /* name */ "A",
-    /* matcher index */ 71,
+    /* matcher index */ 72,
   },
   {
     /* [3] */
     /* name */ "L",
-    /* matcher index */ 71,
+    /* matcher index */ 72,
   },
   {
     /* [4] */
     /* name */ "T",
-    /* matcher index */ 67,
+    /* matcher index */ 68,
   },
   {
     /* [5] */
     /* name */ "C",
-    /* matcher index */ 71,
+    /* matcher index */ 72,
   },
   {
     /* [6] */
     /* name */ "L",
-    /* matcher index */ 71,
+    /* matcher index */ 72,
   },
   {
     /* [7] */
     /* name */ "T",
-    /* matcher index */ 67,
+    /* matcher index */ 68,
   },
   {
     /* [8] */
     /* name */ "C",
-    /* matcher index */ 71,
+    /* matcher index */ 72,
   },
   {
     /* [9] */
     /* name */ "S",
-    /* matcher index */ 71,
+    /* matcher index */ 72,
   },
   {
     /* [10] */
     /* name */ "T",
-    /* matcher index */ 63,
+    /* matcher index */ 64,
   },
   {
     /* [11] */
     /* name */ "U",
-    /* matcher index */ 65,
+    /* matcher index */ 66,
   },
   {
     /* [12] */
     /* name */ "T",
-    /* matcher index */ 67,
+    /* matcher index */ 68,
   },
   {
     /* [13] */
     /* name */ "L",
-    /* matcher index */ 71,
+    /* matcher index */ 72,
   },
   {
     /* [14] */
@@ -8200,7 +8241,7 @@
   {
     /* [15] */
     /* name */ "U",
-    /* matcher index */ 54,
+    /* matcher index */ 55,
   },
   {
     /* [16] */
@@ -8210,7 +8251,7 @@
   {
     /* [17] */
     /* name */ "U",
-    /* matcher index */ 55,
+    /* matcher index */ 56,
   },
   {
     /* [18] */
@@ -8220,7 +8261,7 @@
   {
     /* [19] */
     /* name */ "U",
-    /* matcher index */ 56,
+    /* matcher index */ 57,
   },
   {
     /* [20] */
@@ -8230,7 +8271,7 @@
   {
     /* [21] */
     /* name */ "U",
-    /* matcher index */ 57,
+    /* matcher index */ 58,
   },
   {
     /* [22] */
@@ -8240,12 +8281,12 @@
   {
     /* [23] */
     /* name */ "U",
-    /* matcher index */ 58,
+    /* matcher index */ 59,
   },
   {
     /* [24] */
     /* name */ "T",
-    /* matcher index */ 59,
+    /* matcher index */ 60,
   },
   {
     /* [25] */
@@ -8255,62 +8296,62 @@
   {
     /* [26] */
     /* name */ "T",
-    /* matcher index */ 71,
+    /* matcher index */ 72,
   },
   {
     /* [27] */
     /* name */ "T",
-    /* matcher index */ 52,
+    /* matcher index */ 53,
   },
   {
     /* [28] */
     /* name */ "T",
-    /* matcher index */ 60,
+    /* matcher index */ 61,
   },
   {
     /* [29] */
     /* name */ "T",
-    /* matcher index */ 64,
+    /* matcher index */ 65,
   },
   {
     /* [30] */
     /* name */ "T",
-    /* matcher index */ 66,
+    /* matcher index */ 67,
   },
   {
     /* [31] */
     /* name */ "T",
-    /* matcher index */ 56,
+    /* matcher index */ 57,
   },
   {
     /* [32] */
     /* name */ "T",
-    /* matcher index */ 57,
+    /* matcher index */ 58,
   },
   {
     /* [33] */
     /* name */ "T",
-    /* matcher index */ 54,
+    /* matcher index */ 55,
   },
   {
     /* [34] */
     /* name */ "T",
-    /* matcher index */ 55,
+    /* matcher index */ 56,
   },
   {
     /* [35] */
     /* name */ "T",
-    /* matcher index */ 58,
+    /* matcher index */ 59,
   },
   {
     /* [36] */
     /* name */ "T",
-    /* matcher index */ 53,
+    /* matcher index */ 54,
   },
   {
     /* [37] */
     /* name */ "T",
-    /* matcher index */ 70,
+    /* matcher index */ 71,
   },
 };
 
@@ -8879,7 +8920,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[36],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[134],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -9515,7 +9556,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[36],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[106],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -9983,7 +10024,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[36],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[23],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -10499,7 +10540,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[37],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[178],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -10571,7 +10612,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[37],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[184],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -10643,7 +10684,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[37],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[190],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -10715,7 +10756,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[37],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[196],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -10787,7 +10828,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[37],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[202],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -10859,7 +10900,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[37],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[208],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -10931,7 +10972,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[37],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[214],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -11003,7 +11044,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[37],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[220],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -11075,7 +11116,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[37],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[226],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -11591,7 +11632,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[38],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[9],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -11627,7 +11668,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[38],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[105],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -11663,7 +11704,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[38],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[42],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -11699,7 +11740,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[38],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -11735,7 +11776,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[38],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ &kMatcherIndices[39],
     /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::Zero,
@@ -13751,7 +13792,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[38],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline),
     /* const eval */ nullptr,
@@ -13835,7 +13876,7 @@
     /* num template numbers */ 0,
     /* template types */ &kTemplateTypes[38],
     /* template numbers */ &kTemplateNumbers[10],
-    /* parameters */ &kParameters[1013],
+    /* parameters */ &kParameters[1014],
     /* return matcher indices */ nullptr,
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline),
     /* const eval */ nullptr,
@@ -14020,6 +14061,18 @@
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* const eval */ &ConstEval::OpLogicalOr,
   },
+  {
+    /* [471] */
+    /* num parameters */ 1,
+    /* num template types */ 1,
+    /* num template numbers */ 0,
+    /* template types */ &kTemplateTypes[36],
+    /* template numbers */ &kTemplateNumbers[10],
+    /* parameters */ &kParameters[1013],
+    /* return matcher indices */ &kMatcherIndices[232],
+    /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
+    /* const eval */ &ConstEval::Conv,
+  },
 };
 
 constexpr IntrinsicInfo kBuiltins[] = {
@@ -15284,6 +15337,12 @@
     /* num overloads */ 6,
     /* overloads */ &kOverloads[225],
   },
+  {
+    /* [17] */
+    /* conv packedVec3<T : concrete_scalar>(vec3<T>) -> packedVec3<T> */
+    /* num overloads */ 1,
+    /* overloads */ &kOverloads[471],
+  },
 };
 
 // clang-format on
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 76bb3dd..2d4950e 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -2045,6 +2045,10 @@
             [&](const type::F32*) { return ctor_or_conv(CtorConvIntrinsic::kF32, nullptr); },
             [&](const type::Bool*) { return ctor_or_conv(CtorConvIntrinsic::kBool, nullptr); },
             [&](const type::Vector* v) {
+                if (v->Packed()) {
+                    TINT_ASSERT(Resolver, v->Width() == 3u);
+                    return ctor_or_conv(CtorConvIntrinsic::kPackedVec3, v->type());
+                }
                 return ctor_or_conv(VectorCtorConvIntrinsic(v->Width()), v->type());
             },
             [&](const type::Matrix* m) {
@@ -2574,6 +2578,24 @@
         }
         return tex;
     };
+    auto packed_vec3_t = [&]() -> type::Vector* {
+        auto* tmpl_ident = templated_identifier(1);
+        if (TINT_UNLIKELY(!tmpl_ident)) {
+            return nullptr;
+        }
+        auto* el_ty = Type(tmpl_ident->arguments[0]);
+        if (TINT_UNLIKELY(!el_ty)) {
+            return nullptr;
+        }
+
+        if (TINT_UNLIKELY(!el_ty)) {
+            return nullptr;
+        }
+        if (TINT_UNLIKELY(!validator_.Vector(el_ty, ident->source))) {
+            return nullptr;
+        }
+        return b.create<type::Vector>(el_ty, 3u, true);
+    };
 
     switch (builtin_ty) {
         case builtin::Builtin::kBool:
@@ -2720,6 +2742,9 @@
             return storage_texture(type::TextureDimension::k2dArray);
         case builtin::Builtin::kTextureStorage3D:
             return storage_texture(type::TextureDimension::k3d);
+        case builtin::Builtin::kPackedVec3: {
+            return packed_vec3_t();
+        }
         case builtin::Builtin::kUndefined:
             break;
     }
diff --git a/src/tint/transform/packed_vec3.cc b/src/tint/transform/packed_vec3.cc
index 6337197..956adcb 100644
--- a/src/tint/transform/packed_vec3.cc
+++ b/src/tint/transform/packed_vec3.cc
@@ -18,16 +18,23 @@
 #include <string>
 #include <utility>
 
+#include "src/tint/ast/assignment_statement.h"
+#include "src/tint/builtin/builtin.h"
 #include "src/tint/program_builder.h"
+#include "src/tint/sem/array_count.h"
 #include "src/tint/sem/index_accessor_expression.h"
-#include "src/tint/sem/member_accessor_expression.h"
+#include "src/tint/sem/load.h"
 #include "src/tint/sem/statement.h"
+#include "src/tint/sem/type_expression.h"
 #include "src/tint/sem/variable.h"
+#include "src/tint/type/array.h"
+#include "src/tint/type/reference.h"
+#include "src/tint/type/vector.h"
 #include "src/tint/utils/hashmap.h"
 #include "src/tint/utils/hashset.h"
+#include "src/tint/utils/vector.h"
 
 TINT_INSTANTIATE_TYPEINFO(tint::transform::PackedVec3);
-TINT_INSTANTIATE_TYPEINFO(tint::transform::PackedVec3::Attribute);
 
 using namespace tint::number_suffixes;  // NOLINT
 
@@ -39,105 +46,447 @@
     /// @param program the source program
     explicit State(const Program* program) : src(program) {}
 
+    /// The name of the struct member used when wrapping packed vec3 types.
+    static constexpr const char* kStructMemberName = "elements";
+
+    /// The names of the structures used to wrap packed vec3 types.
+    utils::Hashmap<const type::Type*, Symbol, 4> packed_vec3_wrapper_struct_names;
+
+    /// A cache of host-shareable structures that have been rewritten.
+    utils::Hashmap<const type::Type*, Symbol, 4> rewritten_structs;
+
+    /// A map from type to the name of a helper function used to pack that type.
+    utils::Hashmap<const type::Type*, Symbol, 4> pack_helpers;
+
+    /// A map from type to the name of a helper function used to unpack that type.
+    utils::Hashmap<const type::Type*, Symbol, 4> unpack_helpers;
+
+    /// @param ty the type to test
+    /// @returns true if `ty` is a vec3, false otherwise
+    bool IsVec3(const type::Type* ty) {
+        if (auto* vec = ty->As<type::Vector>()) {
+            if (vec->Width() == 3) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /// @param ty the type to test
+    /// @returns true if `ty` is or contains a vec3, false otherwise
+    bool ContainsVec3(const type::Type* ty) {
+        return Switch(
+            ty,  //
+            [&](const type::Vector* vec) { return IsVec3(vec); },
+            [&](const type::Matrix* mat) { return ContainsVec3(mat->ColumnType()); },
+            [&](const type::Array* arr) { return ContainsVec3(arr->ElemType()); },
+            [&](const type::Struct* str) {
+                for (auto* member : str->Members()) {
+                    if (ContainsVec3(member->Type())) {
+                        return true;
+                    }
+                }
+                return false;
+            });
+    }
+
+    /// Create a `__packed_vec3` type with the same element type as `ty`.
+    /// @param ty a three-element vector type
+    /// @returns the new AST type
+    ast::Type MakePackedVec3(const type::Type* ty) {
+        auto* vec = ty->As<type::Vector>();
+        TINT_ASSERT(Transform, vec != nullptr && vec->Width() == 3);
+        return b.ty(builtin::Builtin::kPackedVec3, CreateASTTypeFor(ctx, vec->type()));
+    }
+
+    /// Recursively rewrite a type using `__packed_vec3`, if needed.
+    /// When used as an array element type, the `__packed_vec3` type will be wrapped in a structure
+    /// and given an `@align()` attribute to give it alignment it needs to yield the correct array
+    /// element stride. For vec3 types used in structures directly, the `@align()` attribute is
+    /// placed on the containing structure instead. Matrices with three rows become arrays of
+    /// columns, and used the aligned wrapper struct for the column type.
+    /// @param ty the type to rewrite
+    /// @param array_element `true` if this is being called for the element of an array
+    /// @returns the new AST type, or nullptr if rewriting was not necessary
+    ast::Type RewriteType(const type::Type* ty, bool array_element = false) {
+        return Switch(
+            ty,
+            [&](const type::Vector* vec) -> ast::Type {
+                if (IsVec3(vec)) {
+                    if (array_element) {
+                        // Create a struct with a single `__packed_vec3` member.
+                        // Give the struct member the same alignment as the original unpacked vec3
+                        // type, to avoid changing the array element stride.
+                        return b.ty(packed_vec3_wrapper_struct_names.GetOrCreate(vec, [&]() {
+                            auto name = b.Symbols().New(
+                                "tint_packed_vec3_" + vec->type()->FriendlyName(src->Symbols()) +
+                                (array_element ? "_array_element" : "_struct_member"));
+                            auto* member =
+                                b.Member(kStructMemberName, MakePackedVec3(vec),
+                                         utils::Vector{b.MemberAlign(AInt(vec->Align()))});
+                            b.Structure(b.Ident(name), utils::Vector{member}, utils::Empty);
+                            return name;
+                        }));
+                    } else {
+                        return MakePackedVec3(vec);
+                    }
+                }
+                return {};
+            },
+            [&](const type::Matrix* mat) -> ast::Type {
+                // Rewrite the matrix as an array of columns that use the aligned wrapper struct.
+                auto new_col_type = RewriteType(mat->ColumnType(), /* array_element */ true);
+                if (new_col_type) {
+                    return b.ty.array(new_col_type, u32(mat->columns()));
+                }
+                return {};
+            },
+            [&](const type::Array* arr) -> ast::Type {
+                // Rewrite the array with the modified element type.
+                auto new_type = RewriteType(arr->ElemType(), /* array_element */ true);
+                if (new_type) {
+                    utils::Vector<const ast::Attribute*, 1> attrs;
+                    if (arr->Count()->Is<type::RuntimeArrayCount>()) {
+                        return b.ty.array(new_type, std::move(attrs));
+                    } else if (auto count = arr->ConstantCount()) {
+                        return b.ty.array(new_type, u32(count.value()), std::move(attrs));
+                    } else {
+                        TINT_ICE(Transform, b.Diagnostics())
+                            << type::Array::kErrExpectedConstantCount;
+                        return {};
+                    }
+                }
+                return {};
+            },
+            [&](const sem::Struct* str) -> ast::Type {
+                if (ContainsVec3(str)) {
+                    auto name = rewritten_structs.GetOrCreate(str, [&]() {
+                        utils::Vector<const ast::StructMember*, 4> members;
+                        for (auto* member : str->Members()) {
+                            // If the member type contains a vec3, rewrite it.
+                            auto new_type = RewriteType(member->Type());
+                            if (new_type) {
+                                // Copy the member attributes.
+                                bool needs_align = true;
+                                utils::Vector<const ast::Attribute*, 4> attributes;
+                                for (auto* attr : member->Declaration()->attributes) {
+                                    if (attr->IsAnyOf<ast::StructMemberAlignAttribute,
+                                                      ast::StructMemberOffsetAttribute>()) {
+                                        needs_align = false;
+                                    }
+                                    attributes.Push(ctx.Clone(attr));
+                                }
+                                // If the alignment wasn't already specified, add an attribute to
+                                // make sure that we don't alter the alignment when using the packed
+                                // vector type.
+                                if (needs_align) {
+                                    attributes.Push(b.MemberAlign(AInt(member->Align())));
+                                }
+                                members.Push(b.Member(ctx.Clone(member->Name()), new_type,
+                                                      std::move(attributes)));
+                            } else {
+                                // No vec3s, just clone the member as is.
+                                members.Push(ctx.Clone(member->Declaration()));
+                            }
+                        }
+                        // Create the new structure.
+                        auto struct_name = b.Symbols().New(
+                            src->Symbols().NameFor(str->Declaration()->name->symbol) +
+                            "_tint_packed_vec3");
+                        b.Structure(struct_name, std::move(members));
+                        return struct_name;
+                    });
+                    return b.ty(name);
+                }
+                return {};
+            });
+    }
+
+    /// Create a helper function to recursively pack or unpack a composite that contains vec3 types.
+    /// @param name_prefix the name of the helper function
+    /// @param ty the composite type to pack or unpack
+    /// @param pack_or_unpack_element a function that packs or unpacks an element with a given type
+    /// @param in_type a function that create an AST type for the input type
+    /// @param out_type a function that create an AST type for the output type
+    /// @returns the name of the helper function
+    Symbol MakePackUnpackHelper(
+        const char* name_prefix,
+        const type::Type* ty,
+        const std::function<const ast::Expression*(const ast::Expression*, const type::Type*)>&
+            pack_or_unpack_element,
+        const std::function<ast::Type()>& in_type,
+        const std::function<ast::Type()>& out_type) {
+        // Allocate a variable to hold the return value of the function.
+        utils::Vector<const ast::Statement*, 4> statements;
+        statements.Push(b.Decl(b.Var("result", out_type())));
+
+        // Helper that generates a loop to copy and pack/unpack elements of an array to the result:
+        //   for (var i = 0u; i < num_elements; i = i + 1) {
+        //     result[i] = pack_or_unpack_element(in[i]);
+        //   }
+        auto copy_array_elements = [&](uint32_t num_elements, const type::Type* element_type) {
+            // Generate an expression for packing or unpacking an element of the array.
+            auto* element = pack_or_unpack_element(b.IndexAccessor("in", "i"), element_type);
+            statements.Push(b.For(                   //
+                b.Decl(b.Var("i", b.ty.u32())),      //
+                b.LessThan("i", u32(num_elements)),  //
+                b.Assign("i", b.Add("i", 1_a)),      //
+                b.Block(utils::Vector{
+                    b.Assign(b.IndexAccessor("result", "i"), element),
+                })));
+        };
+
+        // Copy the elements of the value over to the result.
+        Switch(
+            ty,
+            [&](const type::Array* arr) {
+                TINT_ASSERT(Transform, arr->ConstantCount());
+                copy_array_elements(arr->ConstantCount().value(), arr->ElemType());
+            },
+            [&](const type::Matrix* mat) {
+                copy_array_elements(mat->columns(), mat->ColumnType());
+            },
+            [&](const sem::Struct* str) {
+                // Copy the struct members over one at a time, packing/unpacking as necessary.
+                for (auto* member : str->Members()) {
+                    const ast::Expression* element =
+                        b.MemberAccessor("in", b.Ident(ctx.Clone(member->Name())));
+                    if (ContainsVec3(member->Type())) {
+                        element = pack_or_unpack_element(element, member->Type());
+                    }
+                    statements.Push(b.Assign(
+                        b.MemberAccessor("result", b.Ident(ctx.Clone(member->Name()))), element));
+                }
+            });
+
+        // Return the result.
+        statements.Push(b.Return("result"));
+
+        // Create the function and return its name.
+        auto name = b.Symbols().New(name_prefix);
+        b.Func(name, utils::Vector{b.Param("in", in_type())}, out_type(), std::move(statements));
+        return name;
+    }
+
+    /// Unpack the composite value `expr` to the unpacked type `ty`. If `ty` is a matrix, this will
+    /// produce a regular matNx3 value from an array of packed column vectors.
+    /// @param expr the composite value expression to unpack
+    /// @param ty the unpacked type
+    /// @returns an expression that holds the unpacked value
+    const ast::Expression* UnpackComposite(const ast::Expression* expr, const type::Type* ty) {
+        auto helper = unpack_helpers.GetOrCreate(ty, [&]() {
+            return MakePackUnpackHelper(
+                "tint_unpack_vec3_in_composite", ty,
+                [&](const ast::Expression* element,
+                    const type::Type* element_type) -> const ast::Expression* {
+                    if (element_type->Is<type::Vector>()) {
+                        // Unpack a `__packed_vec3` by casting it to a regular vec3.
+                        // If it is an array element, extract the vector from the wrapper struct.
+                        if (element->Is<ast::IndexAccessorExpression>()) {
+                            element = b.MemberAccessor(element, kStructMemberName);
+                        }
+                        return b.Call(CreateASTTypeFor(ctx, element_type), element);
+                    } else {
+                        return UnpackComposite(element, element_type);
+                    }
+                },
+                [&]() { return RewriteType(ty); },  //
+                [&]() { return CreateASTTypeFor(ctx, ty); });
+        });
+        return b.Call(helper, expr);
+    }
+
+    /// Pack the composite value `expr` from the unpacked type `ty`. If `ty` is a matrix, this will
+    /// produce an array of packed column vectors.
+    /// @param expr the composite value expression to pack
+    /// @param ty the unpacked type
+    /// @returns an expression that holds the packed value
+    const ast::Expression* PackComposite(const ast::Expression* expr, const type::Type* ty) {
+        auto helper = pack_helpers.GetOrCreate(ty, [&]() {
+            return MakePackUnpackHelper(
+                "tint_pack_vec3_in_composite", ty,
+                [&](const ast::Expression* element,
+                    const type::Type* element_type) -> const ast::Expression* {
+                    if (element_type->Is<type::Vector>()) {
+                        // Pack a vector element by casting it to a packed_vec3.
+                        // If it is an array element, construct a wrapper struct.
+                        auto* packed = b.Call(MakePackedVec3(element_type), element);
+                        if (element->Is<ast::IndexAccessorExpression>()) {
+                            packed = b.Call(RewriteType(element_type, true), packed);
+                        }
+                        return packed;
+                    } else {
+                        return PackComposite(element, element_type);
+                    }
+                },
+                [&]() { return CreateASTTypeFor(ctx, ty); },  //
+                [&]() { return RewriteType(ty); });
+        });
+        return b.Call(helper, expr);
+    }
+
+    /// @returns true if there are host-shareable vec3's that need transforming
+    bool ShouldRun() {
+        // Check for vec3s in the types of all uniform and storage buffer variables to determine
+        // if the transform is necessary.
+        for (auto* decl : src->AST().GlobalVariables()) {
+            auto* var = sem.Get<sem::GlobalVariable>(decl);
+            if (var && builtin::IsHostShareable(var->AddressSpace()) &&
+                ContainsVec3(var->Type()->UnwrapRef())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /// Runs the transform
     /// @returns the new program or SkipTransform if the transform is not required
     ApplyResult Run() {
-        // Packed vec3<T> struct members
-        utils::Hashset<const sem::StructMember*, 8> members;
-
-        // Find all the packed vector struct members, and apply the @internal(packed_vector)
-        // attribute.
-        for (auto* decl : ctx.src->AST().GlobalDeclarations()) {
-            if (auto* str = sem.Get<sem::Struct>(decl)) {
-                if (str->IsHostShareable()) {
-                    for (auto* member : str->Members()) {
-                        if (auto* vec = member->Type()->As<type::Vector>()) {
-                            if (vec->Width() == 3) {
-                                members.Add(member);
-
-                                // Apply the PackedVec3::Attribute to the member
-                                ctx.InsertFront(
-                                    member->Declaration()->attributes,
-                                    b.ASTNodes().Create<Attribute>(b.ID(), b.AllocateNodeID()));
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        if (members.IsEmpty()) {
+        if (!ShouldRun()) {
             return SkipTransform;
         }
 
-        // Walk the nodes, starting with the most deeply nested, finding all the AST expressions
-        // that load a whole packed vector (not a scalar / swizzle of the vector).
-        utils::Hashset<const sem::ValueExpression*, 16> refs;
+        // Changing the types of certain structure members can trigger stricter layout validation
+        // rules for the uniform address space. In particular, replacing 16-bit matrices with arrays
+        // violates the requirement that the array element stride is a multiple of 16 bytes, and
+        // replacing vec3s with a structure violates the requirement that there must be at least 16
+        // bytes from the start of a structure to the start of the next member.
+        // Disable these validation rules using an internal extension, as MSL does not have these
+        // restrictions.
+        b.Enable(builtin::Extension::kChromiumInternalRelaxedUniformLayout);
+
+        // Track expressions that need to be packed or unpacked.
+        utils::Hashset<const sem::ValueExpression*, 8> to_pack;
+        utils::Hashset<const sem::ValueExpression*, 8> to_unpack;
+
+        // Replace vec3 types in host-shareable address spaces with `__packed_vec3` types, and
+        // collect expressions that need to be converted to or from values that use the
+        // `__packed_vec3` type.
         for (auto* node : ctx.src->ASTNodes().Objects()) {
-            auto* sem_node = sem.Get(node);
-            if (sem_node) {
-                if (auto* expr = sem_node->As<sem::ValueExpression>()) {
-                    sem_node = expr->UnwrapLoad();
-                }
-            }
             Switch(
-                sem_node,  //
-                [&](const sem::StructMemberAccess* access) {
-                    if (members.Contains(access->Member())) {
-                        // Access to a packed vector member. Seed the expression tracking.
-                        refs.Add(access);
-                    }
-                },
-                [&](const sem::IndexAccessorExpression* access) {
-                    // Not loading a whole packed vector. Ignore.
-                    refs.Remove(access->Object()->UnwrapLoad());
-                },
-                [&](const sem::Swizzle* access) {
-                    // Not loading a whole packed vector. Ignore.
-                    refs.Remove(access->Object()->UnwrapLoad());
-                },
-                [&](const sem::VariableUser* user) {
-                    auto* v = user->Variable();
-                    if (v->Declaration()->Is<ast::Let>() &&  // if variable is let...
-                        v->Type()->Is<type::Pointer>() &&    // and let is a pointer...
-                        refs.Contains(v->Initializer())) {   // and pointer is to a packed vector...
-                        refs.Add(user);  // then propagate tracking to pointer usage
-                    }
-                },
-                [&](const sem::ValueExpression* expr) {
-                    if (auto* unary = expr->Declaration()->As<ast::UnaryOpExpression>()) {
-                        if (unary->op == ast::UnaryOp::kAddressOf ||
-                            unary->op == ast::UnaryOp::kIndirection) {
-                            // Memory access on the packed vector. Track these.
-                            auto* inner = sem.GetVal(unary->expr);
-                            if (refs.Remove(inner)) {
-                                refs.Add(expr);
-                            }
+                sem.Get(node),
+                [&](const sem::TypeExpression* type) {
+                    // Rewrite pointers to types that contain vec3s.
+                    auto* ptr = type->Type()->As<type::Pointer>();
+                    if (ptr && builtin::IsHostShareable(ptr->AddressSpace())) {
+                        auto new_store_type = RewriteType(ptr->StoreType());
+                        if (new_store_type) {
+                            auto access = ptr->AddressSpace() == builtin::AddressSpace::kStorage
+                                              ? ptr->Access()
+                                              : builtin::Access::kUndefined;
+                            auto new_ptr_type =
+                                b.ty.pointer(new_store_type, ptr->AddressSpace(), access);
+                            ctx.Replace(node, new_ptr_type.expr);
                         }
-                        // Note: non-memory ops (e.g. '-') are ignored, leaving any tracked
-                        // reference at the inner expression, so we'd cast, then apply the unary op.
                     }
                 },
-                [&](const sem::Statement* e) {
-                    if (auto* assign = e->Declaration()->As<ast::AssignmentStatement>()) {
-                        // We don't want to cast packed_vectors if they're being assigned to.
-                        refs.Remove(sem.GetVal(assign->lhs));
+                [&](const sem::Variable* var) {
+                    if (!builtin::IsHostShareable(var->AddressSpace())) {
+                        return;
+                    }
+
+                    // Rewrite the var type, if it contains vec3s.
+                    auto new_store_type = RewriteType(var->Type()->UnwrapRef());
+                    if (new_store_type) {
+                        ctx.Replace(var->Declaration()->type.expr, new_store_type.expr);
+                    }
+                },
+                [&](const sem::Statement* stmt) {
+                    // Pack the RHS of assignment statements that are writing to packed types.
+                    if (auto* assign = stmt->Declaration()->As<ast::AssignmentStatement>()) {
+                        auto* lhs = sem.GetVal(assign->lhs);
+                        auto* rhs = sem.GetVal(assign->rhs);
+                        if (!ContainsVec3(rhs->Type()) ||
+                            !builtin::IsHostShareable(
+                                lhs->Type()->As<type::Reference>()->AddressSpace())) {
+                            // Skip assignments to address spaces that are not host-shareable, or
+                            // that do not contain vec3 types.
+                            return;
+                        }
+
+                        // Pack the RHS expression.
+                        if (to_unpack.Contains(rhs)) {
+                            // The expression will already be packed, so skip the pending unpack.
+                            to_unpack.Remove(rhs);
+
+                            // If the expression produces a vec3 from an array element, extract
+                            // the packed vector from the wrapper struct.
+                            if (IsVec3(rhs->Type()) &&
+                                rhs->UnwrapLoad()->Is<sem::IndexAccessorExpression>()) {
+                                ctx.Replace(rhs->Declaration(),
+                                            b.MemberAccessor(ctx.Clone(rhs->Declaration()),
+                                                             kStructMemberName));
+                            }
+                        } else if (rhs) {
+                            to_pack.Add(rhs);
+                        }
+                    }
+                },
+                [&](const sem::Load* load) {
+                    // Unpack loads of types that contain vec3s in host-shareable address spaces.
+                    if (ContainsVec3(load->Type()) &&
+                        builtin::IsHostShareable(load->ReferenceType()->AddressSpace())) {
+                        to_unpack.Add(load);
+                    }
+                },
+                [&](const sem::IndexAccessorExpression* accessor) {
+                    // If the expression produces a reference to a vec3 in a host-shareable address
+                    // space from an array element, extract the packed vector from the wrapper
+                    // struct.
+                    if (auto* ref = accessor->Type()->As<type::Reference>()) {
+                        if (IsVec3(ref->StoreType()) &&
+                            builtin::IsHostShareable(ref->AddressSpace())) {
+                            ctx.Replace(node, b.MemberAccessor(ctx.Clone(accessor->Declaration()),
+                                                               kStructMemberName));
+                        }
                     }
                 });
         }
 
-        // Wrap the load expressions with a cast to the unpacked type.
-        utils::Hashmap<const type::Vector*, Symbol, 3> unpack_fns;
-        for (auto* ref : refs) {
-            // ref is either a packed vec3 that needs casting, or a pointer to a vec3 which we just
-            // leave alone.
-            if (auto* vec_ty = ref->Type()->UnwrapRef()->As<type::Vector>()) {
-                auto* expr = ref->Declaration();
-                ctx.Replace(expr, [this, vec_ty, expr] {  //
-                    auto* packed = ctx.CloneWithoutTransform(expr);
-                    return b.Call(CreateASTTypeFor(ctx, vec_ty), packed);
-                });
+        // Sort the pending pack/unpack operations by AST node ID to make the order deterministic.
+        auto to_unpack_sorted = to_unpack.Vector();
+        auto to_pack_sorted = to_pack.Vector();
+        auto pred = [&](auto* expr_a, auto* expr_b) {
+            return expr_a->Declaration()->node_id < expr_b->Declaration()->node_id;
+        };
+        to_unpack_sorted.Sort(pred);
+        to_pack_sorted.Sort(pred);
+
+        // Apply all of the pending unpack operations that we have collected.
+        for (auto* expr : to_unpack_sorted) {
+            TINT_ASSERT(Transform, ContainsVec3(expr->Type()));
+            auto* packed = ctx.Clone(expr->Declaration());
+            const ast::Expression* unpacked = nullptr;
+            if (IsVec3(expr->Type())) {
+                if (expr->UnwrapLoad()->Is<sem::IndexAccessorExpression>()) {
+                    // If we are unpacking a vec3 from an array element, extract the vector from the
+                    // wrapper struct.
+                    packed = b.MemberAccessor(packed, kStructMemberName);
+                }
+                // Cast the packed vector to a regular vec3.
+                unpacked = b.Call(CreateASTTypeFor(ctx, expr->Type()), packed);
+            } else {
+                // Use a helper function to unpack an array or matrix.
+                unpacked = UnpackComposite(packed, expr->Type());
             }
+            TINT_ASSERT(Transform, unpacked != nullptr);
+            ctx.Replace(expr->Declaration(), unpacked);
+        }
+
+        // Apply all of the pending pack operations that we have collected.
+        for (auto* expr : to_pack_sorted) {
+            TINT_ASSERT(Transform, ContainsVec3(expr->Type()));
+            auto* unpacked = ctx.Clone(expr->Declaration());
+            const ast::Expression* packed = nullptr;
+            if (IsVec3(expr->Type())) {
+                // Cast the regular vec3 to a packed vector type.
+                packed = b.Call(MakePackedVec3(expr->Type()), unpacked);
+            } else {
+                // Use a helper function to pack an array or matrix.
+                packed = PackComposite(unpacked, expr->Type());
+            }
+            TINT_ASSERT(Transform, packed != nullptr);
+            ctx.Replace(expr->Declaration(), packed);
         }
 
         ctx.Clone();
@@ -153,21 +502,8 @@
     CloneContext ctx = {&b, src, /* auto_clone_symbols */ true};
     /// Alias to the semantic info in ctx.src
     const sem::Info& sem = ctx.src->Sem();
-    /// Alias to the symbols in ctx.src
-    const SymbolTable& sym = ctx.src->Symbols();
 };
 
-PackedVec3::Attribute::Attribute(ProgramID pid, ast::NodeID nid) : Base(pid, nid) {}
-PackedVec3::Attribute::~Attribute() = default;
-
-const PackedVec3::Attribute* PackedVec3::Attribute::Clone(CloneContext* ctx) const {
-    return ctx->dst->ASTNodes().Create<Attribute>(ctx->dst->ID(), ctx->dst->AllocateNodeID());
-}
-
-std::string PackedVec3::Attribute::InternalName() const {
-    return "packed_vector";
-}
-
 PackedVec3::PackedVec3() = default;
 PackedVec3::~PackedVec3() = default;
 
diff --git a/src/tint/transform/packed_vec3.h b/src/tint/transform/packed_vec3.h
index 0d304fa..89e8286 100644
--- a/src/tint/transform/packed_vec3.h
+++ b/src/tint/transform/packed_vec3.h
@@ -15,42 +15,31 @@
 #ifndef SRC_TINT_TRANSFORM_PACKED_VEC3_H_
 #define SRC_TINT_TRANSFORM_PACKED_VEC3_H_
 
-#include <string>
-
-#include "src/tint/ast/internal_attribute.h"
 #include "src/tint/transform/transform.h"
 
 namespace tint::transform {
 
 /// A transform to be used by the MSL backend which will:
-/// * Apply the `@internal('packed_vector')` attribute (PackedVec3::Attribute) to all host-sharable
-///   structure members that have a vec3<T> type.
+/// * Replace `vec3<T>` types with an internal `__packed_vec3` type when they are used in
+///   host-shareable address spaces.
+/// * Wrap generated `__packed_vec3` types in a structure when they are used in arrays, so that we
+///   ensure that the array has the correct element stride.
+/// * Multi-version structures that contain `vec3<T>` types when they are used in host-shareable
+///   memory, to avoid modifying uses in other address spaces.
+/// * Rewrite matrix types that have three rows into arrays of column vectors.
+/// * Insert calls to helper functions to convert expressions that use these types to or from the
+///   regular vec3 types when accessing host-shareable memory.
 /// * Cast all direct (not sub-accessed) loads of these packed vectors to the 'unpacked' vec3<T>
 ///   type before usage.
 ///
-/// This transform papers over overload holes in the MSL standard library where an MSL
-/// `packed_vector` type cannot be interchangable used as a regular `vec` type.
+/// This transform is necessary in order to emit vec3 types with the correct size (so that scalars
+/// can follow them in structures), and also to ensure that padding bytes are preserved when writing
+/// to a vec3, an array of vec3 elements, or a matrix with vec3 column type.
+///
+/// @note Depends on the following transforms to have been run first:
+/// * ExpandCompoundAssignment
 class PackedVec3 final : public Castable<PackedVec3, Transform> {
   public:
-    /// Attribute is the attribute applied to padded vector structure members.
-    class Attribute final : public Castable<Attribute, ast::InternalAttribute> {
-      public:
-        /// Constructor
-        /// @param pid the identifier of the program that owns this node
-        /// @param nid the unique node identifier
-        Attribute(ProgramID pid, ast::NodeID nid);
-        /// Destructor
-        ~Attribute() override;
-
-        /// @returns "packed_vector".
-        std::string InternalName() const override;
-
-        /// Performs a deep clone of this object using the CloneContext `ctx`.
-        /// @param ctx the clone context
-        /// @return the newly cloned object
-        const Attribute* Clone(CloneContext* ctx) const override;
-    };
-
     /// Constructor
     PackedVec3();
     /// Destructor
diff --git a/src/tint/transform/packed_vec3_test.cc b/src/tint/transform/packed_vec3_test.cc
index 0f5c92e..670bc05 100644
--- a/src/tint/transform/packed_vec3_test.cc
+++ b/src/tint/transform/packed_vec3_test.cc
@@ -18,7 +18,12 @@
 #include <utility>
 #include <vector>
 
+#include "src/tint/ast/module.h"
+#include "src/tint/program_builder.h"
+#include "src/tint/sem/struct.h"
+#include "src/tint/sem/variable.h"
 #include "src/tint/transform/test_helper.h"
+#include "src/tint/type/array.h"
 #include "src/tint/utils/string.h"
 
 namespace tint::transform {
@@ -32,14 +37,29 @@
     EXPECT_FALSE(ShouldRun<PackedVec3>(src));
 }
 
-TEST_F(PackedVec3Test, ShouldRun_NonHostSharableStruct) {
+TEST_F(PackedVec3Test, ShouldRun_NoHostShareableVec3s) {
     auto* src = R"(
 struct S {
   v : vec3<f32>,
+  m : mat3x3<f32>,
+  a : array<vec3<f32>, 4>,
 }
 
+var<private> p_s : S;
+var<private> p_v : vec3<f32>;
+var<private> p_m : mat3x3<f32>;
+var<private> p_a : array<vec3<f32>, 4>;
+
+var<workgroup> w_s : S;
+var<workgroup> w_v : vec3<f32>;
+var<workgroup> w_m : mat3x3<f32>;
+var<workgroup> w_a : array<vec3<f32>, 4>;
+
 fn f() {
-  var v : S; // function address-space - not host sharable
+  var f_s : S;
+  var f_v : vec3<f32>;
+  var f_m : mat3x3<f32>;
+  var f_a : array<vec3<f32>, 4>;
 }
 )";
 
@@ -53,13 +73,85 @@
   v2 : vec2<f32>,
 }
 
-@group(0) @binding(0) var<uniform> P : S; // Host sharable
+@group(0) @binding(0) var<uniform> Ps : S; // Host sharable
+@group(0) @binding(1) var<uniform> Pv4 : vec4<f32>; // Host sharable
+@group(0) @binding(2) var<uniform> Pv2 : vec2<f32>; // Host sharable
 )";
 
     EXPECT_FALSE(ShouldRun<PackedVec3>(src));
 }
 
-TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct) {
+TEST_F(PackedVec3Test, ShouldRun_OtherMatrices) {
+    auto* src = R"(
+struct S {
+  m2x2 : mat2x2<f32>,
+  m2x4 : mat2x4<f32>,
+  m3x2 : mat3x2<f32>,
+  m3x4 : mat3x4<f32>,
+  m4x2 : mat4x2<f32>,
+  m4x4 : mat4x4<f32>,
+}
+
+@group(0) @binding(0) var<uniform> Ps : S; // Host sharable
+@group(0) @binding(1) var<uniform> Pm2x2 : mat2x2<f32>; // Host sharable
+@group(0) @binding(2) var<uniform> Pm2x4 : mat2x4<f32>; // Host sharable
+@group(0) @binding(3) var<uniform> Pm3x2 : mat3x2<f32>; // Host sharable
+@group(0) @binding(4) var<uniform> Pm3x4 : mat3x4<f32>; // Host sharable
+@group(0) @binding(5) var<uniform> Pm4x2 : mat4x2<f32>; // Host sharable
+@group(0) @binding(6) var<uniform> Pm4x4 : mat4x4<f32>; // Host sharable
+)";
+
+    EXPECT_FALSE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_ArrayOfNonVec3) {
+    auto* src = R"(
+struct S {
+  arr_v : array<vec2<f32>, 4>,
+  arr_m : array<mat3x2<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> Ps : S; // Host sharable
+@group(0) @binding(1) var<storage> Parr_v : array<vec2<f32>, 4>; // Host sharable
+@group(0) @binding(2) var<storage> Parr_m : array<mat3x2<f32>, 4>; // Host sharable
+)";
+
+    EXPECT_FALSE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_HostSharable_Vec3) {
+    auto* src = R"(
+@group(0) @binding(0) var<uniform> P : vec3<f32>; // Host sharable
+)";
+
+    EXPECT_TRUE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_HostSharable_Mat3x3) {
+    auto* src = R"(
+@group(0) @binding(0) var<uniform> P : mat3x3<f32>; // Host sharable
+)";
+
+    EXPECT_TRUE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_HostSharable_ArrayOfVec3) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> P : array<vec3<f32>>; // Host sharable
+)";
+
+    EXPECT_TRUE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_HostSharable_ArrayOfMat3x3) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> P : array<mat3x3<f32>>; // Host sharable
+)";
+
+    EXPECT_TRUE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_Vec3) {
     auto* src = R"(
 struct S {
   v : vec3<f32>,
@@ -71,61 +163,3929 @@
     EXPECT_TRUE(ShouldRun<PackedVec3>(src));
 }
 
-TEST_F(PackedVec3Test, UniformAddressSpace) {
+TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_Mat3x3) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<uniform> P : S; // Host sharable
+)";
+
+    EXPECT_TRUE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_ArrayOfVec3) {
+    auto* src = R"(
+struct S {
+  a : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<uniform> P : S; // Host sharable
+)";
+
+    EXPECT_TRUE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_ArrayOfMat3x3) {
+    auto* src = R"(
+struct S {
+  a : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<uniform> P : S; // Host sharable
+)";
+
+    EXPECT_TRUE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, Vec3_ReadVector) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> v : vec3<f32>;
+
+fn f() {
+  let x = v;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
+
+fn f() {
+  let x = vec3<f32>(v);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Vec3_ReadComponent_MemberAccessChain) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> v : vec3<f32>;
+
+fn f() {
+  let x = v.yz.x;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
+
+fn f() {
+  let x = vec3<f32>(v).yz.x;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Vec3_ReadComponent_IndexAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> v : vec3<f32>;
+
+fn f() {
+  let x = v[1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
+
+fn f() {
+  let x = v[1];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Vec3_WriteVector_ValueRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
+
+fn f() {
+  v = vec3(1.23);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
+
+fn f() {
+  v = __packed_vec3<f32>(vec3(1.23));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Vec3_WriteVector_RefRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
+@group(0) @binding(1) var<uniform> in : vec3<f32>;
+
+fn f() {
+  v = in;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
+
+@group(0) @binding(1) var<uniform> in : __packed_vec3<f32>;
+
+fn f() {
+  v = in;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Vec3_WriteComponent_MemberAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
+
+fn f() {
+  v.y = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
+
+fn f() {
+  v.y = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Vec3_WriteComponent_IndexAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
+
+fn f() {
+  v[1] = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
+
+fn f() {
+  v[1] = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_ReadArray) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
+
+fn f() {
+  let x = arr;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite(arr);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_ReadVector) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
+
+fn f() {
+  let x = arr[0];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+fn f() {
+  let x = vec3<f32>(arr[0].elements);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_ReadComponent_MemberAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
+
+fn f() {
+  let x = arr[0].y;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+fn f() {
+  let x = arr[0].elements.y;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_ReadComponent_IndexAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
+
+fn f() {
+  let x = arr[0][1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+fn f() {
+  let x = arr[0].elements[1];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_WriteArray_ValueRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 2>;
+
+fn f() {
+  arr = array(vec3(1.5, 2.5, 3.5), vec3(4.5, 5.5, 6.5));
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 2u>) -> array<tint_packed_vec3_f32_array_element, 2u> {
+  var result : array<tint_packed_vec3_f32_array_element, 2u>;
+  for(var i : u32; (i < 2u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 2u>;
+
+fn f() {
+  arr = tint_pack_vec3_in_composite(array(vec3(1.5, 2.5, 3.5), vec3(4.5, 5.5, 6.5)));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_WriteArray_RefRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 2>;
+@group(0) @binding(1) var<uniform> in : array<vec3<f32>, 2>;
+
+fn f() {
+  arr = in;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 2u>;
+
+@group(0) @binding(1) var<uniform> in : array<tint_packed_vec3_f32_array_element, 2u>;
+
+fn f() {
+  arr = in;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_WriteVector_ValueRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
+
+fn f() {
+  arr[0] = vec3(1.23);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+fn f() {
+  arr[0].elements = __packed_vec3<f32>(vec3(1.23));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_WriteVector_RefRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
+@group(0) @binding(1) var<uniform> in_arr : array<vec3<f32>, 4>;
+@group(0) @binding(2) var<uniform> in_vec : vec3<f32>;
+
+fn f() {
+  arr[0] = in_arr[0];
+  arr[1] = in_vec;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+@group(0) @binding(1) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+@group(0) @binding(2) var<uniform> in_vec : __packed_vec3<f32>;
+
+fn f() {
+  arr[0].elements = in_arr[0].elements;
+  arr[1].elements = in_vec;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_WriteComponent_MemberAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
+
+fn f() {
+  arr[0].y = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+fn f() {
+  arr[0].elements.y = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_WriteComponent_IndexAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
+
+fn f() {
+  arr[0][1] = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+fn f() {
+  arr[0].elements[1] = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Matrix_ReadMatrix) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> m : mat3x3<f32>;
+
+fn f() {
+  let x = m;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+@group(0) @binding(0) var<storage> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite(m);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Matrix_ReadColumn) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> m : mat3x3<f32>;
+
+fn f() {
+  let x = m[1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  let x = vec3<f32>(m[1].elements);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Matrix_ReadComponent_MemberAccessChain) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> m : mat3x3<f32>;
+
+fn f() {
+  let x = m[1].yz.x;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  let x = vec3<f32>(m[1].elements).yz.x;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Matrix_ReadComponent_IndexAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> m : mat3x3<f32>;
+
+fn f() {
+  let x = m[2][1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  let x = m[2].elements[1];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Matrix_WriteMatrix_ValueRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
+
+fn f() {
+  m = mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  m = tint_pack_vec3_in_composite(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Matrix_WriteMatrix_RefRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
+@group(0) @binding(1) var<uniform> in : mat3x3<f32>;
+
+fn f() {
+  m = in;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(1) var<uniform> in : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  m = in;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Matrix_WriteColumn_ValueRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
+
+fn f() {
+  m[1] = vec3(1.23);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  m[1].elements = __packed_vec3<f32>(vec3(1.23));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Matrix_WriteColumn_RefRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
+@group(0) @binding(1) var<uniform> in_mat : mat3x3<f32>;
+@group(0) @binding(1) var<uniform> in_vec : vec3<f32>;
+
+fn f() {
+  m[0] = in_mat[0];
+  m[1] = in_vec;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(1) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(1) var<uniform> in_vec : __packed_vec3<f32>;
+
+fn f() {
+  m[0].elements = in_mat[0].elements;
+  m[1].elements = in_vec;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Matrix_WriteComponent_MemberAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
+
+fn f() {
+  m[1].y = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  m[1].elements.y = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Matrix_WriteComponent_IndexAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
+
+fn f() {
+  m[1][2] = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  m[1].elements[2] = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_ReadArray) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
+
+fn f() {
+  let x = arr;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite_1(arr);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_ReadMatrix) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
+
+fn f() {
+  let x = arr[0];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite(arr[0]);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_ReadColumn) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
+
+fn f() {
+  let x = arr[0][1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+fn f() {
+  let x = vec3<f32>(arr[0][1].elements);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_ReadComponent_MemberAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
+
+fn f() {
+  let x = arr[0][1].y;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+fn f() {
+  let x = arr[0][1].elements.y;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_ReadComponent_IndexAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
+
+fn f() {
+  let x = arr[0][1][2];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+fn f() {
+  let x = arr[0][1].elements[2];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_WriteArray_ValueRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 2>;
+
+fn f() {
+  arr = array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 2u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 2u> {
+  var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
+  for(var i : u32; (i < 2u); i = (i + 1)) {
+    result[i] = tint_pack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
+
+fn f() {
+  arr = tint_pack_vec3_in_composite_1(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5)));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_WriteArray_RefRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 2>;
+@group(0) @binding(1) var<uniform> in : array<mat3x3<f32>, 2>;
+
+fn f() {
+  arr = in;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
+
+@group(0) @binding(1) var<uniform> in : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
+
+fn f() {
+  arr = in;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_WriteMatrix_ValueRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
+
+fn f() {
+  arr[0] = mat3x3(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+fn f() {
+  arr[0] = tint_pack_vec3_in_composite(mat3x3(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_WriteMatrix_RefRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
+@group(0) @binding(1) var<uniform> in_arr : array<mat3x3<f32>, 4>;
+@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
+
+fn f() {
+  arr[0] = in_arr[0];
+  arr[1] = in_mat;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(1) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  arr[0] = in_arr[0];
+  arr[1] = in_mat;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_WriteVector_ValueRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
+
+fn f() {
+  arr[0][1] = vec3(1.23);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+fn f() {
+  arr[0][1].elements = __packed_vec3<f32>(vec3(1.23));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_WriteVector_RefRHS) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
+@group(0) @binding(1) var<uniform> in_arr : array<mat3x3<f32>, 4>;
+@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
+@group(0) @binding(3) var<uniform> in_vec : vec3<f32>;
+
+fn f() {
+  arr[0][0] = arr[0][1];
+  arr[0][1] = in_mat[2];
+  arr[0][2] = in_vec;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(1) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(3) var<uniform> in_vec : __packed_vec3<f32>;
+
+fn f() {
+  arr[0][0].elements = arr[0][1].elements;
+  arr[0][1].elements = in_mat[2].elements;
+  arr[0][2].elements = in_vec;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_WriteComponent_MemberAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
+
+fn f() {
+  arr[0][1].y = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+fn f() {
+  arr[0][1].elements.y = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_WriteComponent_IndexAccessor) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
+
+fn f() {
+  arr[0][1][2] = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+fn f() {
+  arr[0][1].elements[2] = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Vec3_ReadStruct) {
     auto* src = R"(
 struct S {
   v : vec3<f32>,
 }
 
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+fn tint_unpack_vec3_in_composite(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.v = vec3<f32>(in.v);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite(P);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Vec3_ReadVector) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.v;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = vec3<f32>(P.v);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Vec3_ReadComponent_MemberAccessChain) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.v.yz.x;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = vec3<f32>(P.v).yz.x;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Vec3_ReadComponent_IndexAccessor) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.v[1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = P.v[1];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Vec3_WriteStruct_ValueRHS) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P = S(vec3(1.23));
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+fn tint_pack_vec3_in_composite(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.v = __packed_vec3<f32>(in.v);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P = tint_pack_vec3_in_composite(S(vec3(1.23)));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Vec3_WriteStruct_RefRHS) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in : S;
+
+fn f() {
+  P = in;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
+
+fn f() {
+  P = in;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Vec3_WriteVector_ValueRHS) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.v = vec3(1.23);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.v = __packed_vec3<f32>(vec3(1.23));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Vec3_WriteVector_RefRHS) {
+    auto* src = R"(
+struct S {
+  v1 : vec3<f32>,
+  v2 : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in_str : S;
+@group(0) @binding(2) var<uniform> in_vec : vec3<f32>;
+
+fn f() {
+  P.v1 = in_str.v1;
+  P.v2 = in_vec;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v1 : __packed_vec3<f32>,
+  @align(16)
+  v2 : __packed_vec3<f32>,
+}
+
+struct S {
+  v1 : vec3<f32>,
+  v2 : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
+
+@group(0) @binding(2) var<uniform> in_vec : __packed_vec3<f32>;
+
+fn f() {
+  P.v1 = in_str.v1;
+  P.v2 = in_vec;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Vec3_WriteComponent_MemberAccessor) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.v.y = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.v.y = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Vec3_WriteComponent_IndexAccessor) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.v[1] = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.v[1] = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadStruct) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.arr = tint_unpack_vec3_in_composite(in.arr);
+  return result;
+}
+
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite_1(P);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadArray) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.arr;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite(P.arr);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadVector) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.arr[0];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = vec3<f32>(P.arr[0].elements);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadComponent_MemberAccessor) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.arr[0].y;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = P.arr[0].elements.y;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadComponent_IndexAccessor) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.arr[0][1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = P.arr[0].elements[1];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteStruct_ValueRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P = S(array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5)));
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 2u>,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 2u>) -> array<tint_packed_vec3_f32_array_element, 2u> {
+  var result : array<tint_packed_vec3_f32_array_element, 2u>;
+  for(var i : u32; (i < 2u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.arr = tint_pack_vec3_in_composite(in.arr);
+  return result;
+}
+
+struct S {
+  arr : array<vec3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P = tint_pack_vec3_in_composite_1(S(array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5))));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteStruct_RefRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in : S;
+
+fn f() {
+  P = in;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 2u>,
+}
+
+struct S {
+  arr : array<vec3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
+
+fn f() {
+  P = in;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteArray_ValueRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.arr = array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5));
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 2u>,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 2u>) -> array<tint_packed_vec3_f32_array_element, 2u> {
+  var result : array<tint_packed_vec3_f32_array_element, 2u>;
+  for(var i : u32; (i < 2u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+struct S {
+  arr : array<vec3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.arr = tint_pack_vec3_in_composite(array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5)));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteArray_RefRHS) {
+    auto* src = R"(
+struct S {
+  arr1 : array<vec3<f32>, 2>,
+  arr2 : array<vec3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in_str : S;
+@group(0) @binding(2) var<uniform> in_arr : array<vec3<f32>, 2>;
+
+fn f() {
+  P.arr1 = in_str.arr1;
+  P.arr2 = in_arr;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr1 : array<tint_packed_vec3_f32_array_element, 2u>,
+  @align(16)
+  arr2 : array<tint_packed_vec3_f32_array_element, 2u>,
+}
+
+struct S {
+  arr1 : array<vec3<f32>, 2>,
+  arr2 : array<vec3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
+
+@group(0) @binding(2) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 2u>;
+
+fn f() {
+  P.arr1 = in_str.arr1;
+  P.arr2 = in_arr;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteVector_ValueRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.arr[0] = vec3(1.23);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.arr[0].elements = __packed_vec3<f32>(vec3(1.23));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteVector_RefRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in_str : S;
+@group(0) @binding(2) var<uniform> in_arr : array<vec3<f32>, 4>;
+@group(0) @binding(3) var<uniform> in_vec : vec3<f32>;
+
+fn f() {
+  P.arr[0] = in_str.arr[0];
+  P.arr[1] = in_arr[1];
+  P.arr[2] = in_vec;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
+
+@group(0) @binding(2) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+@group(0) @binding(3) var<uniform> in_vec : __packed_vec3<f32>;
+
+fn f() {
+  P.arr[0].elements = in_str.arr[0].elements;
+  P.arr[1].elements = in_arr[1].elements;
+  P.arr[2].elements = in_vec;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteComponent_MemberAccessor) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.arr[0].y = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.arr[0].elements.y = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteComponent_IndexAccessor) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.arr[0][1] = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.arr[0].elements[1] = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_ReadStruct) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite_1(P);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_ReadMatrix) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.m;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite(P.m);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_ReadColumn) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.m[1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = vec3<f32>(P.m[1].elements);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_ReadComponent_MemberAccessChain) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.m[1].yz.x;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = vec3<f32>(P.m[1].elements).yz.x;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_ReadComponent_IndexAccessor) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.m[2][1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = P.m[2].elements[1];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_WriteStruct_ValueRHS) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P = S(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.m = tint_pack_vec3_in_composite(in.m);
+  return result;
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P = tint_pack_vec3_in_composite_1(S(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5)));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_WriteStruct_RefRHS) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in : S;
+
+fn f() {
+  P = in;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
+
+fn f() {
+  P = in;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_WriteMatrix_ValueRHS) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.m = mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.m = tint_pack_vec3_in_composite(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_WriteMatrix_RefRHS) {
+    auto* src = R"(
+struct S {
+  m1 : mat3x3<f32>,
+  m2 : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in_str : S;
+@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
+
+fn f() {
+  P.m1 = in_str.m1;
+  P.m2 = in_mat;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m1 : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  m2 : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  m1 : mat3x3<f32>,
+  m2 : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
+
+@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  P.m1 = in_str.m1;
+  P.m2 = in_mat;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_WriteColumn_ValueRHS) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.m[1] = vec3(1.23);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.m[1].elements = __packed_vec3<f32>(vec3(1.23));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_WriteColumn_RefRHS) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in_str : S;
+@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
+@group(0) @binding(3) var<uniform> in_vec : vec3<f32>;
+
+fn f() {
+  P.m[0] = in_str.m[0];
+  P.m[1] = in_mat[1];
+  P.m[2] = in_vec;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
+
+@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(3) var<uniform> in_vec : __packed_vec3<f32>;
+
+fn f() {
+  P.m[0].elements = in_str.m[0].elements;
+  P.m[1].elements = in_mat[1].elements;
+  P.m[2].elements = in_vec;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_WriteComponent_MemberAccessor) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.m[1].y = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.m[1].elements.y = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_Matrix_WriteComponent_IndexAccessor) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.m[1][2] = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.m[1].elements[2] = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadStruct) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.arr = tint_unpack_vec3_in_composite_1(in.arr);
+  return result;
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite_2(P);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadArray) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.arr;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite_1(P.arr);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadMatrix) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.arr[0];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite(P.arr[0]);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadColumn) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.arr[0][1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = vec3<f32>(P.arr[0][1].elements);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadComponent_MemberAccessor) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.arr[0][1].y;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = P.arr[0][1].elements.y;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadComponent_IndexAccessor) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  let x = P.arr[0][1][2];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = P.arr[0][1].elements[2];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteStruct_ValueRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P = S(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5)));
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 2u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 2u> {
+  var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
+  for(var i : u32; (i < 2u); i = (i + 1)) {
+    result[i] = tint_pack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_2(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.arr = tint_pack_vec3_in_composite_1(in.arr);
+  return result;
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P = tint_pack_vec3_in_composite_2(S(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5))));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteStruct_RefRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in : S;
+
+fn f() {
+  P = in;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
+
+fn f() {
+  P = in;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteArray_ValueRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.arr = array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 2u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 2u> {
+  var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
+  for(var i : u32; (i < 2u); i = (i + 1)) {
+    result[i] = tint_pack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.arr = tint_pack_vec3_in_composite_1(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5)));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteArray_RefRHS) {
+    auto* src = R"(
+struct S {
+  arr1 : array<mat3x3<f32>, 2>,
+  arr2 : array<mat3x3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in_str : S;
+@group(0) @binding(2) var<uniform> in_arr : array<mat3x3<f32>, 2>;
+
+fn f() {
+  P.arr1 = in_str.arr1;
+  P.arr2 = in_arr;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr1 : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
+  @align(16)
+  arr2 : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
+}
+
+struct S {
+  arr1 : array<mat3x3<f32>, 2>,
+  arr2 : array<mat3x3<f32>, 2>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
+
+@group(0) @binding(2) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
+
+fn f() {
+  P.arr1 = in_str.arr1;
+  P.arr2 = in_arr;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteMatrix_ValueRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.arr[0] = mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.arr[0] = tint_pack_vec3_in_composite(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteMatrix_RefRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in_str : S;
+@group(0) @binding(2) var<uniform> in_arr : array<mat3x3<f32>, 4>;
+@group(0) @binding(3) var<uniform> in_mat : mat3x3<f32>;
+
+fn f() {
+  P.arr[0] = in_str.arr[0];
+  P.arr[1] = in_arr[1];
+  P.arr[2] = in_mat;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
+
+@group(0) @binding(2) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(3) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
+
+fn f() {
+  P.arr[0] = in_str.arr[0];
+  P.arr[1] = in_arr[1];
+  P.arr[2] = in_mat;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteVector_ValueRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.arr[0][1] = vec3(1.23);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.arr[0][1].elements = __packed_vec3<f32>(vec3(1.23));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteVector_RefRHS) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(1) var<uniform> in_str : S;
+@group(0) @binding(2) var<uniform> in_arr : array<mat3x3<f32>, 4>;
+@group(0) @binding(3) var<uniform> in_mat : mat3x3<f32>;
+@group(0) @binding(4) var<uniform> in_vec : vec3<f32>;
+
+fn f() {
+  P.arr[0][0] = in_str.arr[0][1];
+  P.arr[1][1] = in_arr[3][2];
+  P.arr[2][2] = in_mat[1];
+  P.arr[3][0] = in_vec;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
+
+@group(0) @binding(2) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(3) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(4) var<uniform> in_vec : __packed_vec3<f32>;
+
+fn f() {
+  P.arr[0][0].elements = in_str.arr[0][1].elements;
+  P.arr[1][1].elements = in_arr[3][2].elements;
+  P.arr[2][2].elements = in_mat[1].elements;
+  P.arr[3][0].elements = in_vec;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteComponent_MemberAccessor) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.arr[0][1].y = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.arr[0][1].elements.y = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteComponent_IndexAccessor) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  P.arr[0][1][2] = 1.23;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4u>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  P.arr[0][1].elements[2] = 1.23;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes) {
+    auto* src = R"(
+struct S {
+  @align(32) @size(32) v : vec3<f32>,
+  @align(64) @size(64) arr : array<vec3<f32>, 4>,
+  @align(128) @size(128) x : u32,
+}
+
 @group(0) @binding(0) var<uniform> P : S;
 
 fn f() {
-  let x = P.v;
+  let x = P.v[0];
 }
 )";
 
     auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(32) @size(32)
+  v : __packed_vec3<f32>,
+  @align(64) @size(64)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(128) @size(128)
+  x : u32,
+}
+
 struct S {
-  @internal(packed_vector)
+  @align(32) @size(32)
   v : vec3<f32>,
+  @align(64) @size(64)
+  arr : array<vec3<f32>, 4>,
+  @align(128) @size(128)
+  x : u32,
+}
+
+@group(0) @binding(0) var<uniform> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = P.v[0];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes_SizeMatchesUnpackedVec3) {
+    // Test that the type we replace a vec3 with is not larger than it should be.
+    auto* src = R"(
+struct S {
+  @size(12) v : vec3<f32>,
+  @size(64) arr : array<vec3<f32>, 4>,
 }
 
 @group(0) @binding(0) var<uniform> P : S;
 
 fn f() {
-  let x = vec3<f32>(P.v);
-}
-)";
-
-    DataMap data;
-    auto got = Run<PackedVec3>(src, data);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StorageAddressSpace) {
-    auto* src = R"(
-struct S {
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = P.v;
+  let x = P.v[0];
 }
 )";
 
     auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
 }
 
-@group(0) @binding(0) var<storage> P : S;
+struct S_tint_packed_vec3 {
+  @size(12) @align(16)
+  v : __packed_vec3<f32>,
+  @size(64) @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  @size(12)
+  v : vec3<f32>,
+  @size(64)
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<uniform> P : S_tint_packed_vec3;
 
 fn f() {
-  let x = vec3<f32>(P.v);
+  let x = P.v[0];
 }
 )";
 
@@ -135,29 +4095,52 @@
     EXPECT_EQ(expect, str(got));
 }
 
-TEST_F(PackedVec3Test, ExistingMemberAttributes) {
+TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes_AlignTooSmall) {
+    // Test that we add an @align() attribute when the new alignment of the packed vec3 struct would
+    // be too small.
     auto* src = R"(
 struct S {
-  @align(32) @size(64) v : vec3<f32>,
+  a : u32,
+  v : vec3<f32>,
+  b : u32,
+  arr : array<vec3<f32>, 4>,
 }
 
-@group(0) @binding(0) var<storage> P : S;
+@group(0) @binding(0) var<uniform> P : S;
 
 fn f() {
-  let x = P.v;
+  let x = P.v[0];
 }
 )";
 
     auto* expect = R"(
-struct S {
-  @internal(packed_vector) @align(32) @size(64)
-  v : vec3<f32>,
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
 }
 
-@group(0) @binding(0) var<storage> P : S;
+struct S_tint_packed_vec3 {
+  a : u32,
+  @align(16)
+  v : __packed_vec3<f32>,
+  b : u32,
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  a : u32,
+  v : vec3<f32>,
+  b : u32,
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<uniform> P : S_tint_packed_vec3;
 
 fn f() {
-  let x = vec3<f32>(P.v);
+  let x = P.v[0];
 }
 )";
 
@@ -167,7 +4150,441 @@
     EXPECT_EQ(expect, str(got));
 }
 
-TEST_F(PackedVec3Test, MultipleVectors) {
+TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes_ExplicitOffset) {
+    // Test that the we do not add an @align attribute if @offset is present.
+
+    // struct S {
+    //   a : u32,
+    //   @offset(32) v : vec3<f32>,
+    //   b : u32,
+    //   @offset(128) arr : array<vec3<f32>, 4>,
+    // }
+    //
+    // @group(0) @binding(0) var<uniform> P : S;
+    ProgramBuilder b;
+    b.Structure("S", utils::Vector{
+                         b.Member("a", b.ty.u32()),
+                         b.Member("v", b.ty.vec3<f32>(), utils::Vector{b.MemberOffset(AInt(32))}),
+                         b.Member("b", b.ty.u32()),
+                         b.Member("arr", b.ty.array(b.ty.vec3<f32>(), b.Expr(AInt(4))),
+                                  utils::Vector{b.MemberOffset(AInt(128))}),
+                     });
+    b.GlobalVar("P", builtin::AddressSpace::kStorage, b.ty("S"),
+                utils::Vector{b.Group(AInt(0)), b.Binding(AInt(0))});
+    Program src(std::move(b));
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  a : u32,
+  @size(28)
+  padding : u32,
+  /* @offset(32) */
+  v : __packed_vec3<f32>,
+  b : u32,
+  @size(80)
+  padding_1 : u32,
+  /* @offset(128) */
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  a : u32,
+  @size(16)
+  padding_2 : u32,
+  /* @offset(32) */
+  v : vec3<f32>,
+  b : u32,
+  @size(80)
+  padding_3 : u32,
+  /* @offset(128) */
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(std::move(src), data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructValueConstructor_ViaIndexAccessor) {
+    auto* src = R"(
+struct S {
+  a : vec3<f32>,
+  b : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> s : S;
+
+fn f() {
+  let value_arr : array<vec3<f32>, 4> = array<vec3<f32>, 4>();
+  let x = S(value_arr[0], s.arr[0], value_arr);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  a : __packed_vec3<f32>,
+  @align(16)
+  b : __packed_vec3<f32>,
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct S {
+  a : vec3<f32>,
+  b : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> s : S_tint_packed_vec3;
+
+fn f() {
+  let value_arr : array<vec3<f32>, 4> = array<vec3<f32>, 4>();
+  let x = S(value_arr[0], vec3<f32>(s.arr[0].elements), value_arr);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, WrapperStructLayout_MixedUsage) {
+    // Test the layout of the generated wrapper struct(s) when vec3s are used in both structures and
+    // arrays.
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  a : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> str : S;
+@group(0) @binding(1) var<storage, read_write> arr : array<vec3<f32>, 4>;
+
+fn main() {
+  str.v = arr[0];
+  arr[1] = str.v;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  a : u32,
+}
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S {
+  v : vec3<f32>,
+  a : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> str : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+fn main() {
+  str.v = arr[0].elements;
+  arr[1].elements = str.v;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    auto& vars = got.program.AST().GlobalVariables();
+    ASSERT_EQ(vars.Length(), 2u);
+
+    {
+        // Check the layout of the struct type of "str".
+        // The first member should have an alignment of 16 bytes, a size of 12 bytes, and the second
+        // member should have an offset of 12 bytes.
+        auto* sem_str = got.program.Sem().Get(vars[0]);
+        auto* str_ty = sem_str->Type()->UnwrapRef()->As<sem::Struct>();
+        ASSERT_NE(str_ty, nullptr);
+        ASSERT_EQ(str_ty->Members().Length(), 2u);
+        EXPECT_EQ(str_ty->Members()[0]->Align(), 16u);
+        EXPECT_EQ(str_ty->Members()[0]->Size(), 12u);
+        EXPECT_EQ(str_ty->Members()[1]->Offset(), 12u);
+    }
+
+    {
+        // Check the layout of the array type of "arr".
+        // The element stride should be 16 bytes.
+        auto* sem_arr = got.program.Sem().Get(vars[1]);
+        auto* arr_ty = sem_arr->Type()->UnwrapRef()->As<type::Array>();
+        ASSERT_NE(arr_ty, nullptr);
+        EXPECT_EQ(arr_ty->Stride(), 16u);
+    }
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, PackUnpackStructWithNonVec3Members) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
+  a : u32,
+  b : vec4<f32>,
+  c : array<vec4<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+  let x = P;
+  P = x;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+  a : u32,
+  b : vec4<f32>,
+  c : array<vec4<f32>, 4>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.v = vec3<f32>(in.v);
+  result.arr = tint_unpack_vec3_in_composite(in.arr);
+  result.a = in.a;
+  result.b = in.b;
+  result.c = in.c;
+  return result;
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
+  var result : array<tint_packed_vec3_f32_array_element, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.v = __packed_vec3<f32>(in.v);
+  result.arr = tint_pack_vec3_in_composite(in.arr);
+  result.a = in.a;
+  result.b = in.b;
+  result.c = in.c;
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
+  a : u32,
+  b : vec4<f32>,
+  c : array<vec4<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+  let x = tint_unpack_vec3_in_composite_1(P);
+  P = tint_pack_vec3_in_composite_1(x);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Struct_ShaderIO) {
+    // Test that we do not modify structures that are used for shader IO.
+    auto* src = R"(
+struct S1 {
+  @location(0) v : vec3<f32>,
+}
+
+struct S2 {
+  @location(0) v : vec3<f32>,
+  @builtin(position) pos : vec4<f32>,
+}
+
+@vertex
+fn main(s1 : S1) -> S2 {
+  let v : vec3<f32> = s1.v;
+  var s2 : S2;
+  s2.v = v;
+  return s2;
+}
+)";
+
+    auto* expect = R"(
+struct S1 {
+  @location(0)
+  v : vec3<f32>,
+}
+
+struct S2 {
+  @location(0)
+  v : vec3<f32>,
+  @builtin(position)
+  pos : vec4<f32>,
+}
+
+@vertex
+fn main(s1 : S1) -> S2 {
+  let v : vec3<f32> = s1.v;
+  var s2 : S2;
+  s2.v = v;
+  return s2;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ModfReturnStruct) {
+    // Test that we do not try to modify accessors on the anonymous structure returned by modf.
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> output : vec3<f32>;
+
+const values = array(modf(vec3(1.0, 2.0, 3.0)).fract);
+
+@compute @workgroup_size(1)
+fn main() {
+  output = values[0];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage, read_write> output : __packed_vec3<f32>;
+
+const values = array(modf(vec3(1.0, 2.0, 3.0)).fract);
+
+@compute @workgroup_size(1)
+fn main() {
+  output = __packed_vec3<f32>(values[0]);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ModfReturnStruct_PointerToMember) {
+    // Test that we can pass a pointer to the vec3 member of the modf return struct to a function
+    // parameter to which we also pass a pointer to a vec3 member on a host-shareable struct.
+    auto* src = R"(
+enable chromium_experimental_full_ptr_parameters;
+
+struct S {
+  v : vec3<f32>
+}
+
+@group(0) @binding(0) var<storage, read_write> output : S;
+
+fn foo(p : ptr<function, vec3<f32>>) {
+  (*p) = vec3(1, 2, 3);
+}
+
+@compute @workgroup_size(1)
+fn main() {
+  var f : S;
+  var modf_ret = modf(vec3(1.0, 2.0, 3.0));
+  foo(&f.v);
+  foo(&modf_ret.fract);
+  output.v = modf_ret.fract;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+enable chromium_experimental_full_ptr_parameters;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> output : S_tint_packed_vec3;
+
+fn foo(p : ptr<function, vec3<f32>>) {
+  *(p) = vec3(1, 2, 3);
+}
+
+@compute @workgroup_size(1)
+fn main() {
+  var f : S;
+  var modf_ret = modf(vec3(1.0, 2.0, 3.0));
+  foo(&(f.v));
+  foo(&(modf_ret.fract));
+  output.v = __packed_vec3<f32>(modf_ret.fract);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MultipleStructMembers) {
     auto* src = R"(
 struct S {
   v2_a : vec2<f32>,
@@ -176,6 +4593,9 @@
   v2_b : vec2<f32>,
   v3_b : vec3<f32>,
   v4_b : vec4<f32>,
+  v2_arr : array<vec2<f32>, 4>,
+  v3_arr : array<vec3<f32>, 4>,
+  v4_arr : array<vec4<f32>, 4>,
 }
 
 @group(0) @binding(0) var<storage> P : S;
@@ -187,22 +4607,56 @@
   let v2_b = P.v2_b;
   let v3_b = P.v3_b;
   let v4_b = P.v4_b;
+  let v2_arr : array<vec2<f32>, 4> = P.v2_arr;
+  let v3_arr : array<vec3<f32>, 4> = P.v3_arr;
+  let v4_arr : array<vec4<f32>, 4> = P.v4_arr;
 }
 )";
 
     auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  v2_a : vec2<f32>,
+  @align(16)
+  v3_a : __packed_vec3<f32>,
+  v4_a : vec4<f32>,
+  v2_b : vec2<f32>,
+  @align(16)
+  v3_b : __packed_vec3<f32>,
+  v4_b : vec4<f32>,
+  v2_arr : array<vec2<f32>, 4>,
+  @align(16)
+  v3_arr : array<tint_packed_vec3_f32_array_element, 4u>,
+  v4_arr : array<vec4<f32>, 4>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
 struct S {
   v2_a : vec2<f32>,
-  @internal(packed_vector)
   v3_a : vec3<f32>,
   v4_a : vec4<f32>,
   v2_b : vec2<f32>,
-  @internal(packed_vector)
   v3_b : vec3<f32>,
   v4_b : vec4<f32>,
+  v2_arr : array<vec2<f32>, 4>,
+  v3_arr : array<vec3<f32>, 4>,
+  v4_arr : array<vec4<f32>, 4>,
 }
 
-@group(0) @binding(0) var<storage> P : S;
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
 
 fn f() {
   let v2_a = P.v2_a;
@@ -211,6 +4665,9 @@
   let v2_b = P.v2_b;
   let v3_b = vec3<f32>(P.v3_b);
   let v4_b = P.v4_b;
+  let v2_arr : array<vec2<f32>, 4> = P.v2_arr;
+  let v3_arr : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite(P.v3_arr);
+  let v4_arr : array<vec4<f32>, 4> = P.v4_arr;
 }
 )";
 
@@ -220,31 +4677,1116 @@
     EXPECT_EQ(expect, str(got));
 }
 
-TEST_F(PackedVec3Test, MixedAddressSpace) {
+TEST_F(PackedVec3Test, Vec3Pointers) {
     auto* src = R"(
 struct S {
   v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
 }
 
-@group(0) @binding(0) var<storage> P : S;
+@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
+@group(0) @binding(1) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
+@group(0) @binding(2) var<storage, read_write> m : mat3x3<f32>;
+@group(0) @binding(3) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
+@group(0) @binding(4) var<storage, read_write> str : S;
+
+fn f() {
+  let p_v = &v;
+  let v = *p_v;
+  *p_v = v;
+
+  let p_arr_v = &arr_v[0];
+  let arr_v = *p_arr_v;
+  *p_arr_v = arr_v;
+
+  let p_m = &m[0];
+  let m = *p_m;
+  *p_m = m;
+
+  let p_arr_m = &arr_m[0][1];
+  let arr_m = *p_arr_m;
+  *p_arr_m = arr_m;
+
+  let p_str_v = &str.v;
+  let str_v = *p_str_v;
+  *p_str_v = str_v;
+
+  let p_str_arr_v = &str.arr_v[0];
+  let str_arr_v = *p_str_arr_v;
+  *p_str_arr_v = str_arr_v;
+
+  let p_str_m = &str.m[0];
+  let str_m = *p_str_m;
+  *p_str_m = str_m;
+
+  let p_str_arr_m = &str.arr_m[0][1];
+  let str_arr_m = *p_str_arr_m;
+  *p_str_arr_m = str_arr_m;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
+
+@group(0) @binding(1) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
+
+@group(0) @binding(2) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(3) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(4) var<storage, read_write> str : S_tint_packed_vec3;
+
+fn f() {
+  let p_v = &(v);
+  let v = vec3<f32>(*(p_v));
+  *(p_v) = __packed_vec3<f32>(v);
+  let p_arr_v = &(arr_v[0].elements);
+  let arr_v = vec3<f32>(*(p_arr_v));
+  *(p_arr_v) = __packed_vec3<f32>(arr_v);
+  let p_m = &(m[0].elements);
+  let m = vec3<f32>(*(p_m));
+  *(p_m) = __packed_vec3<f32>(m);
+  let p_arr_m = &(arr_m[0][1].elements);
+  let arr_m = vec3<f32>(*(p_arr_m));
+  *(p_arr_m) = __packed_vec3<f32>(arr_m);
+  let p_str_v = &(str.v);
+  let str_v = vec3<f32>(*(p_str_v));
+  *(p_str_v) = __packed_vec3<f32>(str_v);
+  let p_str_arr_v = &(str.arr_v[0].elements);
+  let str_arr_v = vec3<f32>(*(p_str_arr_v));
+  *(p_str_arr_v) = __packed_vec3<f32>(str_arr_v);
+  let p_str_m = &(str.m[0].elements);
+  let str_m = vec3<f32>(*(p_str_m));
+  *(p_str_m) = __packed_vec3<f32>(str_m);
+  let p_str_arr_m = &(str.arr_m[0][1].elements);
+  let str_arr_m = vec3<f32>(*(p_str_arr_m));
+  *(p_str_arr_m) = __packed_vec3<f32>(str_arr_m);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MatrixPointers) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
+@group(0) @binding(1) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
+@group(0) @binding(2) var<storage, read_write> str : S;
+
+fn f() {
+  let p_m = &m;
+  let m = *p_m;
+  *p_m = m;
+
+  let p_arr_m = &arr_m[0];
+  let arr_m = *p_arr_m;
+  *p_arr_m = arr_m;
+
+  let p_str_m = &str.m;
+  let str_m = *p_str_m;
+  *p_str_m = str_m;
+
+  let p_str_arr_m = &str.arr_m[0];
+  let str_arr_m = *p_str_arr_m;
+  *p_str_arr_m = str_arr_m;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+struct S {
+  m : mat3x3<f32>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(1) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(2) var<storage, read_write> str : S_tint_packed_vec3;
+
+fn f() {
+  let p_m = &(m);
+  let m = tint_unpack_vec3_in_composite(*(p_m));
+  *(p_m) = tint_pack_vec3_in_composite(m);
+  let p_arr_m = &(arr_m[0]);
+  let arr_m = tint_unpack_vec3_in_composite(*(p_arr_m));
+  *(p_arr_m) = tint_pack_vec3_in_composite(arr_m);
+  let p_str_m = &(str.m);
+  let str_m = tint_unpack_vec3_in_composite(*(p_str_m));
+  *(p_str_m) = tint_pack_vec3_in_composite(str_m);
+  let p_str_arr_m = &(str.arr_m[0]);
+  let str_arr_m = tint_unpack_vec3_in_composite(*(p_str_arr_m));
+  *(p_str_arr_m) = tint_pack_vec3_in_composite(str_arr_m);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3Pointers) {
+    auto* src = R"(
+struct S {
+  arr_v : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
+@group(0) @binding(1) var<storage, read_write> str : S;
+
+fn f() {
+  let p_arr_v = &arr_v;
+  let arr_v = *p_arr_v;
+  *p_arr_v = arr_v;
+
+  let p_str_arr_v = &str.arr_v;
+  let str_arr_v = *p_str_arr_v;
+  *p_str_arr_v = str_arr_v;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
+  var result : array<tint_packed_vec3_f32_array_element, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+struct S {
+  arr_v : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
+
+@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
+
+fn f() {
+  let p_arr_v = &(arr_v);
+  let arr_v = tint_unpack_vec3_in_composite(*(p_arr_v));
+  *(p_arr_v) = tint_pack_vec3_in_composite(arr_v);
+  let p_str_arr_v = &(str.arr_v);
+  let str_arr_v = tint_unpack_vec3_in_composite(*(p_str_arr_v));
+  *(p_str_arr_v) = tint_pack_vec3_in_composite(str_arr_v);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrixPointers) {
+    auto* src = R"(
+struct S {
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
+@group(0) @binding(1) var<storage, read_write> str : S;
+
+fn f() {
+  let p_arr_m = &arr_m;
+  let arr_m = *p_arr_m;
+  *p_arr_m = arr_m;
+
+  let p_str_arr_m = &str.arr_m;
+  let str_arr_m = *p_str_arr_m;
+  *p_str_arr_m = str_arr_m;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
+  var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_pack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+struct S {
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
+
+fn f() {
+  let p_arr_m = &(arr_m);
+  let arr_m = tint_unpack_vec3_in_composite_1(*(p_arr_m));
+  *(p_arr_m) = tint_pack_vec3_in_composite_1(arr_m);
+  let p_str_arr_m = &(str.arr_m);
+  let str_arr_m = tint_unpack_vec3_in_composite_1(*(p_str_arr_m));
+  *(p_str_arr_m) = tint_pack_vec3_in_composite_1(str_arr_m);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructPointers) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> str : S;
+
+fn f() {
+  let p_str = &str;
+  let str = *p_str;
+  *p_str = str;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.v = vec3<f32>(in.v);
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
+  result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
+  return result;
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
+  var result : array<tint_packed_vec3_f32_array_element, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_2(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
+  var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_pack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_3(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.v = __packed_vec3<f32>(in.v);
+  result.m = tint_pack_vec3_in_composite(in.m);
+  result.arr_v = tint_pack_vec3_in_composite_1(in.arr_v);
+  result.arr_m = tint_pack_vec3_in_composite_2(in.arr_m);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> str : S_tint_packed_vec3;
+
+fn f() {
+  let p_str = &(str);
+  let str = tint_unpack_vec3_in_composite_3(*(p_str));
+  *(p_str) = tint_pack_vec3_in_composite_3(str);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, VectorPointerParameters) {
+    auto* src = R"(
+enable chromium_experimental_full_ptr_parameters;
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
+@group(0) @binding(1) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
+@group(0) @binding(2) var<storage, read_write> m : mat3x3<f32>;
+@group(0) @binding(3) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
+@group(0) @binding(4) var<storage, read_write> str : S;
+
+fn load(p : ptr<storage, vec3<f32>, read_write>) -> vec3<f32> {
+  return *p;
+}
+
+fn store(p : ptr<storage, vec3<f32>, read_write>) {
+  *p = vec3(1, 2, 3);
+}
+
+fn f() {
+  load(&v);
+  store(&v);
+  load(&arr_v[0]);
+  store(&arr_v[0]);
+  load(&m[0]);
+  store(&m[0]);
+  load(&arr_m[0][1]);
+  store(&arr_m[0][1]);
+  load(&str.v);
+  store(&str.v);
+  load(&str.arr_v[0]);
+  store(&str.arr_v[0]);
+  load(&str.m[0]);
+  store(&str.m[0]);
+  load(&str.arr_m[0][1]);
+  store(&str.arr_m[0][1]);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+enable chromium_experimental_full_ptr_parameters;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
+
+@group(0) @binding(1) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
+
+@group(0) @binding(2) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(3) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(4) var<storage, read_write> str : S_tint_packed_vec3;
+
+fn load(p : ptr<storage, __packed_vec3<f32>, read_write>) -> vec3<f32> {
+  return vec3<f32>(*(p));
+}
+
+fn store(p : ptr<storage, __packed_vec3<f32>, read_write>) {
+  *(p) = __packed_vec3<f32>(vec3(1, 2, 3));
+}
+
+fn f() {
+  load(&(v));
+  store(&(v));
+  load(&(arr_v[0].elements));
+  store(&(arr_v[0].elements));
+  load(&(m[0].elements));
+  store(&(m[0].elements));
+  load(&(arr_m[0][1].elements));
+  store(&(arr_m[0][1].elements));
+  load(&(str.v));
+  store(&(str.v));
+  load(&(str.arr_v[0].elements));
+  store(&(str.arr_v[0].elements));
+  load(&(str.m[0].elements));
+  store(&(str.m[0].elements));
+  load(&(str.arr_m[0][1].elements));
+  store(&(str.arr_m[0][1].elements));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MatrixPointerParameters) {
+    auto* src = R"(
+enable chromium_experimental_full_ptr_parameters;
+
+struct S {
+  m : mat3x3<f32>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
+@group(0) @binding(1) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
+@group(0) @binding(2) var<storage, read_write> str : S;
+
+fn load(p : ptr<storage, mat3x3<f32>, read_write>) -> mat3x3<f32> {
+  return *p;
+}
+
+fn store(p : ptr<storage, mat3x3<f32>, read_write>) {
+  *p = mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9);
+}
+
+fn f() {
+  load(&m);
+  store(&m);
+  load(&arr_m[0]);
+  store(&arr_m[0]);
+  load(&str.m);
+  store(&str.m);
+  load(&str.arr_m[0]);
+  store(&str.arr_m[0]);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+enable chromium_experimental_full_ptr_parameters;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+struct S {
+  m : mat3x3<f32>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(1) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(2) var<storage, read_write> str : S_tint_packed_vec3;
+
+fn load(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 3u>, read_write>) -> mat3x3<f32> {
+  return tint_unpack_vec3_in_composite(*(p));
+}
+
+fn store(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 3u>, read_write>) {
+  *(p) = tint_pack_vec3_in_composite(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9));
+}
+
+fn f() {
+  load(&(m));
+  store(&(m));
+  load(&(arr_m[0]));
+  store(&(arr_m[0]));
+  load(&(str.m));
+  store(&(str.m));
+  load(&(str.arr_m[0]));
+  store(&(str.arr_m[0]));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVectorPointerParameters) {
+    auto* src = R"(
+enable chromium_experimental_full_ptr_parameters;
+
+struct S {
+  arr_v : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
+@group(0) @binding(1) var<storage, read_write> str : S;
+
+fn load(p : ptr<storage, array<vec3<f32>, 4>, read_write>) -> array<vec3<f32>, 4> {
+  return *p;
+}
+
+fn store(p : ptr<storage, array<vec3<f32>, 4>, read_write>) {
+  *p = array(vec3(1.0), vec3(2.0), vec3(3.0), vec3(4.0));
+}
+
+fn f() {
+  load(&arr_v);
+  store(&arr_v);
+  load(&str.arr_v);
+  store(&str.arr_v);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+enable chromium_experimental_full_ptr_parameters;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
+  var result : array<tint_packed_vec3_f32_array_element, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+struct S {
+  arr_v : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
+
+@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
+
+fn load(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 4u>, read_write>) -> array<vec3<f32>, 4> {
+  return tint_unpack_vec3_in_composite(*(p));
+}
+
+fn store(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 4u>, read_write>) {
+  *(p) = tint_pack_vec3_in_composite(array(vec3(1.0), vec3(2.0), vec3(3.0), vec3(4.0)));
+}
+
+fn f() {
+  load(&(arr_v));
+  store(&(arr_v));
+  load(&(str.arr_v));
+  store(&(str.arr_v));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrixPointerParameters) {
+    auto* src = R"(
+enable chromium_experimental_full_ptr_parameters;
+
+struct S {
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
+@group(0) @binding(1) var<storage, read_write> str : S;
+
+fn load(p : ptr<storage, array<mat3x3<f32>, 4>, read_write>) -> array<mat3x3<f32>, 4> {
+  return *p;
+}
+
+fn store(p : ptr<storage, array<mat3x3<f32>, 4>, read_write>) {
+  *p = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
+}
+
+fn f() {
+  load(&arr_m);
+  store(&arr_m);
+  load(&str.arr_m);
+  store(&str.arr_m);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+enable chromium_experimental_full_ptr_parameters;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
+  var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_pack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+struct S {
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
+
+fn load(p : ptr<storage, array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, read_write>) -> array<mat3x3<f32>, 4> {
+  return tint_unpack_vec3_in_composite_1(*(p));
+}
+
+fn store(p : ptr<storage, array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, read_write>) {
+  *(p) = tint_pack_vec3_in_composite_1(array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>()));
+}
+
+fn f() {
+  load(&(arr_m));
+  store(&(arr_m));
+  load(&(str.arr_m));
+  store(&(str.arr_m));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructPointerParameters) {
+    auto* src = R"(
+enable chromium_experimental_full_ptr_parameters;
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> str : S;
+
+fn load(p : ptr<storage, S, read_write>) -> S {
+  return *p;
+}
+
+fn store(p : ptr<storage, S, read_write>) {
+  *p = S();
+}
+
+fn f() {
+  load(&str);
+  store(&str);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+enable chromium_experimental_full_ptr_parameters;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.v = vec3<f32>(in.v);
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
+  result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
+  return result;
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
+  var result : array<tint_packed_vec3_f32_array_element, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_2(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
+  var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_pack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_3(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.v = __packed_vec3<f32>(in.v);
+  result.m = tint_pack_vec3_in_composite(in.m);
+  result.arr_v = tint_pack_vec3_in_composite_1(in.arr_v);
+  result.arr_m = tint_pack_vec3_in_composite_2(in.arr_m);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> str : S_tint_packed_vec3;
+
+fn load(p : ptr<storage, S_tint_packed_vec3, read_write>) -> S {
+  return tint_unpack_vec3_in_composite_3(*(p));
+}
+
+fn store(p : ptr<storage, S_tint_packed_vec3, read_write>) {
+  *(p) = tint_pack_vec3_in_composite_3(S());
+}
+
+fn f() {
+  load(&(str));
+  store(&(str));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MixedAddressSpace_Struct) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
 
 fn f() {
   var f : S;
-  let x = f.v;
+  let v = f.v;
+  let arr = f.arr;
+  P = f;
 }
 )";
 
     auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
 }
 
-@group(0) @binding(0) var<storage> P : S;
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
+  var result : array<tint_packed_vec3_f32_array_element, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.v = __packed_vec3<f32>(in.v);
+  result.arr = tint_pack_vec3_in_composite(in.arr);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
 
 fn f() {
   var f : S;
-  let x = vec3<f32>(f.v);
+  let v = f.v;
+  let arr = f.arr;
+  P = tint_pack_vec3_in_composite_1(f);
 }
 )";
 
@@ -254,29 +5796,88 @@
     EXPECT_EQ(expect, str(got));
 }
 
-TEST_F(PackedVec3Test, ReadMemberAccessChain) {
+TEST_F(PackedVec3Test, MixedAddressSpace_NestedStruct) {
     auto* src = R"(
 struct S {
   v : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
 }
 
-@group(0) @binding(0) var<storage> P : S;
+struct Outer {
+  inner : S,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : Outer;
 
 fn f() {
-  let x = P.v.yz.x;
+  var f : Outer;
+  let v = f.inner.v;
+  let arr = f.inner.arr;
+  P = f;
+  P.inner = f.inner;
+  P.inner.v = f.inner.v;
 }
 )";
 
     auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
 }
 
-@group(0) @binding(0) var<storage> P : S;
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+struct Outer_tint_packed_vec3 {
+  @align(16)
+  inner : S_tint_packed_vec3,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
+  var result : array<tint_packed_vec3_f32_array_element, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.v = __packed_vec3<f32>(in.v);
+  result.arr = tint_pack_vec3_in_composite(in.arr);
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_2(in : Outer) -> Outer_tint_packed_vec3 {
+  var result : Outer_tint_packed_vec3;
+  result.inner = tint_pack_vec3_in_composite_1(in.inner);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
+}
+
+struct Outer {
+  inner : S,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : Outer_tint_packed_vec3;
 
 fn f() {
-  let x = P.v.yz.x;
+  var f : Outer;
+  let v = f.inner.v;
+  let arr = f.inner.arr;
+  P = tint_pack_vec3_in_composite_2(f);
+  P.inner = tint_pack_vec3_in_composite_1(f.inner);
+  P.inner.v = __packed_vec3<f32>(f.inner.v);
 }
 )";
 
@@ -286,305 +5887,94 @@
     EXPECT_EQ(expect, str(got));
 }
 
-TEST_F(PackedVec3Test, ReadVector) {
+TEST_F(PackedVec3Test, MixedAddressSpace_AnotherStructNotShared) {
+    // Test that we can pass a pointers to a members of both shared and non-shared structs to the
+    // same function.
     auto* src = R"(
+enable chromium_experimental_full_ptr_parameters;
+
 struct S {
   v : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
 }
 
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = P.v;
-}
-)";
-
-    auto* expect = R"(
-struct S {
-  @internal(packed_vector)
+struct NotShared {
   v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = vec3<f32>(P.v);
-}
-)";
-
-    DataMap data;
-    auto got = Run<PackedVec3>(src, data);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ReadIndexAccessor) {
-    auto* src = R"(
-struct S {
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = P.v[1];
-}
-)";
-
-    auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = P.v[1];
-}
-)";
-
-    DataMap data;
-    auto got = Run<PackedVec3>(src, data);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ReadViaStructPtrDirect) {
-    auto* src = R"(
-struct S {
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = (*(&(*(&P)))).v;
-}
-)";
-
-    auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = vec3<f32>((*(&(*(&(P))))).v);
-}
-)";
-
-    DataMap data;
-    auto got = Run<PackedVec3>(src, data);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ReadViaVectorPtrDirect) {
-    auto* src = R"(
-struct S {
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = *(&(*(&(P.v))));
-}
-)";
-
-    auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = vec3<f32>(*(&(*(&(P.v)))));
-}
-)";
-
-    DataMap data;
-    auto got = Run<PackedVec3>(src, data);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ReadViaStructPtrViaLet) {
-    auto* src = R"(
-struct S {
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let p0 = &P;
-  let p1 = &(*(p0));
-  let a = (*p1).v;
-  let p2 = &(*(p1));
-  let b = (*p2).v;
-  let c = (*p2).v;
-}
-)";
-
-    auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let p0 = &(P);
-  let p1 = &(*(p0));
-  let a = vec3<f32>((*(p1)).v);
-  let p2 = &(*(p1));
-  let b = vec3<f32>((*(p2)).v);
-  let c = vec3<f32>((*(p2)).v);
-}
-)";
-
-    DataMap data;
-    auto got = Run<PackedVec3>(src, data);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ReadViaVectorPtrViaLet) {
-    auto* src = R"(
-struct S {
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let p0 = &(P.v);
-  let p1 = &(*(p0));
-  let a = *p1;
-  let p2 = &(*(p1));
-  let b = *p2;
-  let c = *p2;
-}
-)";
-
-    auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let p0 = &(P.v);
-  let p1 = &(*(p0));
-  let a = vec3<f32>(*(p1));
-  let p2 = &(*(p1));
-  let b = vec3<f32>(*(p2));
-  let c = vec3<f32>(*(p2));
-}
-)";
-
-    DataMap data;
-    auto got = Run<PackedVec3>(src, data);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ReadUnaryOp) {
-    auto* src = R"(
-struct S {
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = -P.v;
-}
-)";
-
-    auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = -(vec3<f32>(P.v));
-}
-)";
-
-    DataMap data;
-    auto got = Run<PackedVec3>(src, data);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ReadBinaryOp) {
-    auto* src = R"(
-struct S {
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = P.v + P.v;
-}
-)";
-
-    auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
-  let x = (vec3<f32>(P.v) + vec3<f32>(P.v));
-}
-)";
-
-    DataMap data;
-    auto got = Run<PackedVec3>(src, data);
-
-    EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, WriteVector) {
-    auto* src = R"(
-struct S {
-  v : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
 }
 
 @group(0) @binding(0) var<storage, read_write> P : S;
 
+fn g(p : ptr<function, vec3<f32>>) -> vec3<f32> {
+  return *p;
+}
+
 fn f() {
-  P.v = vec3(1.23);
+  var f1 : S;
+  var f2 : NotShared;
+  g(&f1.v);
+  g(&f1.arr[0]);
+  g(&f2.v);
+  g(&f2.arr[0]);
+  P = f1;
 }
 )";
 
     auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
+enable chromium_internal_relaxed_uniform_layout;
+enable chromium_experimental_full_ptr_parameters;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
 }
 
-@group(0) @binding(0) var<storage, read_write> P : S;
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
+  var result : array<tint_packed_vec3_f32_array_element, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.v = __packed_vec3<f32>(in.v);
+  result.arr = tint_pack_vec3_in_composite(in.arr);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
+}
+
+struct NotShared {
+  v : vec3<f32>,
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn g(p : ptr<function, vec3<f32>>) -> vec3<f32> {
+  return *(p);
+}
 
 fn f() {
-  P.v = vec3(1.23);
+  var f1 : S;
+  var f2 : NotShared;
+  g(&(f1.v));
+  g(&(f1.arr[0]));
+  g(&(f2.v));
+  g(&(f2.arr[0]));
+  P = tint_pack_vec3_in_composite_1(f1);
 }
 )";
 
@@ -594,29 +5984,103 @@
     EXPECT_EQ(expect, str(got));
 }
 
-TEST_F(PackedVec3Test, WriteMemberAccess) {
+TEST_F(PackedVec3Test, MixedAddressSpace_InitFromLoad_ExplicitVarType) {
     auto* src = R"(
 struct S {
   v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
 }
 
-@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(0) var<storage> P : S;
 
 fn f() {
-  P.v.y = 1.23;
+  var f1 : S = P;
+  var f2 : vec3<f32> = P.v;
+  var f3 : mat3x3<f32> = P.m;
+  var f4 : array<vec3<f32>, 4> = P.arr_v;
+  var f5 : array<mat3x3<f32>, 4> = P.arr_m;
+  let v_1 = f1.v;
+  let v_2 = f2;
+  let v_3 = f3[0];
+  let v_4 = f4[1];
+  let v_5 = f5[2][2];
 }
 )";
 
     auto* expect = R"(
-struct S {
-  @internal(packed_vector)
-  v : vec3<f32>,
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
 }
 
-@group(0) @binding(0) var<storage, read_write> P : S;
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.v = vec3<f32>(in.v);
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
+  result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
 
 fn f() {
-  P.v.y = 1.23;
+  var f1 : S = tint_unpack_vec3_in_composite_3(P);
+  var f2 : vec3<f32> = vec3<f32>(P.v);
+  var f3 : mat3x3<f32> = tint_unpack_vec3_in_composite(P.m);
+  var f4 : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite_1(P.arr_v);
+  var f5 : array<mat3x3<f32>, 4> = tint_unpack_vec3_in_composite_2(P.arr_m);
+  let v_1 = f1.v;
+  let v_2 = f2;
+  let v_3 = f3[0];
+  let v_4 = f4[1];
+  let v_5 = f5[2][2];
 }
 )";
 
@@ -626,29 +6090,1998 @@
     EXPECT_EQ(expect, str(got));
 }
 
-TEST_F(PackedVec3Test, WriteIndexAccessor) {
+TEST_F(PackedVec3Test, MixedAddressSpace_InitFromLoad_InferredVarType) {
     auto* src = R"(
 struct S {
   v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
 }
 
-@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(0) var<storage> P : S;
 
 fn f() {
-  P.v[1] = 1.23;
+  var f1 = P;
+  var f2 = P.v;
+  var f3 = P.m;
+  var f4 = P.arr_v;
+  var f5 = P.arr_m;
+  let v_1 = f1.v;
+  let v_2 = f2;
+  let v_3 = f3[0];
+  let v_4 = f4[1];
+  let v_5 = f5[2][2];
 }
 )";
 
     auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.v = vec3<f32>(in.v);
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
+  result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
+  return result;
+}
+
 struct S {
-  @internal(packed_vector)
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  var f1 = tint_unpack_vec3_in_composite_3(P);
+  var f2 = vec3<f32>(P.v);
+  var f3 = tint_unpack_vec3_in_composite(P.m);
+  var f4 = tint_unpack_vec3_in_composite_1(P.arr_v);
+  var f5 = tint_unpack_vec3_in_composite_2(P.arr_m);
+  let v_1 = f1.v;
+  let v_2 = f2;
+  let v_3 = f3[0];
+  let v_4 = f4[1];
+  let v_5 = f5[2][2];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MixedAddressSpace_InitFromValue_ExplicitVarType) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  var f1 : S = S();
+  var f2 : vec3<f32> = vec3<f32>();
+  var f3 : mat3x3<f32> = mat3x3<f32>();
+  var f4 : array<vec3<f32>, 4> = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
+  var f5 : array<mat3x3<f32>, 4> = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
+  let v_1 = f1.v;
+  let v_2 = f2;
+  let v_3 = f3[0];
+  let v_4 = f4[1];
+  let v_5 = f5[2][2];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  var f1 : S = S();
+  var f2 : vec3<f32> = vec3<f32>();
+  var f3 : mat3x3<f32> = mat3x3<f32>();
+  var f4 : array<vec3<f32>, 4> = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
+  var f5 : array<mat3x3<f32>, 4> = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
+  let v_1 = f1.v;
+  let v_2 = f2;
+  let v_3 = f3[0];
+  let v_4 = f4[1];
+  let v_5 = f5[2][2];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MixedAddressSpace_InitFromValue_InferredVarType) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  var f1 = S();
+  var f2 = vec3<f32>();
+  var f3 = mat3x3<f32>();
+  var f4 = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
+  var f5 = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
+  let v_1 = f1.v;
+  let v_2 = f2;
+  let v_3 = f3[0];
+  let v_4 = f4[1];
+  let v_5 = f5[2][2];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  var f1 = S();
+  var f2 = vec3<f32>();
+  var f3 = mat3x3<f32>();
+  var f4 = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
+  var f5 = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
+  let v_1 = f1.v;
+  let v_2 = f2;
+  let v_3 = f3[0];
+  let v_4 = f4[1];
+  let v_5 = f5[2][2];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MixedAddressSpace_Pointers_Function) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+  var f1 : S = P;
+  var f2 : vec3<f32> = P.v;
+  var f3 : array<vec3<f32>, 4>;
+  var f4 : mat3x3<f32> = P.m;
+  let pv_1 : ptr<function, vec3<f32>> = &f1.v;
+  let pv_2 : ptr<function, vec3<f32>> = &f2;
+  let pv_3 : ptr<function, vec3<f32>> = &f3[0];
+  let pv_4 : ptr<function, mat3x3<f32>> = &f1.m;
+  let pv_5 : ptr<function, mat3x3<f32>> = &f4;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.v = vec3<f32>(in.v);
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+  var f1 : S = tint_unpack_vec3_in_composite_1(P);
+  var f2 : vec3<f32> = vec3<f32>(P.v);
+  var f3 : array<vec3<f32>, 4>;
+  var f4 : mat3x3<f32> = tint_unpack_vec3_in_composite(P.m);
+  let pv_1 : ptr<function, vec3<f32>> = &(f1.v);
+  let pv_2 : ptr<function, vec3<f32>> = &(f2);
+  let pv_3 : ptr<function, vec3<f32>> = &(f3[0]);
+  let pv_4 : ptr<function, mat3x3<f32>> = &(f1.m);
+  let pv_5 : ptr<function, mat3x3<f32>> = &(f4);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MixedAddressSpace_Pointers_Private) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+var<private> p1 : S;
+var<private> p2 : vec3<f32>;
+var<private> p3 : array<vec3<f32>, 4>;
+var<private> p4 : mat3x3<f32>;
+
+fn f() {
+  let pv_1 : ptr<private, vec3<f32>> = &p1.v;
+  let pv_2 : ptr<private, vec3<f32>> = &p2;
+  let pv_3 : ptr<private, vec3<f32>> = &p3[0];
+  let pv_4 : ptr<private, mat3x3<f32>> = &p1.m;
+  let pv_5 : ptr<private, mat3x3<f32>> = &p4;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+var<private> p1 : S;
+
+var<private> p2 : vec3<f32>;
+
+var<private> p3 : array<vec3<f32>, 4>;
+
+var<private> p4 : mat3x3<f32>;
+
+fn f() {
+  let pv_1 : ptr<private, vec3<f32>> = &(p1.v);
+  let pv_2 : ptr<private, vec3<f32>> = &(p2);
+  let pv_3 : ptr<private, vec3<f32>> = &(p3[0]);
+  let pv_4 : ptr<private, mat3x3<f32>> = &(p1.m);
+  let pv_5 : ptr<private, mat3x3<f32>> = &(p4);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MixedAddressSpace_Pointers_Workgroup) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+var<workgroup> w1 : S;
+var<workgroup> w2 : vec3<f32>;
+var<workgroup> w3 : array<vec3<f32>, 4>;
+var<workgroup> w4 : mat3x3<f32>;
+
+fn f() {
+  let pv_1 : ptr<workgroup, vec3<f32>> = &w1.v;
+  let pv_2 : ptr<workgroup, vec3<f32>> = &w2;
+  let pv_3 : ptr<workgroup, vec3<f32>> = &w3[0];
+  let pv_4 : ptr<workgroup, mat3x3<f32>> = &w1.m;
+  let pv_5 : ptr<workgroup, mat3x3<f32>> = &w4;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+var<workgroup> w1 : S;
+
+var<workgroup> w2 : vec3<f32>;
+
+var<workgroup> w3 : array<vec3<f32>, 4>;
+
+var<workgroup> w4 : mat3x3<f32>;
+
+fn f() {
+  let pv_1 : ptr<workgroup, vec3<f32>> = &(w1.v);
+  let pv_2 : ptr<workgroup, vec3<f32>> = &(w2);
+  let pv_3 : ptr<workgroup, vec3<f32>> = &(w3[0]);
+  let pv_4 : ptr<workgroup, mat3x3<f32>> = &(w1.m);
+  let pv_5 : ptr<workgroup, mat3x3<f32>> = &(w4);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MixedAddressSpace_PointerParameters) {
+    auto* src = R"(
+enable chromium_experimental_full_ptr_parameters;
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn g_v(p : ptr<function, vec3<f32>>) -> vec3<f32> {
+  return *p;
+}
+
+fn g_m(p : ptr<function, mat3x3<f32>>) -> mat3x3<f32> {
+  return *p;
+}
+
+fn f() {
+  var f1 : S = P;
+  var f2 : vec3<f32> = P.v;
+  var f3 : array<vec3<f32>, 4>;
+  var f4 : mat3x3<f32> = P.m;
+  g_v(&f1.v);
+  g_v(&f2);
+  g_v(&f3[0]);
+  g_m(&f1.m);
+  g_m(&f4);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+enable chromium_experimental_full_ptr_parameters;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.v = vec3<f32>(in.v);
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn g_v(p : ptr<function, vec3<f32>>) -> vec3<f32> {
+  return *(p);
+}
+
+fn g_m(p : ptr<function, mat3x3<f32>>) -> mat3x3<f32> {
+  return *(p);
+}
+
+fn f() {
+  var f1 : S = tint_unpack_vec3_in_composite_1(P);
+  var f2 : vec3<f32> = vec3<f32>(P.v);
+  var f3 : array<vec3<f32>, 4>;
+  var f4 : mat3x3<f32> = tint_unpack_vec3_in_composite(P.m);
+  g_v(&(f1.v));
+  g_v(&(f2));
+  g_v(&(f3[0]));
+  g_m(&(f1.m));
+  g_m(&(f4));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, WriteVec3Swizzle_FromRef) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
+
+fn f() {
+  v = v.zyx;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
+
+fn f() {
+  v = __packed_vec3<f32>(vec3<f32>(v).zyx);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, WriteVec3Swizzle_FromValue) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
+
+fn f() {
+  v = vec3f(1, 2, 3).zyx;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
+
+fn f() {
+  v = __packed_vec3<f32>(vec3f(1, 2, 3).zyx);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, WriteVec3Component_FromPackedValueIndexAccessor) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>
+}
+
+@group(0) @binding(0) var<storage, read_write> s : S;
+
+fn g() -> S {
+  return S();
+}
+
+fn f() {
+  s.v[0] = g().v[1];
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+struct S {
   v : vec3<f32>,
 }
 
-@group(0) @binding(0) var<storage, read_write> P : S;
+@group(0) @binding(0) var<storage, read_write> s : S_tint_packed_vec3;
+
+fn g() -> S {
+  return S();
+}
 
 fn f() {
-  P.v[1] = 1.23;
+  s.v[0] = g().v[1];
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ExtractVec3FromStructValueExpression) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S;
+
+fn f() {
+  var v_var : vec3<f32> = S().v;
+  let v_let : vec3<f32> = S().v;
+  v_var = S().v;
+  v_var = S().v * 2.0;
+  buffer = S(S().v);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+}
+
+fn tint_pack_vec3_in_composite(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.v = __packed_vec3<f32>(in.v);
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
+
+fn f() {
+  var v_var : vec3<f32> = S().v;
+  let v_let : vec3<f32> = S().v;
+  v_var = S().v;
+  v_var = (S().v * 2.0);
+  buffer = tint_pack_vec3_in_composite(S(S().v));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ExtractArrayOfVec3FromStructValueExpression) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S;
+
+fn f() {
+  var arr_var : array<vec3<f32>, 4> = S().arr;
+  let arr_let : array<vec3<f32>, 4> = S().arr;
+  arr_var = S().arr;
+  arr_var[0] = S().arr[0] * 2.0;
+  buffer = S(S().arr);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element, 4u>,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
+  var result : array<tint_packed_vec3_f32_array_element, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.arr = tint_pack_vec3_in_composite(in.arr);
+  return result;
+}
+
+struct S {
+  arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
+
+fn f() {
+  var arr_var : array<vec3<f32>, 4> = S().arr;
+  let arr_let : array<vec3<f32>, 4> = S().arr;
+  arr_var = S().arr;
+  arr_var[0] = (S().arr[0] * 2.0);
+  buffer = tint_pack_vec3_in_composite_1(S(S().arr));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ExtractNestedArrayFromStructValueExpression) {
+    auto* src = R"(
+struct S {
+  arr : array<array<vec3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S;
+
+fn f() {
+  var arr_var : array<array<vec3<f32>, 4>, 4> = S().arr;
+  var inner_var : array<vec3<f32>, 4> = S().arr[0];
+  let arr_let : array<array<vec3<f32>, 4>, 4> = S().arr;
+  arr_var = S().arr;
+  inner_var = S().arr[0];
+  arr_var[0][0] = S().arr[0][0] * 2.0;
+  buffer = S(S().arr);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
+  var result : array<tint_packed_vec3_f32_array_element, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : array<array<vec3<f32>, 4u>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 4u>, 4u> {
+  var result : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_pack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_2(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.arr = tint_pack_vec3_in_composite_1(in.arr);
+  return result;
+}
+
+struct S {
+  arr : array<array<vec3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
+
+fn f() {
+  var arr_var : array<array<vec3<f32>, 4>, 4> = S().arr;
+  var inner_var : array<vec3<f32>, 4> = S().arr[0];
+  let arr_let : array<array<vec3<f32>, 4>, 4> = S().arr;
+  arr_var = S().arr;
+  inner_var = S().arr[0];
+  arr_var[0][0] = (S().arr[0][0] * 2.0);
+  buffer = tint_pack_vec3_in_composite_2(S(S().arr));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ExtractMatrixFromStructValueExpression) {
+    auto* src = R"(
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S;
+
+fn f() {
+  var m_var : mat3x3<f32> = S().m;
+  let m_let : mat3x3<f32> = S().m;
+  m_var = S().m;
+  m_var = S().m * 2.0;
+  buffer = S(S().m);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.m = tint_pack_vec3_in_composite(in.m);
+  return result;
+}
+
+struct S {
+  m : mat3x3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
+
+fn f() {
+  var m_var : mat3x3<f32> = S().m;
+  let m_let : mat3x3<f32> = S().m;
+  m_var = S().m;
+  m_var = (S().m * 2.0);
+  buffer = tint_pack_vec3_in_composite_1(S(S().m));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ExtractArrayOfMatrixFromStructValueExpression) {
+    auto* src = R"(
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S;
+
+fn f() {
+  var arr_var : array<mat3x3<f32>, 4> = S().arr;
+  let arr_let : array<mat3x3<f32>, 4> = S().arr;
+  arr_var = S().arr;
+  arr_var[0] = S().arr[0] * 2.0;
+  buffer = S(S().arr);
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+  var result : array<tint_packed_vec3_f32_array_element, 3u>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
+  var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_pack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_pack_vec3_in_composite_2(in : S) -> S_tint_packed_vec3 {
+  var result : S_tint_packed_vec3;
+  result.arr = tint_pack_vec3_in_composite_1(in.arr);
+  return result;
+}
+
+struct S {
+  arr : array<mat3x3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
+
+fn f() {
+  var arr_var : array<mat3x3<f32>, 4> = S().arr;
+  let arr_let : array<mat3x3<f32>, 4> = S().arr;
+  arr_var = S().arr;
+  arr_var[0] = (S().arr[0] * 2.0);
+  buffer = tint_pack_vec3_in_composite_2(S(S().arr));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, NestedArrays_Let) {
+    auto* src = R"(
+struct S {
+  arr_v : array<array<vec3<f32>, 4>, 4>,
+  arr_m : array<array<mat3x3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 4>;
+
+fn f() {
+  let full_let : array<S, 4> = arr_s;
+  let struct_let : S = arr_s[0];
+  let outer_arr_v_let : array<array<vec3<f32>, 4>, 4> = arr_s[0].arr_v;
+  let inner_arr_v_let : array<vec3<f32>, 4> = arr_s[0].arr_v[1];
+  let v_let : vec3<f32> = arr_s[0].arr_v[1][2];
+  let v_element_let : f32 = arr_s[0].arr_v[1][2].y;
+  let outer_arr_m_let : array<array<mat3x3<f32>, 4>, 4> = arr_s[0].arr_m;
+  let inner_arr_m_let : array<mat3x3<f32>, 4> = arr_s[0].arr_m[1];
+  let m_let : mat3x3<f32> = arr_s[0].arr_m[1][2];
+  let m_col_let : vec3<f32> = arr_s[0].arr_m[1][2][0];
+  let m_element_let : f32 = arr_s[0].arr_m[1][2][0].y;
+}
+)";
+
+    auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
+  @align(16)
+  arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>) -> array<array<vec3<f32>, 4u>, 4u> {
+  var result : array<array<vec3<f32>, 4u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite_2(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>) -> array<array<mat3x3<f32>, 4u>, 4u> {
+  var result : array<array<mat3x3<f32>, 4u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_5(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
+  result.arr_m = tint_unpack_vec3_in_composite_4(in.arr_m);
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 4u>) -> array<S, 4u> {
+  var result : array<S, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite_5(in[i]);
+  }
+  return result;
+}
+
+struct S {
+  arr_v : array<array<vec3<f32>, 4>, 4>,
+  arr_m : array<array<mat3x3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 4u>;
+
+fn f() {
+  let full_let : array<S, 4> = tint_unpack_vec3_in_composite_6(arr_s);
+  let struct_let : S = tint_unpack_vec3_in_composite_5(arr_s[0]);
+  let outer_arr_v_let : array<array<vec3<f32>, 4>, 4> = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
+  let inner_arr_v_let : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
+  let v_let : vec3<f32> = vec3<f32>(arr_s[0].arr_v[1][2].elements);
+  let v_element_let : f32 = arr_s[0].arr_v[1][2].elements.y;
+  let outer_arr_m_let : array<array<mat3x3<f32>, 4>, 4> = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
+  let inner_arr_m_let : array<mat3x3<f32>, 4> = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
+  let m_let : mat3x3<f32> = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
+  let m_col_let : vec3<f32> = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
+  let m_element_let : f32 = arr_s[0].arr_m[1][2][0].elements.y;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, NestedArrays_VarInit) {
+    auto* src = R"(
+struct S {
+  arr_v : array<array<vec3<f32>, 4>, 4>,
+  arr_m : array<array<mat3x3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 4>;
+
+fn f() {
+  var full_var : array<S, 4> = arr_s;
+  var struct_var : S = arr_s[0];
+  var outer_arr_v_var : array<array<vec3<f32>, 4>, 4> = arr_s[0].arr_v;
+  var inner_arr_v_var : array<vec3<f32>, 4> = arr_s[0].arr_v[1];
+  var v_var : vec3<f32> = arr_s[0].arr_v[1][2];
+  var v_element_var : f32 = arr_s[0].arr_v[1][2].y;
+  var outer_arr_m_var : array<array<mat3x3<f32>, 4>, 4> = arr_s[0].arr_m;
+  var inner_arr_m_var : array<mat3x3<f32>, 4> = arr_s[0].arr_m[1];
+  var m_var : mat3x3<f32> = arr_s[0].arr_m[1][2];
+  var m_col_var : vec3<f32> = arr_s[0].arr_m[1][2][0];
+  var m_element_var : f32 = arr_s[0].arr_m[1][2][0].y;
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
+  @align(16)
+  arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>) -> array<array<vec3<f32>, 4u>, 4u> {
+  var result : array<array<vec3<f32>, 4u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite_2(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>) -> array<array<mat3x3<f32>, 4u>, 4u> {
+  var result : array<array<mat3x3<f32>, 4u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_5(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
+  result.arr_m = tint_unpack_vec3_in_composite_4(in.arr_m);
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 4u>) -> array<S, 4u> {
+  var result : array<S, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite_5(in[i]);
+  }
+  return result;
+}
+
+struct S {
+  arr_v : array<array<vec3<f32>, 4>, 4>,
+  arr_m : array<array<mat3x3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 4u>;
+
+fn f() {
+  var full_var : array<S, 4> = tint_unpack_vec3_in_composite_6(arr_s);
+  var struct_var : S = tint_unpack_vec3_in_composite_5(arr_s[0]);
+  var outer_arr_v_var : array<array<vec3<f32>, 4>, 4> = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
+  var inner_arr_v_var : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
+  var v_var : vec3<f32> = vec3<f32>(arr_s[0].arr_v[1][2].elements);
+  var v_element_var : f32 = arr_s[0].arr_v[1][2].elements.y;
+  var outer_arr_m_var : array<array<mat3x3<f32>, 4>, 4> = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
+  var inner_arr_m_var : array<mat3x3<f32>, 4> = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
+  var m_var : mat3x3<f32> = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
+  var m_col_var : vec3<f32> = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
+  var m_element_var : f32 = arr_s[0].arr_m[1][2][0].elements.y;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, NestedArrays_VarAssignment) {
+    auto* src = R"(
+struct S {
+  arr_v : array<array<vec3<f32>, 4>, 4>,
+  arr_m : array<array<mat3x3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 4>;
+
+fn f() {
+  var full_var : array<S, 4>;
+  var struct_var : S;
+  var outer_arr_v_var : array<array<vec3<f32>, 4>, 4>;
+  var inner_arr_v_var : array<vec3<f32>, 4>;
+  var v_var : vec3<f32>;
+  var v_element_var : f32;
+  var outer_arr_m_var : array<array<mat3x3<f32>, 4>, 4>;
+  var inner_arr_m_var : array<mat3x3<f32>, 4>;
+  var m_var : mat3x3<f32>;
+  var m_col_var : vec3<f32>;
+  var m_element_var : f32;
+
+  full_var = arr_s;
+  struct_var = arr_s[0];
+  outer_arr_v_var = arr_s[0].arr_v;
+  inner_arr_v_var = arr_s[0].arr_v[1];
+  v_var = arr_s[0].arr_v[1][2];
+  v_element_var = arr_s[0].arr_v[1][2].y;
+  outer_arr_m_var = arr_s[0].arr_m;
+  inner_arr_m_var = arr_s[0].arr_m[1];
+  m_var = arr_s[0].arr_m[1][2];
+  m_col_var = arr_s[0].arr_m[1][2][0];
+  m_element_var = arr_s[0].arr_m[1][2][0].y;
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
+  @align(16)
+  arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>) -> array<array<vec3<f32>, 4u>, 4u> {
+  var result : array<array<vec3<f32>, 4u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
+  var result : array<mat3x3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite_2(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>) -> array<array<mat3x3<f32>, 4u>, 4u> {
+  var result : array<array<mat3x3<f32>, 4u>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_5(in : S_tint_packed_vec3) -> S {
+  var result : S;
+  result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
+  result.arr_m = tint_unpack_vec3_in_composite_4(in.arr_m);
+  return result;
+}
+
+fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 4u>) -> array<S, 4u> {
+  var result : array<S, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = tint_unpack_vec3_in_composite_5(in[i]);
+  }
+  return result;
+}
+
+struct S {
+  arr_v : array<array<vec3<f32>, 4>, 4>,
+  arr_m : array<array<mat3x3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 4u>;
+
+fn f() {
+  var full_var : array<S, 4>;
+  var struct_var : S;
+  var outer_arr_v_var : array<array<vec3<f32>, 4>, 4>;
+  var inner_arr_v_var : array<vec3<f32>, 4>;
+  var v_var : vec3<f32>;
+  var v_element_var : f32;
+  var outer_arr_m_var : array<array<mat3x3<f32>, 4>, 4>;
+  var inner_arr_m_var : array<mat3x3<f32>, 4>;
+  var m_var : mat3x3<f32>;
+  var m_col_var : vec3<f32>;
+  var m_element_var : f32;
+  full_var = tint_unpack_vec3_in_composite_6(arr_s);
+  struct_var = tint_unpack_vec3_in_composite_5(arr_s[0]);
+  outer_arr_v_var = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
+  inner_arr_v_var = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
+  v_var = vec3<f32>(arr_s[0].arr_v[1][2].elements);
+  v_element_var = arr_s[0].arr_v[1][2].elements.y;
+  outer_arr_m_var = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
+  inner_arr_m_var = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
+  m_var = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
+  m_col_var = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
+  m_element_var = arr_s[0].arr_m[1][2][0].elements.y;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, RuntimeSizedArray) {
+    auto* src = R"(
+struct S {
+  arr : array<vec3<f32>>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_v : array<vec3<f32>>;
+@group(0) @binding(1) var<storage, read_write> s : S;
+
+fn main() {
+  s.arr[0] = arr_v[0];
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  arr : array<tint_packed_vec3_f32_array_element>,
+}
+
+struct S {
+  arr : array<vec3<f32>>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element>;
+
+@group(0) @binding(1) var<storage, read_write> s : S_tint_packed_vec3;
+
+fn main() {
+  s.arr[0].elements = arr_v[0].elements;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Mat3x3_F16_Uniform) {
+    // Test that array element alignment validation rules do not trigger when we rewrite an f16
+    // matrix into an array of vec3s in uniform storage.
+    auto* src = R"(
+enable f16;
+enable chromium_experimental_full_ptr_parameters;
+
+@group(0) @binding(0) var<uniform> m : mat3x3<f16>;
+
+fn g(p : ptr<uniform, mat3x3<f16>>) -> vec3<f16> {
+  return (*p)[0] + vec3<f16>(1);
+}
+
+fn f() {
+  let v = g(&m);
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+enable f16;
+enable chromium_experimental_full_ptr_parameters;
+
+struct tint_packed_vec3_f16_array_element {
+  @align(8)
+  elements : __packed_vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> m : array<tint_packed_vec3_f16_array_element, 3u>;
+
+fn g(p : ptr<uniform, array<tint_packed_vec3_f16_array_element, 3u>>) -> vec3<f16> {
+  return (vec3<f16>((*(p))[0].elements) + vec3<f16>(1));
+}
+
+fn f() {
+  let v = g(&(m));
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MultipleComponentTypes_StructMembers) {
+    auto* src = R"(
+enable f16;
+
+struct S {
+  f : vec3f,
+  h : vec3h,
+  i : vec3i,
+  u : vec3u,
+}
+
+@group(0) @binding(0) var<storage, read_write> s : S;
+
+fn f() {
+  let f = s.f;
+  let h = s.h;
+  let i = s.i;
+  let u = s.u;
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+enable f16;
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  f : __packed_vec3<f32>,
+  @align(8)
+  h : __packed_vec3<f16>,
+  @align(16)
+  i : __packed_vec3<i32>,
+  @align(16)
+  u : __packed_vec3<u32>,
+}
+
+struct S {
+  f : vec3f,
+  h : vec3h,
+  i : vec3i,
+  u : vec3u,
+}
+
+@group(0) @binding(0) var<storage, read_write> s : S_tint_packed_vec3;
+
+fn f() {
+  let f = vec3<f32>(s.f);
+  let h = vec3<f16>(s.h);
+  let i = vec3<i32>(s.i);
+  let u = vec3<u32>(s.u);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MultipleComponentTypes_ArrayElement) {
+    auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<storage, read_write> arr_f : array<vec3f>;
+@group(0) @binding(1) var<storage, read_write> arr_h : array<vec3h>;
+@group(0) @binding(2) var<storage, read_write> arr_i : array<vec3i>;
+@group(0) @binding(3) var<storage, read_write> arr_u : array<vec3u>;
+
+fn main() {
+  let f = arr_f[0];
+  let h = arr_h[0];
+  let i = arr_i[0];
+  let u = arr_u[0];
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+enable f16;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct tint_packed_vec3_f16_array_element {
+  @align(8)
+  elements : __packed_vec3<f16>,
+}
+
+struct tint_packed_vec3_i32_array_element {
+  @align(16)
+  elements : __packed_vec3<i32>,
+}
+
+struct tint_packed_vec3_u32_array_element {
+  @align(16)
+  elements : __packed_vec3<u32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_f : array<tint_packed_vec3_f32_array_element>;
+
+@group(0) @binding(1) var<storage, read_write> arr_h : array<tint_packed_vec3_f16_array_element>;
+
+@group(0) @binding(2) var<storage, read_write> arr_i : array<tint_packed_vec3_i32_array_element>;
+
+@group(0) @binding(3) var<storage, read_write> arr_u : array<tint_packed_vec3_u32_array_element>;
+
+fn main() {
+  let f = vec3<f32>(arr_f[0].elements);
+  let h = vec3<f16>(arr_h[0].elements);
+  let i = vec3<i32>(arr_i[0].elements);
+  let u = vec3<u32>(arr_u[0].elements);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Arithmetic_FromRef) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> buffer_v : vec3<f32>;
+@group(0) @binding(1) var<storage, read_write> buffer_m : mat3x3<f32>;
+@group(0) @binding(2) var<storage, read_write> buffer_arr_v : array<vec3<f32>, 4>;
+@group(0) @binding(3) var<storage, read_write> buffer_arr_m : array<mat3x3<f32>, 4>;
+@group(0) @binding(4) var<storage, read_write> buffer_nested_arr_v : array<array<vec3<f32>, 4>, 4>;
+
+fn f() {
+  var v : vec3<f32> = buffer_v * 2;
+  v = -v;
+  v = buffer_m * v;
+  v = buffer_m[0] + v;
+  v = buffer_arr_v[0] + v;
+  v = buffer_arr_m[0] * v;
+  v = buffer_arr_m[0][1] + v;
+  v = buffer_nested_arr_v[0][0] + v;
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer_v : __packed_vec3<f32>;
+
+@group(0) @binding(1) var<storage, read_write> buffer_m : array<tint_packed_vec3_f32_array_element, 3u>;
+
+@group(0) @binding(2) var<storage, read_write> buffer_arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
+
+@group(0) @binding(3) var<storage, read_write> buffer_arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(4) var<storage, read_write> buffer_nested_arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>;
+
+fn f() {
+  var v : vec3<f32> = (vec3<f32>(buffer_v) * 2);
+  v = -(v);
+  v = (tint_unpack_vec3_in_composite(buffer_m) * v);
+  v = (vec3<f32>(buffer_m[0].elements) + v);
+  v = (vec3<f32>(buffer_arr_v[0].elements) + v);
+  v = (tint_unpack_vec3_in_composite(buffer_arr_m[0]) * v);
+  v = (vec3<f32>(buffer_arr_m[0][1].elements) + v);
+  v = (vec3<f32>(buffer_nested_arr_v[0][0].elements) + v);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Arithmetic_FromValue) {
+    auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> buffer_v : vec3f;
+
+fn f() {
+  var v : vec3f = buffer_v;
+  v = -vec3f(1, 2, 3);
+  v = mat3x3f() * v;
+  v = mat3x3f()[0] + v;
+  v = array<vec3f, 4>()[0] + v;
+  v = array<mat3x3f, 4>()[0] * v;
+  v = array<mat3x3f, 4>()[0][1] + v;
+  v = array<array<vec3f, 4>, 4>()[0][0] + v;
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+@group(0) @binding(0) var<storage, read_write> buffer_v : __packed_vec3<f32>;
+
+fn f() {
+  var v : vec3f = vec3<f32>(buffer_v);
+  v = -(vec3f(1, 2, 3));
+  v = (mat3x3f() * v);
+  v = (mat3x3f()[0] + v);
+  v = (array<vec3f, 4>()[0] + v);
+  v = (array<mat3x3f, 4>()[0] * v);
+  v = (array<mat3x3f, 4>()[0][1] + v);
+  v = (array<array<vec3f, 4>, 4>()[0][0] + v);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Arithmetic_FromRefStruct) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+  nested_arr_v : array<array<vec3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S;
+
+fn f() {
+  var v : vec3<f32> = buffer.v * 2;
+  v = -v;
+  v = buffer.m * v;
+  v = buffer.m[0] + v;
+  v = buffer.arr_v[0] + v;
+  v = buffer.arr_m[0] * v;
+  v = buffer.arr_m[0][1] + v;
+  v = buffer.nested_arr_v[0][0] + v;
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+  @align(16)
+  nested_arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+  var result : mat3x3<f32>;
+  for(var i : u32; (i < 3u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+  nested_arr_v : array<array<vec3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
+
+fn f() {
+  var v : vec3<f32> = (vec3<f32>(buffer.v) * 2);
+  v = -(v);
+  v = (tint_unpack_vec3_in_composite(buffer.m) * v);
+  v = (vec3<f32>(buffer.m[0].elements) + v);
+  v = (vec3<f32>(buffer.arr_v[0].elements) + v);
+  v = (tint_unpack_vec3_in_composite(buffer.arr_m[0]) * v);
+  v = (vec3<f32>(buffer.arr_m[0][1].elements) + v);
+  v = (vec3<f32>(buffer.nested_arr_v[0][0].elements) + v);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Arithmetic_FromValueStruct) {
+    auto* src = R"(
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+  nested_arr_v : array<array<vec3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S;
+
+fn f() {
+  var v : vec3<f32> = S().v;
+  v = -S().v;
+  v = S().m * v;
+  v = S().m[0] + v;
+  v = S().arr_v[0] + v;
+  v = S().arr_m[0] * v;
+  v = S().arr_m[0][1] + v;
+  v = S().nested_arr_v[0][0] + v;
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : __packed_vec3<f32>,
+  @align(16)
+  m : array<tint_packed_vec3_f32_array_element, 3u>,
+  @align(16)
+  arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+  @align(16)
+  nested_arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
+}
+
+struct S {
+  v : vec3<f32>,
+  m : mat3x3<f32>,
+  arr_v : array<vec3<f32>, 4>,
+  arr_m : array<mat3x3<f32>, 4>,
+  nested_arr_v : array<array<vec3<f32>, 4>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
+
+fn f() {
+  var v : vec3<f32> = S().v;
+  v = -(S().v);
+  v = (S().m * v);
+  v = (S().m[0] + v);
+  v = (S().arr_v[0] + v);
+  v = (S().arr_m[0] * v);
+  v = (S().arr_m[0][1] + v);
+  v = (S().nested_arr_v[0][0] + v);
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Aliases) {
+    auto* src = R"(
+alias VecArray = array<vec3<f32>, 4>;
+alias MatArray = array<mat3x3<f32>, 4>;
+alias NestedArray = array<VecArray, 4>;
+
+struct S {
+  v : VecArray,
+  m : MatArray,
+  n : NestedArray,
+}
+
+@group(0) @binding(0) var<storage, read_write> s : S;
+@group(0) @binding(1) var<storage, read_write> arr_v : VecArray;
+@group(0) @binding(2) var<storage, read_write> arr_m : MatArray;
+@group(0) @binding(3) var<storage, read_write> arr_n : NestedArray;
+
+fn g(p : ptr<function, VecArray>) {
+}
+
+fn f() {
+  var f_arr_v : VecArray = s.v;
+  g(&f_arr_v);
+
+  arr_v = s.v;
+  arr_m[0] = s.m[0];
+  arr_n[1][2] = s.n[1][2];
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+  @align(16)
+  elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+  @align(16)
+  v : array<tint_packed_vec3_f32_array_element, 4u>,
+  @align(16)
+  m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+  @align(16)
+  n : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
+  var result : array<vec3<f32>, 4u>;
+  for(var i : u32; (i < 4u); i = (i + 1)) {
+    result[i] = vec3<f32>(in[i].elements);
+  }
+  return result;
+}
+
+alias VecArray = array<vec3<f32>, 4>;
+
+alias MatArray = array<mat3x3<f32>, 4>;
+
+alias NestedArray = array<VecArray, 4>;
+
+struct S {
+  v : VecArray,
+  m : MatArray,
+  n : NestedArray,
+}
+
+@group(0) @binding(0) var<storage, read_write> s : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
+
+@group(0) @binding(2) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+@group(0) @binding(3) var<storage, read_write> arr_n : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>;
+
+fn g(p : ptr<function, VecArray>) {
+}
+
+fn f() {
+  var f_arr_v : VecArray = tint_unpack_vec3_in_composite(s.v);
+  g(&(f_arr_v));
+  arr_v = s.v;
+  arr_m[0] = s.m[0];
+  arr_n[1][2].elements = s.n[1][2].elements;
+}
+)";
+
+    DataMap data;
+    auto got = Run<PackedVec3>(src, data);
+
+    EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, Vec3Bool) {
+    // Make sure that we don't rewrite vec3<bool> types, as the `packed_bool<n>` types are reserved
+    // in MSL and might not be supported everywhere.
+    auto* src = R"(
+struct S {
+  vf : vec3<f32>,
+  af : array<vec3<f32>, 4>,
+  vb : vec3<bool>,
+  ab : array<vec3<bool>, 4>,
+}
+
+// Create a vec3 storage buffer so that the transform is not skipped.
+@group(0) @binding(0) var<storage, read_write> buffer : vec3<f32>;
+
+fn f() {
+  var f : S;
+  f.vf = buffer;
+  buffer = f.af[0];
+}
+)";
+
+    auto* expect =
+        R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct S {
+  vf : vec3<f32>,
+  af : array<vec3<f32>, 4>,
+  vb : vec3<bool>,
+  ab : array<vec3<bool>, 4>,
+}
+
+@group(0) @binding(0) var<storage, read_write> buffer : __packed_vec3<f32>;
+
+fn f() {
+  var f : S;
+  f.vf = vec3<f32>(buffer);
+  buffer = __packed_vec3<f32>(f.af[0]);
 }
 )";
 
diff --git a/src/tint/transform/renamer_test.cc b/src/tint/transform/renamer_test.cc
index 8ff6898..fc34251 100644
--- a/src/tint/transform/renamer_test.cc
+++ b/src/tint/transform/renamer_test.cc
@@ -1714,7 +1714,7 @@
     for (auto* ty : builtin::kBuiltinStrings) {
         std::string_view type(ty);
         if (type != "ptr" && type != "atomic" && !utils::HasPrefix(type, "sampler") &&
-            !utils::HasPrefix(type, "texture")) {
+            !utils::HasPrefix(type, "texture") && !utils::HasPrefix(type, "__")) {
             out.push_back(ty);
         }
     }
@@ -1924,7 +1924,9 @@
 std::vector<const char*> Identifiers() {
     std::vector<const char*> out;
     for (auto* ident : builtin::kBuiltinStrings) {
-        out.push_back(ident);
+        if (!utils::HasPrefix(ident, "__")) {
+            out.push_back(ident);
+        }
     }
     for (auto* ident : builtin::kAddressSpaceStrings) {
         if (!utils::HasPrefix(ident, "_")) {
diff --git a/src/tint/transform/transform.cc b/src/tint/transform/transform.cc
index cc09e6c..ad954ee 100644
--- a/src/tint/transform/transform.cc
+++ b/src/tint/transform/transform.cc
@@ -17,6 +17,7 @@
 #include <algorithm>
 #include <string>
 
+#include "src/tint/builtin/builtin.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/sem/block_statement.h"
 #include "src/tint/sem/for_loop_statement.h"
@@ -98,7 +99,12 @@
     }
     if (auto* v = ty->As<type::Vector>()) {
         auto el = CreateASTTypeFor(ctx, v->type());
-        return ctx.dst->ty.vec(el, v->Width());
+        if (v->Packed()) {
+            TINT_ASSERT(Transform, v->Width() == 3u);
+            return ctx.dst->ty(builtin::Builtin::kPackedVec3, el);
+        } else {
+            return ctx.dst->ty.vec(el, v->Width());
+        }
     }
     if (auto* a = ty->As<type::Array>()) {
         auto el = CreateASTTypeFor(ctx, a->ElemType());
diff --git a/src/tint/type/vector.cc b/src/tint/type/vector.cc
index 146c1f4..6db1465 100644
--- a/src/tint/type/vector.cc
+++ b/src/tint/type/vector.cc
@@ -23,15 +23,16 @@
 
 namespace tint::type {
 
-Vector::Vector(Type const* subtype, uint32_t width)
-    : Base(utils::Hash(TypeInfo::Of<Vector>().full_hashcode, width, subtype),
+Vector::Vector(Type const* subtype, uint32_t width, bool packed /* = false */)
+    : Base(utils::Hash(TypeInfo::Of<Vector>().full_hashcode, width, subtype, packed),
            type::Flags{
                Flag::kConstructable,
                Flag::kCreationFixedFootprint,
                Flag::kFixedFootprint,
            }),
       subtype_(subtype),
-      width_(width) {
+      width_(width),
+      packed_(packed) {
     TINT_ASSERT(Type, width_ > 1);
     TINT_ASSERT(Type, width_ < 5);
 }
@@ -40,13 +41,16 @@
 
 bool Vector::Equals(const UniqueNode& other) const {
     if (auto* v = other.As<Vector>()) {
-        return v->width_ == width_ && v->subtype_ == subtype_;
+        return v->width_ == width_ && v->subtype_ == subtype_ && v->packed_ == packed_;
     }
     return false;
 }
 
 std::string Vector::FriendlyName(const SymbolTable& symbols) const {
     std::ostringstream out;
+    if (packed_) {
+        out << "__packed_";
+    }
     out << "vec" << width_ << "<" << subtype_->FriendlyName(symbols) << ">";
     return out.str();
 }
@@ -60,7 +64,7 @@
         case 2:
             return subtype_->Size() * 2;
         case 3:
-            return subtype_->Size() * 4;
+            return subtype_->Size() * (packed_ ? 1 : 4);
         case 4:
             return subtype_->Size() * 4;
     }
@@ -69,7 +73,7 @@
 
 Vector* Vector::Clone(CloneContext& ctx) const {
     auto* subtype = subtype_->Clone(ctx);
-    return ctx.dst.mgr->Get<Vector>(subtype, width_);
+    return ctx.dst.mgr->Get<Vector>(subtype, width_, packed_);
 }
 
 }  // namespace tint::type
diff --git a/src/tint/type/vector.h b/src/tint/type/vector.h
index acffb8c..e7fd881 100644
--- a/src/tint/type/vector.h
+++ b/src/tint/type/vector.h
@@ -22,12 +22,13 @@
 namespace tint::type {
 
 /// A vector type.
-class Vector final : public Castable<Vector, Type> {
+class Vector : public Castable<Vector, Type> {
   public:
     /// Constructor
     /// @param subtype the vector element type
     /// @param size the number of elements in the vector
-    Vector(Type const* subtype, uint32_t size);
+    /// @param packed the optional 'packed' modifier
+    Vector(Type const* subtype, uint32_t size, bool packed = false);
 
     /// Destructor
     ~Vector() override;
@@ -50,10 +51,12 @@
     /// @returns the size in bytes of the type. This may include tail padding.
     uint32_t Size() const override;
 
-    /// @returns the alignment in bytes of the type. This may include tail
-    /// padding.
+    /// @returns the alignment in bytes of the type. This may include tail padding.
     uint32_t Align() const override;
 
+    /// @returns `true` if this vector is packed, false otherwise
+    bool Packed() const { return packed_; }
+
     /// @param width the width of the vector
     /// @returns the size in bytes of a vector of the given width.
     static uint32_t SizeOf(uint32_t width);
@@ -69,6 +72,7 @@
   private:
     Type const* const subtype_;
     const uint32_t width_;
+    const bool packed_;
 };
 
 }  // namespace tint::type
diff --git a/src/tint/type/vector_test.cc b/src/tint/type/vector_test.cc
index 7dd5c9d..acc62ed 100644
--- a/src/tint/type/vector_test.cc
+++ b/src/tint/type/vector_test.cc
@@ -34,6 +34,21 @@
     EXPECT_NE(a, d);
 }
 
+TEST_F(VectorTest, Creation_Packed) {
+    auto* v = create<Vector>(create<F32>(), 3u);
+    auto* p1 = create<Vector>(create<F32>(), 3u, true);
+    auto* p2 = create<Vector>(create<F32>(), 3u, true);
+
+    EXPECT_FALSE(v->Packed());
+
+    EXPECT_EQ(p1->type(), create<F32>());
+    EXPECT_EQ(p1->Width(), 3u);
+    EXPECT_TRUE(p1->Packed());
+
+    EXPECT_NE(v, p1);
+    EXPECT_EQ(p1, p2);
+}
+
 TEST_F(VectorTest, Hash) {
     auto* a = create<Vector>(create<I32>(), 2u);
     auto* b = create<Vector>(create<I32>(), 2u);
@@ -59,6 +74,12 @@
     EXPECT_EQ(v->FriendlyName(Symbols()), "vec3<f32>");
 }
 
+TEST_F(VectorTest, FriendlyName_Packed) {
+    auto* f32 = create<F32>();
+    auto* v = create<Vector>(f32, 3u, true);
+    EXPECT_EQ(v->FriendlyName(Symbols()), "__packed_vec3<f32>");
+}
+
 TEST_F(VectorTest, Clone) {
     auto* a = create<Vector>(create<I32>(), 2u);
 
@@ -68,6 +89,19 @@
     auto* vec = a->Clone(ctx);
     EXPECT_TRUE(vec->type()->Is<I32>());
     EXPECT_EQ(vec->Width(), 2u);
+    EXPECT_FALSE(vec->Packed());
+}
+
+TEST_F(VectorTest, Clone_Packed) {
+    auto* a = create<Vector>(create<I32>(), 3u, true);
+
+    type::Manager mgr;
+    type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
+
+    auto* vec = a->Clone(ctx);
+    EXPECT_TRUE(vec->type()->Is<I32>());
+    EXPECT_EQ(vec->Width(), 3u);
+    EXPECT_TRUE(vec->Packed());
 }
 
 }  // namespace
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index c433207..c166f5f 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -245,8 +245,9 @@
     // ArrayLengthFromUniform must come after SimplifyPointers, as
     // it assumes that the form of the array length argument is &var.array.
     manager.Add<transform::ArrayLengthFromUniform>();
-    manager.Add<transform::ModuleScopeVarToEntryPointParam>();
+    // PackedVec3 must come after ExpandCompoundAssignment.
     manager.Add<transform::PackedVec3>();
+    manager.Add<transform::ModuleScopeVarToEntryPointParam>();
     data.Add<transform::ArrayLengthFromUniform::Config>(std::move(array_length_from_uniform_cfg));
     data.Add<transform::CanonicalizeEntryPointIO::Config>(std::move(entry_point_io_cfg));
     auto out = manager.Run(in, data);
@@ -273,6 +274,7 @@
                                       builtin::Extension::kChromiumDisableUniformityAnalysis,
                                       builtin::Extension::kChromiumExperimentalFullPtrParameters,
                                       builtin::Extension::kChromiumExperimentalPushConstant,
+                                      builtin::Extension::kChromiumInternalRelaxedUniformLayout,
                                       builtin::Extension::kF16,
                                   })) {
         return false;
@@ -2374,25 +2376,20 @@
     return Switch(
         sem,
         [&](const sem::Swizzle* swizzle) {
-            // Metal 1.x does not support swizzling of packed vector types.
-            // For single element swizzles, we can use the index operator.
-            // For multi-element swizzles, we need to cast to a regular vector type
-            // first. Note that we do not currently allow assignments to swizzles, so
-            // the casting which will convert the l-value to r-value is fine.
+            // Metal did not add support for swizzle syntax with packed vector types until
+            // Metal 2.1, so we need to use the index operator for single-element selection instead.
+            // For multi-component swizzles, the PackedVec3 transform will have inserted casts to
+            // the non-packed types, so we can safely use swizzle syntax here.
             if (swizzle->Indices().Length() == 1) {
                 if (!write_lhs()) {
                     return false;
                 }
                 out << "[" << swizzle->Indices()[0] << "]";
             } else {
-                if (!EmitType(out, swizzle->Object()->Type()->UnwrapRef(), "")) {
-                    return false;
-                }
-                out << "(";
                 if (!write_lhs()) {
                     return false;
                 }
-                out << ")." << program_->Symbols().NameFor(expr->member->symbol);
+                out << "." << program_->Symbols().NameFor(expr->member->symbol);
             }
             return true;
         },
@@ -2731,6 +2728,9 @@
             return true;
         },
         [&](const type::Vector* vec) {
+            if (vec->Packed()) {
+                out << "packed_";
+            }
             if (!EmitType(out, vec->type(), "")) {
                 return false;
             }
@@ -2838,11 +2838,6 @@
             add_byte_offset_comment(out, msl_offset);
         }
 
-        if (auto* decl = mem->Declaration()) {
-            if (ast::HasAttribute<transform::PackedVec3::Attribute>(decl->attributes)) {
-                out << "packed_";
-            }
-        }
         if (!EmitType(out, mem->Type(), mem_name)) {
             return false;
         }
@@ -2924,7 +2919,6 @@
                     [&](const ast::StructMemberOffsetAttribute*) { return true; },
                     [&](const ast::StructMemberAlignAttribute*) { return true; },
                     [&](const ast::StructMemberSizeAttribute*) { return true; },
-                    [&](const transform::PackedVec3::Attribute*) { return true; },
                     [&](Default) {
                         TINT_ICE(Writer, diagnostics_)
                             << "unhandled struct member attribute: " << attr->Name();
diff --git a/src/tint/writer/msl/generator_impl_member_accessor_test.cc b/src/tint/writer/msl/generator_impl_member_accessor_test.cc
index 1e1136e..d0cd219 100644
--- a/src/tint/writer/msl/generator_impl_member_accessor_test.cc
+++ b/src/tint/writer/msl/generator_impl_member_accessor_test.cc
@@ -41,7 +41,7 @@
     GeneratorImpl& gen = Build();
     std::stringstream out;
     ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
-    EXPECT_EQ(out.str(), "float4(my_vec).xyz");
+    EXPECT_EQ(out.str(), "my_vec.xyz");
 }
 
 TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor_Swizzle_gbr) {
@@ -53,7 +53,7 @@
     GeneratorImpl& gen = Build();
     std::stringstream out;
     ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
-    EXPECT_EQ(out.str(), "float4(my_vec).gbr");
+    EXPECT_EQ(out.str(), "my_vec.gbr");
 }
 
 }  // namespace
diff --git a/test/tint/access/let/vector.wgsl.expected.msl b/test/tint/access/let/vector.wgsl.expected.msl
index 13a9b75..2c7a0d5 100644
--- a/test/tint/access/let/vector.wgsl.expected.msl
+++ b/test/tint/access/let/vector.wgsl.expected.msl
@@ -4,8 +4,8 @@
 kernel void tint_symbol() {
   float3 const v = float3(1.0f, 2.0f, 3.0f);
   float const scalar = v[1];
-  float2 const swizzle2 = float3(v).xz;
-  float3 const swizzle3 = float3(v).xzy;
+  float2 const swizzle2 = v.xz;
+  float3 const swizzle3 = v.xzy;
   return;
 }
 
diff --git a/test/tint/access/var/vector.wgsl.expected.msl b/test/tint/access/var/vector.wgsl.expected.msl
index e965ea7..270c842 100644
--- a/test/tint/access/var/vector.wgsl.expected.msl
+++ b/test/tint/access/var/vector.wgsl.expected.msl
@@ -4,8 +4,8 @@
 kernel void tint_symbol() {
   float3 v = 0.0f;
   float const scalar = v[1];
-  float2 const swizzle2 = float3(v).xz;
-  float3 const swizzle3 = float3(v).xzy;
+  float2 const swizzle2 = v.xz;
+  float3 const swizzle3 = v.xzy;
   return;
 }
 
diff --git a/test/tint/buffer/storage/dynamic_index/read.wgsl.expected.msl b/test/tint/buffer/storage/dynamic_index/read.wgsl.expected.msl
index 06cc9d2..48bc0ff 100644
--- a/test/tint/buffer/storage/dynamic_index/read.wgsl.expected.msl
+++ b/test/tint/buffer/storage/dynamic_index/read.wgsl.expected.msl
@@ -14,42 +14,108 @@
     T elements[N];
 };
 
-struct Inner {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct Inner_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
-  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad_1;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
-  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_2;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_3;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0060 */ float4 vec4_f32;
   /* 0x0070 */ int4 vec4_i32;
   /* 0x0080 */ uint4 vec4_u32;
   /* 0x0090 */ float2x2 mat2x2_f32;
-  /* 0x00a0 */ float2x3 mat2x3_f32;
+  /* 0x00a0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00c0 */ float2x4 mat2x4_f32;
   /* 0x00e0 */ float3x2 mat3x2_f32;
-  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_5;
-  /* 0x0100 */ float3x3 mat3x3_f32;
+  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_6;
+  /* 0x0100 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0130 */ float3x4 mat3x4_f32;
   /* 0x0160 */ float4x2 mat4x2_f32;
-  /* 0x0180 */ float4x3 mat4x3_f32;
+  /* 0x0180 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01c0 */ float4x4 mat4x4_f32;
-  /* 0x0200 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x0200 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
+};
+
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 1> arr;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float3x3 tint_unpack_vec3_in_composite_1(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float4x3 tint_unpack_vec3_in_composite_2(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3, 2> tint_unpack_vec3_in_composite_3(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  tint_array<float3, 2> result = {};
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  tint_array<float3, 2> arr2_vec3_f32;
 };
 
 struct S {
-  /* 0x0000 */ tint_array<Inner, 1> arr;
+  tint_array<Inner, 1> arr;
 };
 
-void tint_symbol_inner(uint idx, const device S* const tint_symbol_1) {
+void tint_symbol_inner(uint idx, const device S_tint_packed_vec3* const tint_symbol_1) {
   float const scalar_f32 = (*(tint_symbol_1)).arr[idx].scalar_f32;
   int const scalar_i32 = (*(tint_symbol_1)).arr[idx].scalar_i32;
   uint const scalar_u32 = (*(tint_symbol_1)).arr[idx].scalar_u32;
@@ -63,18 +129,18 @@
   int4 const vec4_i32 = (*(tint_symbol_1)).arr[idx].vec4_i32;
   uint4 const vec4_u32 = (*(tint_symbol_1)).arr[idx].vec4_u32;
   float2x2 const mat2x2_f32 = (*(tint_symbol_1)).arr[idx].mat2x2_f32;
-  float2x3 const mat2x3_f32 = (*(tint_symbol_1)).arr[idx].mat2x3_f32;
+  float2x3 const mat2x3_f32 = tint_unpack_vec3_in_composite((*(tint_symbol_1)).arr[idx].mat2x3_f32);
   float2x4 const mat2x4_f32 = (*(tint_symbol_1)).arr[idx].mat2x4_f32;
   float3x2 const mat3x2_f32 = (*(tint_symbol_1)).arr[idx].mat3x2_f32;
-  float3x3 const mat3x3_f32 = (*(tint_symbol_1)).arr[idx].mat3x3_f32;
+  float3x3 const mat3x3_f32 = tint_unpack_vec3_in_composite_1((*(tint_symbol_1)).arr[idx].mat3x3_f32);
   float3x4 const mat3x4_f32 = (*(tint_symbol_1)).arr[idx].mat3x4_f32;
   float4x2 const mat4x2_f32 = (*(tint_symbol_1)).arr[idx].mat4x2_f32;
-  float4x3 const mat4x3_f32 = (*(tint_symbol_1)).arr[idx].mat4x3_f32;
+  float4x3 const mat4x3_f32 = tint_unpack_vec3_in_composite_2((*(tint_symbol_1)).arr[idx].mat4x3_f32);
   float4x4 const mat4x4_f32 = (*(tint_symbol_1)).arr[idx].mat4x4_f32;
-  tint_array<float3, 2> const arr2_vec3_f32 = (*(tint_symbol_1)).arr[idx].arr2_vec3_f32;
+  tint_array<float3, 2> const arr2_vec3_f32 = tint_unpack_vec3_in_composite_3((*(tint_symbol_1)).arr[idx].arr2_vec3_f32);
 }
 
-kernel void tint_symbol(const device S* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
+kernel void tint_symbol(const device S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
   tint_symbol_inner(idx, tint_symbol_2);
   return;
 }
diff --git a/test/tint/buffer/storage/dynamic_index/read_f16.wgsl.expected.msl b/test/tint/buffer/storage/dynamic_index/read_f16.wgsl.expected.msl
index ee0138a..0acb114 100644
--- a/test/tint/buffer/storage/dynamic_index/read_f16.wgsl.expected.msl
+++ b/test/tint/buffer/storage/dynamic_index/read_f16.wgsl.expected.msl
@@ -14,60 +14,169 @@
     T elements[N];
 };
 
-struct Inner {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad_1;
+};
+
+struct Inner_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
   /* 0x000c */ half scalar_f16;
-  /* 0x000e */ tint_array<int8_t, 2> tint_pad;
+  /* 0x000e */ tint_array<int8_t, 2> tint_pad_2;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
   /* 0x0028 */ half2 vec2_f16;
-  /* 0x002c */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x002c */ tint_array<int8_t, 4> tint_pad_3;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_6;
   /* 0x0060 */ packed_half3 vec3_f16;
-  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_5;
+  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_7;
   /* 0x0070 */ float4 vec4_f32;
   /* 0x0080 */ int4 vec4_i32;
   /* 0x0090 */ uint4 vec4_u32;
   /* 0x00a0 */ half4 vec4_f16;
   /* 0x00a8 */ float2x2 mat2x2_f32;
-  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_6;
-  /* 0x00c0 */ float2x3 mat2x3_f32;
+  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_8;
+  /* 0x00c0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00e0 */ float2x4 mat2x4_f32;
   /* 0x0100 */ float3x2 mat3x2_f32;
-  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_7;
-  /* 0x0120 */ float3x3 mat3x3_f32;
+  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_9;
+  /* 0x0120 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0150 */ float3x4 mat3x4_f32;
   /* 0x0180 */ float4x2 mat4x2_f32;
-  /* 0x01a0 */ float4x3 mat4x3_f32;
+  /* 0x01a0 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01e0 */ float4x4 mat4x4_f32;
   /* 0x0220 */ half2x2 mat2x2_f16;
-  /* 0x0228 */ half2x3 mat2x3_f16;
+  /* 0x0228 */ tint_array<tint_packed_vec3_f16_array_element, 2> mat2x3_f16;
   /* 0x0238 */ half2x4 mat2x4_f16;
   /* 0x0248 */ half3x2 mat3x2_f16;
-  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_8;
-  /* 0x0258 */ half3x3 mat3x3_f16;
+  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_10;
+  /* 0x0258 */ tint_array<tint_packed_vec3_f16_array_element, 3> mat3x3_f16;
   /* 0x0270 */ half3x4 mat3x4_f16;
   /* 0x0288 */ half4x2 mat4x2_f16;
-  /* 0x0298 */ half4x3 mat4x3_f16;
+  /* 0x0298 */ tint_array<tint_packed_vec3_f16_array_element, 4> mat4x3_f16;
   /* 0x02b8 */ half4x4 mat4x4_f16;
-  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_9;
-  /* 0x02e0 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_11;
+  /* 0x02e0 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
   /* 0x0300 */ tint_array<half4x2, 2> arr2_mat4x2_f16;
 };
 
-struct S {
-  /* 0x0000 */ tint_array<Inner, 1> arr;
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 1> arr;
 };
 
-void tint_symbol_inner(uint idx, const device S* const tint_symbol_1) {
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float3x3 tint_unpack_vec3_in_composite_1(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float4x3 tint_unpack_vec3_in_composite_2(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+half2x3 tint_unpack_vec3_in_composite_3(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+half3x3 tint_unpack_vec3_in_composite_4(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+half4x3 tint_unpack_vec3_in_composite_5(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3, 2> tint_unpack_vec3_in_composite_6(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  tint_array<float3, 2> result = {};
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  half scalar_f16;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  half2 vec2_f16;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  half3 vec3_f16;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  half4 vec4_f16;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  half2x2 mat2x2_f16;
+  half2x3 mat2x3_f16;
+  half2x4 mat2x4_f16;
+  half3x2 mat3x2_f16;
+  half3x3 mat3x3_f16;
+  half3x4 mat3x4_f16;
+  half4x2 mat4x2_f16;
+  half4x3 mat4x3_f16;
+  half4x4 mat4x4_f16;
+  tint_array<float3, 2> arr2_vec3_f32;
+  tint_array<half4x2, 2> arr2_mat4x2_f16;
+};
+
+struct S {
+  tint_array<Inner, 1> arr;
+};
+
+void tint_symbol_inner(uint idx, const device S_tint_packed_vec3* const tint_symbol_1) {
   float const scalar_f32 = (*(tint_symbol_1)).arr[idx].scalar_f32;
   int const scalar_i32 = (*(tint_symbol_1)).arr[idx].scalar_i32;
   uint const scalar_u32 = (*(tint_symbol_1)).arr[idx].scalar_u32;
@@ -85,28 +194,28 @@
   uint4 const vec4_u32 = (*(tint_symbol_1)).arr[idx].vec4_u32;
   half4 const vec4_f16 = (*(tint_symbol_1)).arr[idx].vec4_f16;
   float2x2 const mat2x2_f32 = (*(tint_symbol_1)).arr[idx].mat2x2_f32;
-  float2x3 const mat2x3_f32 = (*(tint_symbol_1)).arr[idx].mat2x3_f32;
+  float2x3 const mat2x3_f32 = tint_unpack_vec3_in_composite((*(tint_symbol_1)).arr[idx].mat2x3_f32);
   float2x4 const mat2x4_f32 = (*(tint_symbol_1)).arr[idx].mat2x4_f32;
   float3x2 const mat3x2_f32 = (*(tint_symbol_1)).arr[idx].mat3x2_f32;
-  float3x3 const mat3x3_f32 = (*(tint_symbol_1)).arr[idx].mat3x3_f32;
+  float3x3 const mat3x3_f32 = tint_unpack_vec3_in_composite_1((*(tint_symbol_1)).arr[idx].mat3x3_f32);
   float3x4 const mat3x4_f32 = (*(tint_symbol_1)).arr[idx].mat3x4_f32;
   float4x2 const mat4x2_f32 = (*(tint_symbol_1)).arr[idx].mat4x2_f32;
-  float4x3 const mat4x3_f32 = (*(tint_symbol_1)).arr[idx].mat4x3_f32;
+  float4x3 const mat4x3_f32 = tint_unpack_vec3_in_composite_2((*(tint_symbol_1)).arr[idx].mat4x3_f32);
   float4x4 const mat4x4_f32 = (*(tint_symbol_1)).arr[idx].mat4x4_f32;
   half2x2 const mat2x2_f16 = (*(tint_symbol_1)).arr[idx].mat2x2_f16;
-  half2x3 const mat2x3_f16 = (*(tint_symbol_1)).arr[idx].mat2x3_f16;
+  half2x3 const mat2x3_f16 = tint_unpack_vec3_in_composite_3((*(tint_symbol_1)).arr[idx].mat2x3_f16);
   half2x4 const mat2x4_f16 = (*(tint_symbol_1)).arr[idx].mat2x4_f16;
   half3x2 const mat3x2_f16 = (*(tint_symbol_1)).arr[idx].mat3x2_f16;
-  half3x3 const mat3x3_f16 = (*(tint_symbol_1)).arr[idx].mat3x3_f16;
+  half3x3 const mat3x3_f16 = tint_unpack_vec3_in_composite_4((*(tint_symbol_1)).arr[idx].mat3x3_f16);
   half3x4 const mat3x4_f16 = (*(tint_symbol_1)).arr[idx].mat3x4_f16;
   half4x2 const mat4x2_f16 = (*(tint_symbol_1)).arr[idx].mat4x2_f16;
-  half4x3 const mat4x3_f16 = (*(tint_symbol_1)).arr[idx].mat4x3_f16;
+  half4x3 const mat4x3_f16 = tint_unpack_vec3_in_composite_5((*(tint_symbol_1)).arr[idx].mat4x3_f16);
   half4x4 const mat4x4_f16 = (*(tint_symbol_1)).arr[idx].mat4x4_f16;
-  tint_array<float3, 2> const arr2_vec3_f32 = (*(tint_symbol_1)).arr[idx].arr2_vec3_f32;
+  tint_array<float3, 2> const arr2_vec3_f32 = tint_unpack_vec3_in_composite_6((*(tint_symbol_1)).arr[idx].arr2_vec3_f32);
   tint_array<half4x2, 2> const arr2_mat4x2_f16 = (*(tint_symbol_1)).arr[idx].arr2_mat4x2_f16;
 }
 
-kernel void tint_symbol(const device S* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
+kernel void tint_symbol(const device S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
   tint_symbol_inner(idx, tint_symbol_2);
   return;
 }
diff --git a/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.msl b/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.msl
index efb7ae4..c71462e 100644
--- a/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.msl
+++ b/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.msl
@@ -14,75 +14,109 @@
     T elements[N];
 };
 
-struct Inner {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct Inner_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
-  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad_1;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
-  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_2;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_3;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0060 */ float4 vec4_f32;
   /* 0x0070 */ int4 vec4_i32;
   /* 0x0080 */ uint4 vec4_u32;
   /* 0x0090 */ float2x2 mat2x2_f32;
-  /* 0x00a0 */ float2x3 mat2x3_f32;
+  /* 0x00a0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00c0 */ float2x4 mat2x4_f32;
   /* 0x00e0 */ float3x2 mat3x2_f32;
-  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_5;
-  /* 0x0100 */ float3x3 mat3x3_f32;
+  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_6;
+  /* 0x0100 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0130 */ float3x4 mat3x4_f32;
   /* 0x0160 */ float4x2 mat4x2_f32;
-  /* 0x0180 */ float4x3 mat4x3_f32;
+  /* 0x0180 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01c0 */ float4x4 mat4x4_f32;
-  /* 0x0200 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x0200 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
+};
+
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 1> arr;
+};
+
+struct Inner {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  tint_array<float3, 2> arr2_vec3_f32;
 };
 
 struct S {
-  /* 0x0000 */ tint_array<Inner, 1> arr;
+  tint_array<Inner, 1> arr;
 };
 
-void assign_and_preserve_padding(device float2x3* const dest, float2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, float2x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
 }
 
-void assign_and_preserve_padding_1(device float3x3* const dest, float3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+void assign_and_preserve_padding_1(device tint_array<tint_packed_vec3_f32_array_element, 3>* const dest, float3x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
 }
 
-void assign_and_preserve_padding_2(device float4x3* const dest, float4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+void assign_and_preserve_padding_2(device tint_array<tint_packed_vec3_f32_array_element, 4>* const dest, float4x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+  (*(dest))[3u].elements = packed_float3(value[3u]);
 }
 
-void assign_and_preserve_padding_3(device tint_array<float3, 2>* const dest, tint_array<float3, 2> value) {
+void assign_and_preserve_padding_3(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, tint_array<float3, 2> value) {
   for(uint i = 0u; (i < 2u); i = (i + 1u)) {
-    (*(dest))[i] = value[i];
+    (*(dest))[i].elements = packed_float3(value[i]);
   }
 }
 
-void tint_symbol_inner(uint idx, device S* const tint_symbol_2) {
+void tint_symbol_inner(uint idx, device S_tint_packed_vec3* const tint_symbol_2) {
   (*(tint_symbol_2)).arr[idx].scalar_f32 = 0.0f;
   (*(tint_symbol_2)).arr[idx].scalar_i32 = 0;
   (*(tint_symbol_2)).arr[idx].scalar_u32 = 0u;
   (*(tint_symbol_2)).arr[idx].vec2_f32 = float2(0.0f);
   (*(tint_symbol_2)).arr[idx].vec2_i32 = int2(0);
   (*(tint_symbol_2)).arr[idx].vec2_u32 = uint2(0u);
-  (*(tint_symbol_2)).arr[idx].vec3_f32 = float3(0.0f);
-  (*(tint_symbol_2)).arr[idx].vec3_i32 = int3(0);
-  (*(tint_symbol_2)).arr[idx].vec3_u32 = uint3(0u);
+  (*(tint_symbol_2)).arr[idx].vec3_f32 = packed_float3(0.0f);
+  (*(tint_symbol_2)).arr[idx].vec3_i32 = packed_int3(0);
+  (*(tint_symbol_2)).arr[idx].vec3_u32 = packed_uint3(0u);
   (*(tint_symbol_2)).arr[idx].vec4_f32 = float4(0.0f);
   (*(tint_symbol_2)).arr[idx].vec4_i32 = int4(0);
   (*(tint_symbol_2)).arr[idx].vec4_u32 = uint4(0u);
@@ -99,7 +133,7 @@
   assign_and_preserve_padding_3(&((*(tint_symbol_2)).arr[idx].arr2_vec3_f32), tint_symbol_1);
 }
 
-kernel void tint_symbol(device S* tint_symbol_3 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
+kernel void tint_symbol(device S_tint_packed_vec3* tint_symbol_3 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
   tint_symbol_inner(idx, tint_symbol_3);
   return;
 }
diff --git a/test/tint/buffer/storage/dynamic_index/write_f16.wgsl.expected.msl b/test/tint/buffer/storage/dynamic_index/write_f16.wgsl.expected.msl
index d38aab3..b5afec9 100644
--- a/test/tint/buffer/storage/dynamic_index/write_f16.wgsl.expected.msl
+++ b/test/tint/buffer/storage/dynamic_index/write_f16.wgsl.expected.msl
@@ -14,102 +14,155 @@
     T elements[N];
 };
 
-struct Inner {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad_1;
+};
+
+struct Inner_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
   /* 0x000c */ half scalar_f16;
-  /* 0x000e */ tint_array<int8_t, 2> tint_pad;
+  /* 0x000e */ tint_array<int8_t, 2> tint_pad_2;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
   /* 0x0028 */ half2 vec2_f16;
-  /* 0x002c */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x002c */ tint_array<int8_t, 4> tint_pad_3;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_6;
   /* 0x0060 */ packed_half3 vec3_f16;
-  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_5;
+  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_7;
   /* 0x0070 */ float4 vec4_f32;
   /* 0x0080 */ int4 vec4_i32;
   /* 0x0090 */ uint4 vec4_u32;
   /* 0x00a0 */ half4 vec4_f16;
   /* 0x00a8 */ float2x2 mat2x2_f32;
-  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_6;
-  /* 0x00c0 */ float2x3 mat2x3_f32;
+  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_8;
+  /* 0x00c0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00e0 */ float2x4 mat2x4_f32;
   /* 0x0100 */ float3x2 mat3x2_f32;
-  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_7;
-  /* 0x0120 */ float3x3 mat3x3_f32;
+  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_9;
+  /* 0x0120 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0150 */ float3x4 mat3x4_f32;
   /* 0x0180 */ float4x2 mat4x2_f32;
-  /* 0x01a0 */ float4x3 mat4x3_f32;
+  /* 0x01a0 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01e0 */ float4x4 mat4x4_f32;
   /* 0x0220 */ half2x2 mat2x2_f16;
-  /* 0x0228 */ half2x3 mat2x3_f16;
+  /* 0x0228 */ tint_array<tint_packed_vec3_f16_array_element, 2> mat2x3_f16;
   /* 0x0238 */ half2x4 mat2x4_f16;
   /* 0x0248 */ half3x2 mat3x2_f16;
-  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_8;
-  /* 0x0258 */ half3x3 mat3x3_f16;
+  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_10;
+  /* 0x0258 */ tint_array<tint_packed_vec3_f16_array_element, 3> mat3x3_f16;
   /* 0x0270 */ half3x4 mat3x4_f16;
   /* 0x0288 */ half4x2 mat4x2_f16;
-  /* 0x0298 */ half4x3 mat4x3_f16;
+  /* 0x0298 */ tint_array<tint_packed_vec3_f16_array_element, 4> mat4x3_f16;
   /* 0x02b8 */ half4x4 mat4x4_f16;
-  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_9;
-  /* 0x02e0 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_11;
+  /* 0x02e0 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
   /* 0x0300 */ tint_array<half4x2, 2> arr2_mat4x2_f16;
 };
 
-struct S {
-  /* 0x0000 */ tint_array<Inner, 1> arr;
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 1> arr;
 };
 
-void assign_and_preserve_padding(device float2x3* const dest, float2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+struct Inner {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  half scalar_f16;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  half2 vec2_f16;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  half3 vec3_f16;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  half4 vec4_f16;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  half2x2 mat2x2_f16;
+  half2x3 mat2x3_f16;
+  half2x4 mat2x4_f16;
+  half3x2 mat3x2_f16;
+  half3x3 mat3x3_f16;
+  half3x4 mat3x4_f16;
+  half4x2 mat4x2_f16;
+  half4x3 mat4x3_f16;
+  half4x4 mat4x4_f16;
+  tint_array<float3, 2> arr2_vec3_f32;
+  tint_array<half4x2, 2> arr2_mat4x2_f16;
+};
+
+struct S {
+  tint_array<Inner, 1> arr;
+};
+
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, float2x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
 }
 
-void assign_and_preserve_padding_1(device float3x3* const dest, float3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+void assign_and_preserve_padding_1(device tint_array<tint_packed_vec3_f32_array_element, 3>* const dest, float3x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
 }
 
-void assign_and_preserve_padding_2(device float4x3* const dest, float4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+void assign_and_preserve_padding_2(device tint_array<tint_packed_vec3_f32_array_element, 4>* const dest, float4x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+  (*(dest))[3u].elements = packed_float3(value[3u]);
 }
 
-void assign_and_preserve_padding_3(device half2x3* const dest, half2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+void assign_and_preserve_padding_3(device tint_array<tint_packed_vec3_f16_array_element, 2>* const dest, half2x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
 }
 
-void assign_and_preserve_padding_4(device half3x3* const dest, half3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+void assign_and_preserve_padding_4(device tint_array<tint_packed_vec3_f16_array_element, 3>* const dest, half3x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
 }
 
-void assign_and_preserve_padding_5(device half4x3* const dest, half4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+void assign_and_preserve_padding_5(device tint_array<tint_packed_vec3_f16_array_element, 4>* const dest, half4x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
+  (*(dest))[3u].elements = packed_half3(value[3u]);
 }
 
-void assign_and_preserve_padding_6(device tint_array<float3, 2>* const dest, tint_array<float3, 2> value) {
+void assign_and_preserve_padding_6(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, tint_array<float3, 2> value) {
   for(uint i = 0u; (i < 2u); i = (i + 1u)) {
-    (*(dest))[i] = value[i];
+    (*(dest))[i].elements = packed_float3(value[i]);
   }
 }
 
-void tint_symbol_inner(uint idx, device S* const tint_symbol_3) {
+void tint_symbol_inner(uint idx, device S_tint_packed_vec3* const tint_symbol_3) {
   (*(tint_symbol_3)).arr[idx].scalar_f32 = 0.0f;
   (*(tint_symbol_3)).arr[idx].scalar_i32 = 0;
   (*(tint_symbol_3)).arr[idx].scalar_u32 = 0u;
@@ -118,10 +171,10 @@
   (*(tint_symbol_3)).arr[idx].vec2_i32 = int2(0);
   (*(tint_symbol_3)).arr[idx].vec2_u32 = uint2(0u);
   (*(tint_symbol_3)).arr[idx].vec2_f16 = half2(0.0h);
-  (*(tint_symbol_3)).arr[idx].vec3_f32 = float3(0.0f);
-  (*(tint_symbol_3)).arr[idx].vec3_i32 = int3(0);
-  (*(tint_symbol_3)).arr[idx].vec3_u32 = uint3(0u);
-  (*(tint_symbol_3)).arr[idx].vec3_f16 = half3(0.0h);
+  (*(tint_symbol_3)).arr[idx].vec3_f32 = packed_float3(0.0f);
+  (*(tint_symbol_3)).arr[idx].vec3_i32 = packed_int3(0);
+  (*(tint_symbol_3)).arr[idx].vec3_u32 = packed_uint3(0u);
+  (*(tint_symbol_3)).arr[idx].vec3_f16 = packed_half3(0.0h);
   (*(tint_symbol_3)).arr[idx].vec4_f32 = float4(0.0f);
   (*(tint_symbol_3)).arr[idx].vec4_i32 = int4(0);
   (*(tint_symbol_3)).arr[idx].vec4_u32 = uint4(0u);
@@ -150,7 +203,7 @@
   (*(tint_symbol_3)).arr[idx].arr2_mat4x2_f16 = tint_symbol_2;
 }
 
-kernel void tint_symbol(device S* tint_symbol_4 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
+kernel void tint_symbol(device S_tint_packed_vec3* tint_symbol_4 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
   tint_symbol_inner(idx, tint_symbol_4);
   return;
 }
diff --git a/test/tint/buffer/storage/static_index/read.wgsl.expected.msl b/test/tint/buffer/storage/static_index/read.wgsl.expected.msl
index b0707fe..df35c27 100644
--- a/test/tint/buffer/storage/static_index/read.wgsl.expected.msl
+++ b/test/tint/buffer/storage/static_index/read.wgsl.expected.msl
@@ -14,46 +14,110 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
 struct Inner {
   /* 0x0000 */ int scalar_i32;
   /* 0x0004 */ float scalar_f32;
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
-  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad_1;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
-  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_2;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_3;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0060 */ float4 vec4_f32;
   /* 0x0070 */ int4 vec4_i32;
   /* 0x0080 */ uint4 vec4_u32;
   /* 0x0090 */ float2x2 mat2x2_f32;
-  /* 0x00a0 */ float2x3 mat2x3_f32;
+  /* 0x00a0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00c0 */ float2x4 mat2x4_f32;
   /* 0x00e0 */ float3x2 mat3x2_f32;
-  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_5;
-  /* 0x0100 */ float3x3 mat3x3_f32;
+  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_6;
+  /* 0x0100 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0130 */ float3x4 mat3x4_f32;
   /* 0x0160 */ float4x2 mat4x2_f32;
-  /* 0x0180 */ float4x3 mat4x3_f32;
+  /* 0x0180 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01c0 */ float4x4 mat4x4_f32;
-  /* 0x0200 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x0200 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
   /* 0x0220 */ Inner struct_inner;
   /* 0x0228 */ tint_array<Inner, 4> array_struct_inner;
-  /* 0x0248 */ tint_array<int8_t, 8> tint_pad_6;
+  /* 0x0248 */ tint_array<int8_t, 8> tint_pad_7;
 };
 
-kernel void tint_symbol(const device S* tint_symbol_1 [[buffer(0)]]) {
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float3x3 tint_unpack_vec3_in_composite_1(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float4x3 tint_unpack_vec3_in_composite_2(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3, 2> tint_unpack_vec3_in_composite_3(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  tint_array<float3, 2> result = {};
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  tint_array<float3, 2> arr2_vec3_f32;
+  Inner struct_inner;
+  tint_array<Inner, 4> array_struct_inner;
+};
+
+kernel void tint_symbol(const device S_tint_packed_vec3* tint_symbol_1 [[buffer(0)]]) {
   float const scalar_f32 = (*(tint_symbol_1)).scalar_f32;
   int const scalar_i32 = (*(tint_symbol_1)).scalar_i32;
   uint const scalar_u32 = (*(tint_symbol_1)).scalar_u32;
@@ -67,15 +131,15 @@
   int4 const vec4_i32 = (*(tint_symbol_1)).vec4_i32;
   uint4 const vec4_u32 = (*(tint_symbol_1)).vec4_u32;
   float2x2 const mat2x2_f32 = (*(tint_symbol_1)).mat2x2_f32;
-  float2x3 const mat2x3_f32 = (*(tint_symbol_1)).mat2x3_f32;
+  float2x3 const mat2x3_f32 = tint_unpack_vec3_in_composite((*(tint_symbol_1)).mat2x3_f32);
   float2x4 const mat2x4_f32 = (*(tint_symbol_1)).mat2x4_f32;
   float3x2 const mat3x2_f32 = (*(tint_symbol_1)).mat3x2_f32;
-  float3x3 const mat3x3_f32 = (*(tint_symbol_1)).mat3x3_f32;
+  float3x3 const mat3x3_f32 = tint_unpack_vec3_in_composite_1((*(tint_symbol_1)).mat3x3_f32);
   float3x4 const mat3x4_f32 = (*(tint_symbol_1)).mat3x4_f32;
   float4x2 const mat4x2_f32 = (*(tint_symbol_1)).mat4x2_f32;
-  float4x3 const mat4x3_f32 = (*(tint_symbol_1)).mat4x3_f32;
+  float4x3 const mat4x3_f32 = tint_unpack_vec3_in_composite_2((*(tint_symbol_1)).mat4x3_f32);
   float4x4 const mat4x4_f32 = (*(tint_symbol_1)).mat4x4_f32;
-  tint_array<float3, 2> const arr2_vec3_f32 = (*(tint_symbol_1)).arr2_vec3_f32;
+  tint_array<float3, 2> const arr2_vec3_f32 = tint_unpack_vec3_in_composite_3((*(tint_symbol_1)).arr2_vec3_f32);
   Inner const struct_inner = (*(tint_symbol_1)).struct_inner;
   tint_array<Inner, 4> const array_struct_inner = (*(tint_symbol_1)).array_struct_inner;
   return;
diff --git a/test/tint/buffer/storage/static_index/read_f16.wgsl.expected.msl b/test/tint/buffer/storage/static_index/read_f16.wgsl.expected.msl
index 461e002..18267f3 100644
--- a/test/tint/buffer/storage/static_index/read_f16.wgsl.expected.msl
+++ b/test/tint/buffer/storage/static_index/read_f16.wgsl.expected.msl
@@ -14,66 +14,173 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad_1;
+};
+
 struct Inner {
   /* 0x0000 */ int scalar_i32;
   /* 0x0004 */ float scalar_f32;
   /* 0x0008 */ half scalar_f16;
-  /* 0x000a */ tint_array<int8_t, 2> tint_pad;
+  /* 0x000a */ tint_array<int8_t, 2> tint_pad_2;
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
   /* 0x000c */ half scalar_f16;
-  /* 0x000e */ tint_array<int8_t, 2> tint_pad_1;
+  /* 0x000e */ tint_array<int8_t, 2> tint_pad_3;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
   /* 0x0028 */ half2 vec2_f16;
-  /* 0x002c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x002c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_6;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_5;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_7;
   /* 0x0060 */ packed_half3 vec3_f16;
-  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_6;
+  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_8;
   /* 0x0070 */ float4 vec4_f32;
   /* 0x0080 */ int4 vec4_i32;
   /* 0x0090 */ uint4 vec4_u32;
   /* 0x00a0 */ half4 vec4_f16;
   /* 0x00a8 */ float2x2 mat2x2_f32;
-  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_7;
-  /* 0x00c0 */ float2x3 mat2x3_f32;
+  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_9;
+  /* 0x00c0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00e0 */ float2x4 mat2x4_f32;
   /* 0x0100 */ float3x2 mat3x2_f32;
-  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_8;
-  /* 0x0120 */ float3x3 mat3x3_f32;
+  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_10;
+  /* 0x0120 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0150 */ float3x4 mat3x4_f32;
   /* 0x0180 */ float4x2 mat4x2_f32;
-  /* 0x01a0 */ float4x3 mat4x3_f32;
+  /* 0x01a0 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01e0 */ float4x4 mat4x4_f32;
   /* 0x0220 */ half2x2 mat2x2_f16;
-  /* 0x0228 */ half2x3 mat2x3_f16;
+  /* 0x0228 */ tint_array<tint_packed_vec3_f16_array_element, 2> mat2x3_f16;
   /* 0x0238 */ half2x4 mat2x4_f16;
   /* 0x0248 */ half3x2 mat3x2_f16;
-  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_9;
-  /* 0x0258 */ half3x3 mat3x3_f16;
+  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_11;
+  /* 0x0258 */ tint_array<tint_packed_vec3_f16_array_element, 3> mat3x3_f16;
   /* 0x0270 */ half3x4 mat3x4_f16;
   /* 0x0288 */ half4x2 mat4x2_f16;
-  /* 0x0298 */ half4x3 mat4x3_f16;
+  /* 0x0298 */ tint_array<tint_packed_vec3_f16_array_element, 4> mat4x3_f16;
   /* 0x02b8 */ half4x4 mat4x4_f16;
-  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_10;
-  /* 0x02e0 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_12;
+  /* 0x02e0 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
   /* 0x0300 */ tint_array<half4x2, 2> arr2_mat4x2_f16;
   /* 0x0320 */ Inner struct_inner;
   /* 0x032c */ tint_array<Inner, 4> array_struct_inner;
-  /* 0x035c */ tint_array<int8_t, 4> tint_pad_11;
+  /* 0x035c */ tint_array<int8_t, 4> tint_pad_13;
 };
 
-kernel void tint_symbol(const device S* tint_symbol_1 [[buffer(0)]]) {
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float3x3 tint_unpack_vec3_in_composite_1(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float4x3 tint_unpack_vec3_in_composite_2(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+half2x3 tint_unpack_vec3_in_composite_3(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+half3x3 tint_unpack_vec3_in_composite_4(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+half4x3 tint_unpack_vec3_in_composite_5(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3, 2> tint_unpack_vec3_in_composite_6(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  tint_array<float3, 2> result = {};
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  half scalar_f16;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  half2 vec2_f16;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  half3 vec3_f16;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  half4 vec4_f16;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  half2x2 mat2x2_f16;
+  half2x3 mat2x3_f16;
+  half2x4 mat2x4_f16;
+  half3x2 mat3x2_f16;
+  half3x3 mat3x3_f16;
+  half3x4 mat3x4_f16;
+  half4x2 mat4x2_f16;
+  half4x3 mat4x3_f16;
+  half4x4 mat4x4_f16;
+  tint_array<float3, 2> arr2_vec3_f32;
+  tint_array<half4x2, 2> arr2_mat4x2_f16;
+  Inner struct_inner;
+  tint_array<Inner, 4> array_struct_inner;
+};
+
+kernel void tint_symbol(const device S_tint_packed_vec3* tint_symbol_1 [[buffer(0)]]) {
   float const scalar_f32 = (*(tint_symbol_1)).scalar_f32;
   int const scalar_i32 = (*(tint_symbol_1)).scalar_i32;
   uint const scalar_u32 = (*(tint_symbol_1)).scalar_u32;
@@ -91,24 +198,24 @@
   uint4 const vec4_u32 = (*(tint_symbol_1)).vec4_u32;
   half4 const vec4_f16 = (*(tint_symbol_1)).vec4_f16;
   float2x2 const mat2x2_f32 = (*(tint_symbol_1)).mat2x2_f32;
-  float2x3 const mat2x3_f32 = (*(tint_symbol_1)).mat2x3_f32;
+  float2x3 const mat2x3_f32 = tint_unpack_vec3_in_composite((*(tint_symbol_1)).mat2x3_f32);
   float2x4 const mat2x4_f32 = (*(tint_symbol_1)).mat2x4_f32;
   float3x2 const mat3x2_f32 = (*(tint_symbol_1)).mat3x2_f32;
-  float3x3 const mat3x3_f32 = (*(tint_symbol_1)).mat3x3_f32;
+  float3x3 const mat3x3_f32 = tint_unpack_vec3_in_composite_1((*(tint_symbol_1)).mat3x3_f32);
   float3x4 const mat3x4_f32 = (*(tint_symbol_1)).mat3x4_f32;
   float4x2 const mat4x2_f32 = (*(tint_symbol_1)).mat4x2_f32;
-  float4x3 const mat4x3_f32 = (*(tint_symbol_1)).mat4x3_f32;
+  float4x3 const mat4x3_f32 = tint_unpack_vec3_in_composite_2((*(tint_symbol_1)).mat4x3_f32);
   float4x4 const mat4x4_f32 = (*(tint_symbol_1)).mat4x4_f32;
   half2x2 const mat2x2_f16 = (*(tint_symbol_1)).mat2x2_f16;
-  half2x3 const mat2x3_f16 = (*(tint_symbol_1)).mat2x3_f16;
+  half2x3 const mat2x3_f16 = tint_unpack_vec3_in_composite_3((*(tint_symbol_1)).mat2x3_f16);
   half2x4 const mat2x4_f16 = (*(tint_symbol_1)).mat2x4_f16;
   half3x2 const mat3x2_f16 = (*(tint_symbol_1)).mat3x2_f16;
-  half3x3 const mat3x3_f16 = (*(tint_symbol_1)).mat3x3_f16;
+  half3x3 const mat3x3_f16 = tint_unpack_vec3_in_composite_4((*(tint_symbol_1)).mat3x3_f16);
   half3x4 const mat3x4_f16 = (*(tint_symbol_1)).mat3x4_f16;
   half4x2 const mat4x2_f16 = (*(tint_symbol_1)).mat4x2_f16;
-  half4x3 const mat4x3_f16 = (*(tint_symbol_1)).mat4x3_f16;
+  half4x3 const mat4x3_f16 = tint_unpack_vec3_in_composite_5((*(tint_symbol_1)).mat4x3_f16);
   half4x4 const mat4x4_f16 = (*(tint_symbol_1)).mat4x4_f16;
-  tint_array<float3, 2> const arr2_vec3_f32 = (*(tint_symbol_1)).arr2_vec3_f32;
+  tint_array<float3, 2> const arr2_vec3_f32 = tint_unpack_vec3_in_composite_6((*(tint_symbol_1)).arr2_vec3_f32);
   tint_array<half4x2, 2> const arr2_mat4x2_f16 = (*(tint_symbol_1)).arr2_mat4x2_f16;
   Inner const struct_inner = (*(tint_symbol_1)).struct_inner;
   tint_array<Inner, 4> const array_struct_inner = (*(tint_symbol_1)).array_struct_inner;
diff --git a/test/tint/buffer/storage/static_index/write.wgsl.expected.msl b/test/tint/buffer/storage/static_index/write.wgsl.expected.msl
index 2c5bfa3..7f0d7eb 100644
--- a/test/tint/buffer/storage/static_index/write.wgsl.expected.msl
+++ b/test/tint/buffer/storage/static_index/write.wgsl.expected.msl
@@ -14,79 +14,111 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
 struct Inner {
   /* 0x0000 */ int scalar_i32;
   /* 0x0004 */ float scalar_f32;
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
-  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad_1;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
-  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_2;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_3;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0060 */ float4 vec4_f32;
   /* 0x0070 */ int4 vec4_i32;
   /* 0x0080 */ uint4 vec4_u32;
   /* 0x0090 */ float2x2 mat2x2_f32;
-  /* 0x00a0 */ float2x3 mat2x3_f32;
+  /* 0x00a0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00c0 */ float2x4 mat2x4_f32;
   /* 0x00e0 */ float3x2 mat3x2_f32;
-  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_5;
-  /* 0x0100 */ float3x3 mat3x3_f32;
+  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_6;
+  /* 0x0100 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0130 */ float3x4 mat3x4_f32;
   /* 0x0160 */ float4x2 mat4x2_f32;
-  /* 0x0180 */ float4x3 mat4x3_f32;
+  /* 0x0180 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01c0 */ float4x4 mat4x4_f32;
-  /* 0x0200 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x0200 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
   /* 0x0220 */ Inner struct_inner;
   /* 0x0228 */ tint_array<Inner, 4> array_struct_inner;
-  /* 0x0248 */ tint_array<int8_t, 8> tint_pad_6;
+  /* 0x0248 */ tint_array<int8_t, 8> tint_pad_7;
 };
 
-void assign_and_preserve_padding(device float2x3* const dest, float2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+struct S {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  tint_array<float3, 2> arr2_vec3_f32;
+  Inner struct_inner;
+  tint_array<Inner, 4> array_struct_inner;
+};
+
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, float2x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
 }
 
-void assign_and_preserve_padding_1(device float3x3* const dest, float3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+void assign_and_preserve_padding_1(device tint_array<tint_packed_vec3_f32_array_element, 3>* const dest, float3x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
 }
 
-void assign_and_preserve_padding_2(device float4x3* const dest, float4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+void assign_and_preserve_padding_2(device tint_array<tint_packed_vec3_f32_array_element, 4>* const dest, float4x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+  (*(dest))[3u].elements = packed_float3(value[3u]);
 }
 
-void assign_and_preserve_padding_3(device tint_array<float3, 2>* const dest, tint_array<float3, 2> value) {
+void assign_and_preserve_padding_3(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, tint_array<float3, 2> value) {
   for(uint i = 0u; (i < 2u); i = (i + 1u)) {
-    (*(dest))[i] = value[i];
+    (*(dest))[i].elements = packed_float3(value[i]);
   }
 }
 
-kernel void tint_symbol(device S* tint_symbol_4 [[buffer(0)]]) {
+kernel void tint_symbol(device S_tint_packed_vec3* tint_symbol_4 [[buffer(0)]]) {
   (*(tint_symbol_4)).scalar_f32 = 0.0f;
   (*(tint_symbol_4)).scalar_i32 = 0;
   (*(tint_symbol_4)).scalar_u32 = 0u;
   (*(tint_symbol_4)).vec2_f32 = float2(0.0f);
   (*(tint_symbol_4)).vec2_i32 = int2(0);
   (*(tint_symbol_4)).vec2_u32 = uint2(0u);
-  (*(tint_symbol_4)).vec3_f32 = float3(0.0f);
-  (*(tint_symbol_4)).vec3_i32 = int3(0);
-  (*(tint_symbol_4)).vec3_u32 = uint3(0u);
+  (*(tint_symbol_4)).vec3_f32 = packed_float3(0.0f);
+  (*(tint_symbol_4)).vec3_i32 = packed_int3(0);
+  (*(tint_symbol_4)).vec3_u32 = packed_uint3(0u);
   (*(tint_symbol_4)).vec4_f32 = float4(0.0f);
   (*(tint_symbol_4)).vec4_i32 = int4(0);
   (*(tint_symbol_4)).vec4_u32 = uint4(0u);
diff --git a/test/tint/buffer/storage/static_index/write_f16.wgsl.expected.msl b/test/tint/buffer/storage/static_index/write_f16.wgsl.expected.msl
index d9da3dd..a6aa784 100644
--- a/test/tint/buffer/storage/static_index/write_f16.wgsl.expected.msl
+++ b/test/tint/buffer/storage/static_index/write_f16.wgsl.expected.msl
@@ -14,104 +14,155 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad_1;
+};
+
 struct Inner {
   /* 0x0000 */ int scalar_i32;
   /* 0x0004 */ float scalar_f32;
   /* 0x0008 */ half scalar_f16;
-  /* 0x000a */ tint_array<int8_t, 2> tint_pad;
+  /* 0x000a */ tint_array<int8_t, 2> tint_pad_2;
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
   /* 0x000c */ half scalar_f16;
-  /* 0x000e */ tint_array<int8_t, 2> tint_pad_1;
+  /* 0x000e */ tint_array<int8_t, 2> tint_pad_3;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
   /* 0x0028 */ half2 vec2_f16;
-  /* 0x002c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x002c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_6;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_5;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_7;
   /* 0x0060 */ packed_half3 vec3_f16;
-  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_6;
+  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_8;
   /* 0x0070 */ float4 vec4_f32;
   /* 0x0080 */ int4 vec4_i32;
   /* 0x0090 */ uint4 vec4_u32;
   /* 0x00a0 */ half4 vec4_f16;
   /* 0x00a8 */ float2x2 mat2x2_f32;
-  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_7;
-  /* 0x00c0 */ float2x3 mat2x3_f32;
+  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_9;
+  /* 0x00c0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00e0 */ float2x4 mat2x4_f32;
   /* 0x0100 */ float3x2 mat3x2_f32;
-  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_8;
-  /* 0x0120 */ float3x3 mat3x3_f32;
+  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_10;
+  /* 0x0120 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0150 */ float3x4 mat3x4_f32;
   /* 0x0180 */ float4x2 mat4x2_f32;
-  /* 0x01a0 */ float4x3 mat4x3_f32;
+  /* 0x01a0 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01e0 */ float4x4 mat4x4_f32;
   /* 0x0220 */ half2x2 mat2x2_f16;
-  /* 0x0228 */ half2x3 mat2x3_f16;
+  /* 0x0228 */ tint_array<tint_packed_vec3_f16_array_element, 2> mat2x3_f16;
   /* 0x0238 */ half2x4 mat2x4_f16;
   /* 0x0248 */ half3x2 mat3x2_f16;
-  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_9;
-  /* 0x0258 */ half3x3 mat3x3_f16;
+  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_11;
+  /* 0x0258 */ tint_array<tint_packed_vec3_f16_array_element, 3> mat3x3_f16;
   /* 0x0270 */ half3x4 mat3x4_f16;
   /* 0x0288 */ half4x2 mat4x2_f16;
-  /* 0x0298 */ half4x3 mat4x3_f16;
+  /* 0x0298 */ tint_array<tint_packed_vec3_f16_array_element, 4> mat4x3_f16;
   /* 0x02b8 */ half4x4 mat4x4_f16;
-  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_10;
-  /* 0x02e0 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_12;
+  /* 0x02e0 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
   /* 0x0300 */ tint_array<half4x2, 2> arr2_mat4x2_f16;
   /* 0x0320 */ Inner struct_inner;
   /* 0x032c */ tint_array<Inner, 4> array_struct_inner;
-  /* 0x035c */ tint_array<int8_t, 4> tint_pad_11;
+  /* 0x035c */ tint_array<int8_t, 4> tint_pad_13;
 };
 
-void assign_and_preserve_padding(device float2x3* const dest, float2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+struct S {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  half scalar_f16;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  half2 vec2_f16;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  half3 vec3_f16;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  half4 vec4_f16;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  half2x2 mat2x2_f16;
+  half2x3 mat2x3_f16;
+  half2x4 mat2x4_f16;
+  half3x2 mat3x2_f16;
+  half3x3 mat3x3_f16;
+  half3x4 mat3x4_f16;
+  half4x2 mat4x2_f16;
+  half4x3 mat4x3_f16;
+  half4x4 mat4x4_f16;
+  tint_array<float3, 2> arr2_vec3_f32;
+  tint_array<half4x2, 2> arr2_mat4x2_f16;
+  Inner struct_inner;
+  tint_array<Inner, 4> array_struct_inner;
+};
+
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, float2x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
 }
 
-void assign_and_preserve_padding_1(device float3x3* const dest, float3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+void assign_and_preserve_padding_1(device tint_array<tint_packed_vec3_f32_array_element, 3>* const dest, float3x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
 }
 
-void assign_and_preserve_padding_2(device float4x3* const dest, float4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+void assign_and_preserve_padding_2(device tint_array<tint_packed_vec3_f32_array_element, 4>* const dest, float4x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+  (*(dest))[3u].elements = packed_float3(value[3u]);
 }
 
-void assign_and_preserve_padding_3(device half2x3* const dest, half2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+void assign_and_preserve_padding_3(device tint_array<tint_packed_vec3_f16_array_element, 2>* const dest, half2x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
 }
 
-void assign_and_preserve_padding_4(device half3x3* const dest, half3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+void assign_and_preserve_padding_4(device tint_array<tint_packed_vec3_f16_array_element, 3>* const dest, half3x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
 }
 
-void assign_and_preserve_padding_5(device half4x3* const dest, half4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+void assign_and_preserve_padding_5(device tint_array<tint_packed_vec3_f16_array_element, 4>* const dest, half4x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
+  (*(dest))[3u].elements = packed_half3(value[3u]);
 }
 
-void assign_and_preserve_padding_6(device tint_array<float3, 2>* const dest, tint_array<float3, 2> value) {
+void assign_and_preserve_padding_6(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, tint_array<float3, 2> value) {
   for(uint i = 0u; (i < 2u); i = (i + 1u)) {
-    (*(dest))[i] = value[i];
+    (*(dest))[i].elements = packed_float3(value[i]);
   }
 }
 
@@ -127,7 +178,7 @@
   }
 }
 
-kernel void tint_symbol(device S* tint_symbol_5 [[buffer(0)]]) {
+kernel void tint_symbol(device S_tint_packed_vec3* tint_symbol_5 [[buffer(0)]]) {
   (*(tint_symbol_5)).scalar_f32 = 0.0f;
   (*(tint_symbol_5)).scalar_i32 = 0;
   (*(tint_symbol_5)).scalar_u32 = 0u;
@@ -136,10 +187,10 @@
   (*(tint_symbol_5)).vec2_i32 = int2(0);
   (*(tint_symbol_5)).vec2_u32 = uint2(0u);
   (*(tint_symbol_5)).vec2_f16 = half2(0.0h);
-  (*(tint_symbol_5)).vec3_f32 = float3(0.0f);
-  (*(tint_symbol_5)).vec3_i32 = int3(0);
-  (*(tint_symbol_5)).vec3_u32 = uint3(0u);
-  (*(tint_symbol_5)).vec3_f16 = half3(0.0h);
+  (*(tint_symbol_5)).vec3_f32 = packed_float3(0.0f);
+  (*(tint_symbol_5)).vec3_i32 = packed_int3(0);
+  (*(tint_symbol_5)).vec3_u32 = packed_uint3(0u);
+  (*(tint_symbol_5)).vec3_f16 = packed_half3(0.0h);
   (*(tint_symbol_5)).vec4_f32 = float4(0.0f);
   (*(tint_symbol_5)).vec4_i32 = int4(0);
   (*(tint_symbol_5)).vec4_u32 = uint4(0u);
diff --git a/test/tint/buffer/storage/types/mat2x3_f16.wgsl.expected.msl b/test/tint/buffer/storage/types/mat2x3_f16.wgsl.expected.msl
index a79d9bb..2e9605e 100644
--- a/test/tint/buffer/storage/types/mat2x3_f16.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/mat2x3_f16.wgsl.expected.msl
@@ -1,13 +1,39 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device half2x3* const dest, half2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void tint_symbol(device half2x3* tint_symbol_1 [[buffer(0)]], const device half2x3* tint_symbol_2 [[buffer(1)]]) {
-  assign_and_preserve_padding(tint_symbol_1, *(tint_symbol_2));
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f16_array_element, 2>* const dest, half2x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+}
+
+kernel void tint_symbol(device tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol_1 [[buffer(0)]], const device tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol_2 [[buffer(1)]]) {
+  assign_and_preserve_padding(tint_symbol_1, tint_unpack_vec3_in_composite(*(tint_symbol_2)));
   return;
 }
 
diff --git a/test/tint/buffer/storage/types/mat2x3_f32.wgsl.expected.msl b/test/tint/buffer/storage/types/mat2x3_f32.wgsl.expected.msl
index 486563d..a03434b 100644
--- a/test/tint/buffer/storage/types/mat2x3_f32.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/mat2x3_f32.wgsl.expected.msl
@@ -1,13 +1,39 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device float2x3* const dest, float2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void tint_symbol(device float2x3* tint_symbol_1 [[buffer(0)]], const device float2x3* tint_symbol_2 [[buffer(1)]]) {
-  assign_and_preserve_padding(tint_symbol_1, *(tint_symbol_2));
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, float2x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+}
+
+kernel void tint_symbol(device tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol_1 [[buffer(0)]], const device tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol_2 [[buffer(1)]]) {
+  assign_and_preserve_padding(tint_symbol_1, tint_unpack_vec3_in_composite(*(tint_symbol_2)));
   return;
 }
 
diff --git a/test/tint/buffer/storage/types/mat3x3_f16.wgsl.expected.msl b/test/tint/buffer/storage/types/mat3x3_f16.wgsl.expected.msl
index 69da6e0..c688ab9 100644
--- a/test/tint/buffer/storage/types/mat3x3_f16.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/mat3x3_f16.wgsl.expected.msl
@@ -1,14 +1,40 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device half3x3* const dest, half3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void tint_symbol(device half3x3* tint_symbol_1 [[buffer(0)]], const device half3x3* tint_symbol_2 [[buffer(1)]]) {
-  assign_and_preserve_padding(tint_symbol_1, *(tint_symbol_2));
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f16_array_element, 3>* const dest, half3x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
+}
+
+kernel void tint_symbol(device tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol_1 [[buffer(0)]], const device tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol_2 [[buffer(1)]]) {
+  assign_and_preserve_padding(tint_symbol_1, tint_unpack_vec3_in_composite(*(tint_symbol_2)));
   return;
 }
 
diff --git a/test/tint/buffer/storage/types/mat3x3_f32.wgsl.expected.msl b/test/tint/buffer/storage/types/mat3x3_f32.wgsl.expected.msl
index 3054c1c..924c9d6 100644
--- a/test/tint/buffer/storage/types/mat3x3_f32.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/mat3x3_f32.wgsl.expected.msl
@@ -1,14 +1,40 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device float3x3* const dest, float3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void tint_symbol(device float3x3* tint_symbol_1 [[buffer(0)]], const device float3x3* tint_symbol_2 [[buffer(1)]]) {
-  assign_and_preserve_padding(tint_symbol_1, *(tint_symbol_2));
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f32_array_element, 3>* const dest, float3x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+}
+
+kernel void tint_symbol(device tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol_1 [[buffer(0)]], const device tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol_2 [[buffer(1)]]) {
+  assign_and_preserve_padding(tint_symbol_1, tint_unpack_vec3_in_composite(*(tint_symbol_2)));
   return;
 }
 
diff --git a/test/tint/buffer/storage/types/mat4x3_f16.wgsl.expected.msl b/test/tint/buffer/storage/types/mat4x3_f16.wgsl.expected.msl
index 15032a4..5ced5ff 100644
--- a/test/tint/buffer/storage/types/mat4x3_f16.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/mat4x3_f16.wgsl.expected.msl
@@ -1,15 +1,41 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device half4x3* const dest, half4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void tint_symbol(device half4x3* tint_symbol_1 [[buffer(0)]], const device half4x3* tint_symbol_2 [[buffer(1)]]) {
-  assign_and_preserve_padding(tint_symbol_1, *(tint_symbol_2));
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f16_array_element, 4>* const dest, half4x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
+  (*(dest))[3u].elements = packed_half3(value[3u]);
+}
+
+kernel void tint_symbol(device tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol_1 [[buffer(0)]], const device tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol_2 [[buffer(1)]]) {
+  assign_and_preserve_padding(tint_symbol_1, tint_unpack_vec3_in_composite(*(tint_symbol_2)));
   return;
 }
 
diff --git a/test/tint/buffer/storage/types/mat4x3_f32.wgsl.expected.msl b/test/tint/buffer/storage/types/mat4x3_f32.wgsl.expected.msl
index f5ebf26..78ba3ce 100644
--- a/test/tint/buffer/storage/types/mat4x3_f32.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/mat4x3_f32.wgsl.expected.msl
@@ -1,15 +1,41 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device float4x3* const dest, float4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void tint_symbol(device float4x3* tint_symbol_1 [[buffer(0)]], const device float4x3* tint_symbol_2 [[buffer(1)]]) {
-  assign_and_preserve_padding(tint_symbol_1, *(tint_symbol_2));
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f32_array_element, 4>* const dest, float4x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+  (*(dest))[3u].elements = packed_float3(value[3u]);
+}
+
+kernel void tint_symbol(device tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol_1 [[buffer(0)]], const device tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol_2 [[buffer(1)]]) {
+  assign_and_preserve_padding(tint_symbol_1, tint_unpack_vec3_in_composite(*(tint_symbol_2)));
   return;
 }
 
diff --git a/test/tint/buffer/storage/types/struct_f16.wgsl.expected.msl b/test/tint/buffer/storage/types/struct_f16.wgsl.expected.msl
index b52016d..a852b99 100644
--- a/test/tint/buffer/storage/types/struct_f16.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/struct_f16.wgsl.expected.msl
@@ -14,7 +14,7 @@
     T elements[N];
 };
 
-struct Inner {
+struct Inner_tint_packed_vec3 {
   /* 0x0000 */ half scalar_f16;
   /* 0x0002 */ tint_array<int8_t, 6> tint_pad;
   /* 0x0008 */ packed_half3 vec3_f16;
@@ -22,22 +22,46 @@
   /* 0x0010 */ half2x4 mat2x4_f16;
 };
 
-struct S {
-  /* 0x0000 */ Inner inner;
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ Inner_tint_packed_vec3 inner;
 };
 
-void assign_and_preserve_padding_1(device Inner* const dest, Inner value) {
+struct Inner {
+  half scalar_f16;
+  half3 vec3_f16;
+  half2x4 mat2x4_f16;
+};
+
+Inner tint_unpack_vec3_in_composite(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.scalar_f16 = in.scalar_f16;
+  result.vec3_f16 = half3(in.vec3_f16);
+  result.mat2x4_f16 = in.mat2x4_f16;
+  return result;
+}
+
+struct S {
+  Inner inner;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.inner = tint_unpack_vec3_in_composite(in.inner);
+  return result;
+}
+
+void assign_and_preserve_padding_1(device Inner_tint_packed_vec3* const dest, Inner value) {
   (*(dest)).scalar_f16 = value.scalar_f16;
-  (*(dest)).vec3_f16 = half3(value.vec3_f16);
+  (*(dest)).vec3_f16 = packed_half3(value.vec3_f16);
   (*(dest)).mat2x4_f16 = value.mat2x4_f16;
 }
 
-void assign_and_preserve_padding(device S* const dest, S value) {
+void assign_and_preserve_padding(device S_tint_packed_vec3* const dest, S value) {
   assign_and_preserve_padding_1(&((*(dest)).inner), value.inner);
 }
 
-kernel void tint_symbol(const device S* tint_symbol_1 [[buffer(1)]], device S* tint_symbol_2 [[buffer(0)]]) {
-  S const t = *(tint_symbol_1);
+kernel void tint_symbol(const device S_tint_packed_vec3* tint_symbol_1 [[buffer(1)]], device S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]]) {
+  S const t = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
   assign_and_preserve_padding(tint_symbol_2, t);
   return;
 }
diff --git a/test/tint/buffer/storage/types/struct_f32.wgsl.expected.msl b/test/tint/buffer/storage/types/struct_f32.wgsl.expected.msl
index 8b66d01..872631a 100644
--- a/test/tint/buffer/storage/types/struct_f32.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/struct_f32.wgsl.expected.msl
@@ -14,7 +14,7 @@
     T elements[N];
 };
 
-struct Inner {
+struct Inner_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
   /* 0x0010 */ packed_float3 vec3_f32;
@@ -22,22 +22,46 @@
   /* 0x0020 */ float2x4 mat2x4_f32;
 };
 
-struct S {
-  /* 0x0000 */ Inner inner;
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ Inner_tint_packed_vec3 inner;
 };
 
-void assign_and_preserve_padding_1(device Inner* const dest, Inner value) {
+struct Inner {
+  float scalar_f32;
+  float3 vec3_f32;
+  float2x4 mat2x4_f32;
+};
+
+Inner tint_unpack_vec3_in_composite(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.scalar_f32 = in.scalar_f32;
+  result.vec3_f32 = float3(in.vec3_f32);
+  result.mat2x4_f32 = in.mat2x4_f32;
+  return result;
+}
+
+struct S {
+  Inner inner;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.inner = tint_unpack_vec3_in_composite(in.inner);
+  return result;
+}
+
+void assign_and_preserve_padding_1(device Inner_tint_packed_vec3* const dest, Inner value) {
   (*(dest)).scalar_f32 = value.scalar_f32;
-  (*(dest)).vec3_f32 = float3(value.vec3_f32);
+  (*(dest)).vec3_f32 = packed_float3(value.vec3_f32);
   (*(dest)).mat2x4_f32 = value.mat2x4_f32;
 }
 
-void assign_and_preserve_padding(device S* const dest, S value) {
+void assign_and_preserve_padding(device S_tint_packed_vec3* const dest, S value) {
   assign_and_preserve_padding_1(&((*(dest)).inner), value.inner);
 }
 
-kernel void tint_symbol(const device S* tint_symbol_1 [[buffer(1)]], device S* tint_symbol_2 [[buffer(0)]]) {
-  S const t = *(tint_symbol_1);
+kernel void tint_symbol(const device S_tint_packed_vec3* tint_symbol_1 [[buffer(1)]], device S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]]) {
+  S const t = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
   assign_and_preserve_padding(tint_symbol_2, t);
   return;
 }
diff --git a/test/tint/buffer/storage/types/vec3_f16.wgsl.expected.msl b/test/tint/buffer/storage/types/vec3_f16.wgsl.expected.msl
index d5bfb88..1ddee05 100644
--- a/test/tint/buffer/storage/types/vec3_f16.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/vec3_f16.wgsl.expected.msl
@@ -1,7 +1,7 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(device half3* tint_symbol_1 [[buffer(0)]], const device half3* tint_symbol_2 [[buffer(1)]]) {
+kernel void tint_symbol(device packed_half3* tint_symbol_1 [[buffer(0)]], const device packed_half3* tint_symbol_2 [[buffer(1)]]) {
   *(tint_symbol_1) = *(tint_symbol_2);
   return;
 }
diff --git a/test/tint/buffer/storage/types/vec3_f32.wgsl.expected.msl b/test/tint/buffer/storage/types/vec3_f32.wgsl.expected.msl
index 800b609..08877ed 100644
--- a/test/tint/buffer/storage/types/vec3_f32.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/vec3_f32.wgsl.expected.msl
@@ -1,7 +1,7 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(device float3* tint_symbol_1 [[buffer(0)]], const device float3* tint_symbol_2 [[buffer(1)]]) {
+kernel void tint_symbol(device packed_float3* tint_symbol_1 [[buffer(0)]], const device packed_float3* tint_symbol_2 [[buffer(1)]]) {
   *(tint_symbol_1) = *(tint_symbol_2);
   return;
 }
diff --git a/test/tint/buffer/storage/types/vec3_i32.wgsl.expected.msl b/test/tint/buffer/storage/types/vec3_i32.wgsl.expected.msl
index d056869..1a382a5 100644
--- a/test/tint/buffer/storage/types/vec3_i32.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/vec3_i32.wgsl.expected.msl
@@ -1,7 +1,7 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(device int3* tint_symbol_1 [[buffer(0)]], const device int3* tint_symbol_2 [[buffer(1)]]) {
+kernel void tint_symbol(device packed_int3* tint_symbol_1 [[buffer(0)]], const device packed_int3* tint_symbol_2 [[buffer(1)]]) {
   *(tint_symbol_1) = *(tint_symbol_2);
   return;
 }
diff --git a/test/tint/buffer/storage/types/vec3_u32.wgsl.expected.msl b/test/tint/buffer/storage/types/vec3_u32.wgsl.expected.msl
index 54cc7c8..f54161f 100644
--- a/test/tint/buffer/storage/types/vec3_u32.wgsl.expected.msl
+++ b/test/tint/buffer/storage/types/vec3_u32.wgsl.expected.msl
@@ -1,7 +1,7 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(device uint3* tint_symbol_1 [[buffer(0)]], const device uint3* tint_symbol_2 [[buffer(1)]]) {
+kernel void tint_symbol(device packed_uint3* tint_symbol_1 [[buffer(0)]], const device packed_uint3* tint_symbol_2 [[buffer(1)]]) {
   *(tint_symbol_1) = *(tint_symbol_2);
   return;
 }
diff --git a/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.msl b/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.msl
index f976bd1..d8f4ccf 100644
--- a/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.msl
@@ -14,42 +14,108 @@
     T elements[N];
 };
 
-struct Inner {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct Inner_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
-  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad_1;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
-  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_2;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_3;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0060 */ float4 vec4_f32;
   /* 0x0070 */ int4 vec4_i32;
   /* 0x0080 */ uint4 vec4_u32;
   /* 0x0090 */ float2x2 mat2x2_f32;
-  /* 0x00a0 */ float2x3 mat2x3_f32;
+  /* 0x00a0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00c0 */ float2x4 mat2x4_f32;
   /* 0x00e0 */ float3x2 mat3x2_f32;
-  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_5;
-  /* 0x0100 */ float3x3 mat3x3_f32;
+  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_6;
+  /* 0x0100 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0130 */ float3x4 mat3x4_f32;
   /* 0x0160 */ float4x2 mat4x2_f32;
-  /* 0x0180 */ float4x3 mat4x3_f32;
+  /* 0x0180 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01c0 */ float4x4 mat4x4_f32;
-  /* 0x0200 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x0200 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
+};
+
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 8> arr;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float3x3 tint_unpack_vec3_in_composite_1(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float4x3 tint_unpack_vec3_in_composite_2(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3, 2> tint_unpack_vec3_in_composite_3(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  tint_array<float3, 2> result = {};
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  tint_array<float3, 2> arr2_vec3_f32;
 };
 
 struct S {
-  /* 0x0000 */ tint_array<Inner, 8> arr;
+  tint_array<Inner, 8> arr;
 };
 
-void tint_symbol_inner(uint idx, const constant S* const tint_symbol_1) {
+void tint_symbol_inner(uint idx, const constant S_tint_packed_vec3* const tint_symbol_1) {
   float const scalar_f32 = (*(tint_symbol_1)).arr[idx].scalar_f32;
   int const scalar_i32 = (*(tint_symbol_1)).arr[idx].scalar_i32;
   uint const scalar_u32 = (*(tint_symbol_1)).arr[idx].scalar_u32;
@@ -63,18 +129,18 @@
   int4 const vec4_i32 = (*(tint_symbol_1)).arr[idx].vec4_i32;
   uint4 const vec4_u32 = (*(tint_symbol_1)).arr[idx].vec4_u32;
   float2x2 const mat2x2_f32 = (*(tint_symbol_1)).arr[idx].mat2x2_f32;
-  float2x3 const mat2x3_f32 = (*(tint_symbol_1)).arr[idx].mat2x3_f32;
+  float2x3 const mat2x3_f32 = tint_unpack_vec3_in_composite((*(tint_symbol_1)).arr[idx].mat2x3_f32);
   float2x4 const mat2x4_f32 = (*(tint_symbol_1)).arr[idx].mat2x4_f32;
   float3x2 const mat3x2_f32 = (*(tint_symbol_1)).arr[idx].mat3x2_f32;
-  float3x3 const mat3x3_f32 = (*(tint_symbol_1)).arr[idx].mat3x3_f32;
+  float3x3 const mat3x3_f32 = tint_unpack_vec3_in_composite_1((*(tint_symbol_1)).arr[idx].mat3x3_f32);
   float3x4 const mat3x4_f32 = (*(tint_symbol_1)).arr[idx].mat3x4_f32;
   float4x2 const mat4x2_f32 = (*(tint_symbol_1)).arr[idx].mat4x2_f32;
-  float4x3 const mat4x3_f32 = (*(tint_symbol_1)).arr[idx].mat4x3_f32;
+  float4x3 const mat4x3_f32 = tint_unpack_vec3_in_composite_2((*(tint_symbol_1)).arr[idx].mat4x3_f32);
   float4x4 const mat4x4_f32 = (*(tint_symbol_1)).arr[idx].mat4x4_f32;
-  tint_array<float3, 2> const arr2_vec3_f32 = (*(tint_symbol_1)).arr[idx].arr2_vec3_f32;
+  tint_array<float3, 2> const arr2_vec3_f32 = tint_unpack_vec3_in_composite_3((*(tint_symbol_1)).arr[idx].arr2_vec3_f32);
 }
 
-kernel void tint_symbol(const constant S* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
+kernel void tint_symbol(const constant S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
   tint_symbol_inner(idx, tint_symbol_2);
   return;
 }
diff --git a/test/tint/buffer/uniform/dynamic_index/read_f16.wgsl.expected.msl b/test/tint/buffer/uniform/dynamic_index/read_f16.wgsl.expected.msl
index f6b667e..fd2a570 100644
--- a/test/tint/buffer/uniform/dynamic_index/read_f16.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/dynamic_index/read_f16.wgsl.expected.msl
@@ -14,60 +14,169 @@
     T elements[N];
 };
 
-struct Inner {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad_1;
+};
+
+struct Inner_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
   /* 0x000c */ half scalar_f16;
-  /* 0x000e */ tint_array<int8_t, 2> tint_pad;
+  /* 0x000e */ tint_array<int8_t, 2> tint_pad_2;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
   /* 0x0028 */ half2 vec2_f16;
-  /* 0x002c */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x002c */ tint_array<int8_t, 4> tint_pad_3;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_6;
   /* 0x0060 */ packed_half3 vec3_f16;
-  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_5;
+  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_7;
   /* 0x0070 */ float4 vec4_f32;
   /* 0x0080 */ int4 vec4_i32;
   /* 0x0090 */ uint4 vec4_u32;
   /* 0x00a0 */ half4 vec4_f16;
   /* 0x00a8 */ float2x2 mat2x2_f32;
-  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_6;
-  /* 0x00c0 */ float2x3 mat2x3_f32;
+  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_8;
+  /* 0x00c0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00e0 */ float2x4 mat2x4_f32;
   /* 0x0100 */ float3x2 mat3x2_f32;
-  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_7;
-  /* 0x0120 */ float3x3 mat3x3_f32;
+  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_9;
+  /* 0x0120 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0150 */ float3x4 mat3x4_f32;
   /* 0x0180 */ float4x2 mat4x2_f32;
-  /* 0x01a0 */ float4x3 mat4x3_f32;
+  /* 0x01a0 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01e0 */ float4x4 mat4x4_f32;
   /* 0x0220 */ half2x2 mat2x2_f16;
-  /* 0x0228 */ half2x3 mat2x3_f16;
+  /* 0x0228 */ tint_array<tint_packed_vec3_f16_array_element, 2> mat2x3_f16;
   /* 0x0238 */ half2x4 mat2x4_f16;
   /* 0x0248 */ half3x2 mat3x2_f16;
-  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_8;
-  /* 0x0258 */ half3x3 mat3x3_f16;
+  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_10;
+  /* 0x0258 */ tint_array<tint_packed_vec3_f16_array_element, 3> mat3x3_f16;
   /* 0x0270 */ half3x4 mat3x4_f16;
   /* 0x0288 */ half4x2 mat4x2_f16;
-  /* 0x0298 */ half4x3 mat4x3_f16;
+  /* 0x0298 */ tint_array<tint_packed_vec3_f16_array_element, 4> mat4x3_f16;
   /* 0x02b8 */ half4x4 mat4x4_f16;
-  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_9;
-  /* 0x02e0 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_11;
+  /* 0x02e0 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
   /* 0x0300 */ tint_array<half4x2, 2> arr2_mat4x2_f16;
 };
 
-struct S {
-  /* 0x0000 */ tint_array<Inner, 8> arr;
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 8> arr;
 };
 
-void tint_symbol_inner(uint idx, const constant S* const tint_symbol_1) {
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float3x3 tint_unpack_vec3_in_composite_1(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float4x3 tint_unpack_vec3_in_composite_2(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+half2x3 tint_unpack_vec3_in_composite_3(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+half3x3 tint_unpack_vec3_in_composite_4(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+half4x3 tint_unpack_vec3_in_composite_5(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3, 2> tint_unpack_vec3_in_composite_6(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  tint_array<float3, 2> result = {};
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  half scalar_f16;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  half2 vec2_f16;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  half3 vec3_f16;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  half4 vec4_f16;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  half2x2 mat2x2_f16;
+  half2x3 mat2x3_f16;
+  half2x4 mat2x4_f16;
+  half3x2 mat3x2_f16;
+  half3x3 mat3x3_f16;
+  half3x4 mat3x4_f16;
+  half4x2 mat4x2_f16;
+  half4x3 mat4x3_f16;
+  half4x4 mat4x4_f16;
+  tint_array<float3, 2> arr2_vec3_f32;
+  tint_array<half4x2, 2> arr2_mat4x2_f16;
+};
+
+struct S {
+  tint_array<Inner, 8> arr;
+};
+
+void tint_symbol_inner(uint idx, const constant S_tint_packed_vec3* const tint_symbol_1) {
   float const scalar_f32 = (*(tint_symbol_1)).arr[idx].scalar_f32;
   int const scalar_i32 = (*(tint_symbol_1)).arr[idx].scalar_i32;
   uint const scalar_u32 = (*(tint_symbol_1)).arr[idx].scalar_u32;
@@ -85,28 +194,28 @@
   uint4 const vec4_u32 = (*(tint_symbol_1)).arr[idx].vec4_u32;
   half4 const vec4_f16 = (*(tint_symbol_1)).arr[idx].vec4_f16;
   float2x2 const mat2x2_f32 = (*(tint_symbol_1)).arr[idx].mat2x2_f32;
-  float2x3 const mat2x3_f32 = (*(tint_symbol_1)).arr[idx].mat2x3_f32;
+  float2x3 const mat2x3_f32 = tint_unpack_vec3_in_composite((*(tint_symbol_1)).arr[idx].mat2x3_f32);
   float2x4 const mat2x4_f32 = (*(tint_symbol_1)).arr[idx].mat2x4_f32;
   float3x2 const mat3x2_f32 = (*(tint_symbol_1)).arr[idx].mat3x2_f32;
-  float3x3 const mat3x3_f32 = (*(tint_symbol_1)).arr[idx].mat3x3_f32;
+  float3x3 const mat3x3_f32 = tint_unpack_vec3_in_composite_1((*(tint_symbol_1)).arr[idx].mat3x3_f32);
   float3x4 const mat3x4_f32 = (*(tint_symbol_1)).arr[idx].mat3x4_f32;
   float4x2 const mat4x2_f32 = (*(tint_symbol_1)).arr[idx].mat4x2_f32;
-  float4x3 const mat4x3_f32 = (*(tint_symbol_1)).arr[idx].mat4x3_f32;
+  float4x3 const mat4x3_f32 = tint_unpack_vec3_in_composite_2((*(tint_symbol_1)).arr[idx].mat4x3_f32);
   float4x4 const mat4x4_f32 = (*(tint_symbol_1)).arr[idx].mat4x4_f32;
   half2x2 const mat2x2_f16 = (*(tint_symbol_1)).arr[idx].mat2x2_f16;
-  half2x3 const mat2x3_f16 = (*(tint_symbol_1)).arr[idx].mat2x3_f16;
+  half2x3 const mat2x3_f16 = tint_unpack_vec3_in_composite_3((*(tint_symbol_1)).arr[idx].mat2x3_f16);
   half2x4 const mat2x4_f16 = (*(tint_symbol_1)).arr[idx].mat2x4_f16;
   half3x2 const mat3x2_f16 = (*(tint_symbol_1)).arr[idx].mat3x2_f16;
-  half3x3 const mat3x3_f16 = (*(tint_symbol_1)).arr[idx].mat3x3_f16;
+  half3x3 const mat3x3_f16 = tint_unpack_vec3_in_composite_4((*(tint_symbol_1)).arr[idx].mat3x3_f16);
   half3x4 const mat3x4_f16 = (*(tint_symbol_1)).arr[idx].mat3x4_f16;
   half4x2 const mat4x2_f16 = (*(tint_symbol_1)).arr[idx].mat4x2_f16;
-  half4x3 const mat4x3_f16 = (*(tint_symbol_1)).arr[idx].mat4x3_f16;
+  half4x3 const mat4x3_f16 = tint_unpack_vec3_in_composite_5((*(tint_symbol_1)).arr[idx].mat4x3_f16);
   half4x4 const mat4x4_f16 = (*(tint_symbol_1)).arr[idx].mat4x4_f16;
-  tint_array<float3, 2> const arr2_vec3_f32 = (*(tint_symbol_1)).arr[idx].arr2_vec3_f32;
+  tint_array<float3, 2> const arr2_vec3_f32 = tint_unpack_vec3_in_composite_6((*(tint_symbol_1)).arr[idx].arr2_vec3_f32);
   tint_array<half4x2, 2> const arr2_mat4x2_f16 = (*(tint_symbol_1)).arr[idx].arr2_mat4x2_f16;
 }
 
-kernel void tint_symbol(const constant S* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
+kernel void tint_symbol(const constant S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
   tint_symbol_inner(idx, tint_symbol_2);
   return;
 }
diff --git a/test/tint/buffer/uniform/static_index/read.wgsl.expected.msl b/test/tint/buffer/uniform/static_index/read.wgsl.expected.msl
index 93dc443..853a909 100644
--- a/test/tint/buffer/uniform/static_index/read.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/static_index/read.wgsl.expected.msl
@@ -14,47 +14,111 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ int scalar_i32;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float scalar_f32;
-  /* 0x0014 */ tint_array<int8_t, 12> tint_pad_1;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-struct S {
+struct Inner {
+  /* 0x0000 */ int scalar_i32;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ float scalar_f32;
+  /* 0x0014 */ tint_array<int8_t, 12> tint_pad_2;
+};
+
+struct S_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
-  /* 0x000c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad_3;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
-  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_3;
+  /* 0x0028 */ tint_array<int8_t, 8> tint_pad_4;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_5;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_6;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_6;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_7;
   /* 0x0060 */ float4 vec4_f32;
   /* 0x0070 */ int4 vec4_i32;
   /* 0x0080 */ uint4 vec4_u32;
   /* 0x0090 */ float2x2 mat2x2_f32;
-  /* 0x00a0 */ float2x3 mat2x3_f32;
+  /* 0x00a0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00c0 */ float2x4 mat2x4_f32;
   /* 0x00e0 */ float3x2 mat3x2_f32;
-  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_7;
-  /* 0x0100 */ float3x3 mat3x3_f32;
+  /* 0x00f8 */ tint_array<int8_t, 8> tint_pad_8;
+  /* 0x0100 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0130 */ float3x4 mat3x4_f32;
   /* 0x0160 */ float4x2 mat4x2_f32;
-  /* 0x0180 */ float4x3 mat4x3_f32;
+  /* 0x0180 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01c0 */ float4x4 mat4x4_f32;
-  /* 0x0200 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x0200 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
   /* 0x0220 */ Inner struct_inner;
   /* 0x0240 */ tint_array<Inner, 4> array_struct_inner;
 };
 
-kernel void tint_symbol(const constant S* tint_symbol_1 [[buffer(0)]]) {
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float3x3 tint_unpack_vec3_in_composite_1(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float4x3 tint_unpack_vec3_in_composite_2(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3, 2> tint_unpack_vec3_in_composite_3(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  tint_array<float3, 2> result = {};
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  tint_array<float3, 2> arr2_vec3_f32;
+  Inner struct_inner;
+  tint_array<Inner, 4> array_struct_inner;
+};
+
+kernel void tint_symbol(const constant S_tint_packed_vec3* tint_symbol_1 [[buffer(0)]]) {
   float const scalar_f32 = (*(tint_symbol_1)).scalar_f32;
   int const scalar_i32 = (*(tint_symbol_1)).scalar_i32;
   uint const scalar_u32 = (*(tint_symbol_1)).scalar_u32;
@@ -68,15 +132,15 @@
   int4 const vec4_i32 = (*(tint_symbol_1)).vec4_i32;
   uint4 const vec4_u32 = (*(tint_symbol_1)).vec4_u32;
   float2x2 const mat2x2_f32 = (*(tint_symbol_1)).mat2x2_f32;
-  float2x3 const mat2x3_f32 = (*(tint_symbol_1)).mat2x3_f32;
+  float2x3 const mat2x3_f32 = tint_unpack_vec3_in_composite((*(tint_symbol_1)).mat2x3_f32);
   float2x4 const mat2x4_f32 = (*(tint_symbol_1)).mat2x4_f32;
   float3x2 const mat3x2_f32 = (*(tint_symbol_1)).mat3x2_f32;
-  float3x3 const mat3x3_f32 = (*(tint_symbol_1)).mat3x3_f32;
+  float3x3 const mat3x3_f32 = tint_unpack_vec3_in_composite_1((*(tint_symbol_1)).mat3x3_f32);
   float3x4 const mat3x4_f32 = (*(tint_symbol_1)).mat3x4_f32;
   float4x2 const mat4x2_f32 = (*(tint_symbol_1)).mat4x2_f32;
-  float4x3 const mat4x3_f32 = (*(tint_symbol_1)).mat4x3_f32;
+  float4x3 const mat4x3_f32 = tint_unpack_vec3_in_composite_2((*(tint_symbol_1)).mat4x3_f32);
   float4x4 const mat4x4_f32 = (*(tint_symbol_1)).mat4x4_f32;
-  tint_array<float3, 2> const arr2_vec3_f32 = (*(tint_symbol_1)).arr2_vec3_f32;
+  tint_array<float3, 2> const arr2_vec3_f32 = tint_unpack_vec3_in_composite_3((*(tint_symbol_1)).arr2_vec3_f32);
   Inner const struct_inner = (*(tint_symbol_1)).struct_inner;
   tint_array<Inner, 4> const array_struct_inner = (*(tint_symbol_1)).array_struct_inner;
   return;
diff --git a/test/tint/buffer/uniform/static_index/read_f16.wgsl.expected.msl b/test/tint/buffer/uniform/static_index/read_f16.wgsl.expected.msl
index 99638ed..39bb058 100644
--- a/test/tint/buffer/uniform/static_index/read_f16.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/static_index/read_f16.wgsl.expected.msl
@@ -14,65 +14,172 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad_1;
+};
+
 struct Inner {
   /* 0x0000 */ int scalar_i32;
   /* 0x0004 */ float scalar_f32;
   /* 0x0008 */ half scalar_f16;
-  /* 0x000a */ tint_array<int8_t, 6> tint_pad;
+  /* 0x000a */ tint_array<int8_t, 6> tint_pad_2;
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ int scalar_i32;
   /* 0x0008 */ uint scalar_u32;
   /* 0x000c */ half scalar_f16;
-  /* 0x000e */ tint_array<int8_t, 2> tint_pad_1;
+  /* 0x000e */ tint_array<int8_t, 2> tint_pad_3;
   /* 0x0010 */ float2 vec2_f32;
   /* 0x0018 */ int2 vec2_i32;
   /* 0x0020 */ uint2 vec2_u32;
   /* 0x0028 */ half2 vec2_f16;
-  /* 0x002c */ tint_array<int8_t, 4> tint_pad_2;
+  /* 0x002c */ tint_array<int8_t, 4> tint_pad_4;
   /* 0x0030 */ packed_float3 vec3_f32;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad_3;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_5;
   /* 0x0040 */ packed_int3 vec3_i32;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad_4;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_6;
   /* 0x0050 */ packed_uint3 vec3_u32;
-  /* 0x005c */ tint_array<int8_t, 4> tint_pad_5;
+  /* 0x005c */ tint_array<int8_t, 4> tint_pad_7;
   /* 0x0060 */ packed_half3 vec3_f16;
-  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_6;
+  /* 0x0066 */ tint_array<int8_t, 10> tint_pad_8;
   /* 0x0070 */ float4 vec4_f32;
   /* 0x0080 */ int4 vec4_i32;
   /* 0x0090 */ uint4 vec4_u32;
   /* 0x00a0 */ half4 vec4_f16;
   /* 0x00a8 */ float2x2 mat2x2_f32;
-  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_7;
-  /* 0x00c0 */ float2x3 mat2x3_f32;
+  /* 0x00b8 */ tint_array<int8_t, 8> tint_pad_9;
+  /* 0x00c0 */ tint_array<tint_packed_vec3_f32_array_element, 2> mat2x3_f32;
   /* 0x00e0 */ float2x4 mat2x4_f32;
   /* 0x0100 */ float3x2 mat3x2_f32;
-  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_8;
-  /* 0x0120 */ float3x3 mat3x3_f32;
+  /* 0x0118 */ tint_array<int8_t, 8> tint_pad_10;
+  /* 0x0120 */ tint_array<tint_packed_vec3_f32_array_element, 3> mat3x3_f32;
   /* 0x0150 */ float3x4 mat3x4_f32;
   /* 0x0180 */ float4x2 mat4x2_f32;
-  /* 0x01a0 */ float4x3 mat4x3_f32;
+  /* 0x01a0 */ tint_array<tint_packed_vec3_f32_array_element, 4> mat4x3_f32;
   /* 0x01e0 */ float4x4 mat4x4_f32;
   /* 0x0220 */ half2x2 mat2x2_f16;
-  /* 0x0228 */ half2x3 mat2x3_f16;
+  /* 0x0228 */ tint_array<tint_packed_vec3_f16_array_element, 2> mat2x3_f16;
   /* 0x0238 */ half2x4 mat2x4_f16;
   /* 0x0248 */ half3x2 mat3x2_f16;
-  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_9;
-  /* 0x0258 */ half3x3 mat3x3_f16;
+  /* 0x0254 */ tint_array<int8_t, 4> tint_pad_11;
+  /* 0x0258 */ tint_array<tint_packed_vec3_f16_array_element, 3> mat3x3_f16;
   /* 0x0270 */ half3x4 mat3x4_f16;
   /* 0x0288 */ half4x2 mat4x2_f16;
-  /* 0x0298 */ half4x3 mat4x3_f16;
+  /* 0x0298 */ tint_array<tint_packed_vec3_f16_array_element, 4> mat4x3_f16;
   /* 0x02b8 */ half4x4 mat4x4_f16;
-  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_10;
-  /* 0x02e0 */ tint_array<float3, 2> arr2_vec3_f32;
+  /* 0x02d8 */ tint_array<int8_t, 8> tint_pad_12;
+  /* 0x02e0 */ tint_array<tint_packed_vec3_f32_array_element, 2> arr2_vec3_f32;
   /* 0x0300 */ tint_array<half4x2, 2> arr2_mat4x2_f16;
   /* 0x0320 */ Inner struct_inner;
   /* 0x0330 */ tint_array<Inner, 4> array_struct_inner;
 };
 
-kernel void tint_symbol(const constant S* tint_symbol_1 [[buffer(0)]]) {
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float3x3 tint_unpack_vec3_in_composite_1(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+float4x3 tint_unpack_vec3_in_composite_2(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+half2x3 tint_unpack_vec3_in_composite_3(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+half3x3 tint_unpack_vec3_in_composite_4(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+half4x3 tint_unpack_vec3_in_composite_5(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3, 2> tint_unpack_vec3_in_composite_6(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  tint_array<float3, 2> result = {};
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  float scalar_f32;
+  int scalar_i32;
+  uint scalar_u32;
+  half scalar_f16;
+  float2 vec2_f32;
+  int2 vec2_i32;
+  uint2 vec2_u32;
+  half2 vec2_f16;
+  float3 vec3_f32;
+  int3 vec3_i32;
+  uint3 vec3_u32;
+  half3 vec3_f16;
+  float4 vec4_f32;
+  int4 vec4_i32;
+  uint4 vec4_u32;
+  half4 vec4_f16;
+  float2x2 mat2x2_f32;
+  float2x3 mat2x3_f32;
+  float2x4 mat2x4_f32;
+  float3x2 mat3x2_f32;
+  float3x3 mat3x3_f32;
+  float3x4 mat3x4_f32;
+  float4x2 mat4x2_f32;
+  float4x3 mat4x3_f32;
+  float4x4 mat4x4_f32;
+  half2x2 mat2x2_f16;
+  half2x3 mat2x3_f16;
+  half2x4 mat2x4_f16;
+  half3x2 mat3x2_f16;
+  half3x3 mat3x3_f16;
+  half3x4 mat3x4_f16;
+  half4x2 mat4x2_f16;
+  half4x3 mat4x3_f16;
+  half4x4 mat4x4_f16;
+  tint_array<float3, 2> arr2_vec3_f32;
+  tint_array<half4x2, 2> arr2_mat4x2_f16;
+  Inner struct_inner;
+  tint_array<Inner, 4> array_struct_inner;
+};
+
+kernel void tint_symbol(const constant S_tint_packed_vec3* tint_symbol_1 [[buffer(0)]]) {
   float const scalar_f32 = (*(tint_symbol_1)).scalar_f32;
   int const scalar_i32 = (*(tint_symbol_1)).scalar_i32;
   uint const scalar_u32 = (*(tint_symbol_1)).scalar_u32;
@@ -90,24 +197,24 @@
   uint4 const vec4_u32 = (*(tint_symbol_1)).vec4_u32;
   half4 const vec4_f16 = (*(tint_symbol_1)).vec4_f16;
   float2x2 const mat2x2_f32 = (*(tint_symbol_1)).mat2x2_f32;
-  float2x3 const mat2x3_f32 = (*(tint_symbol_1)).mat2x3_f32;
+  float2x3 const mat2x3_f32 = tint_unpack_vec3_in_composite((*(tint_symbol_1)).mat2x3_f32);
   float2x4 const mat2x4_f32 = (*(tint_symbol_1)).mat2x4_f32;
   float3x2 const mat3x2_f32 = (*(tint_symbol_1)).mat3x2_f32;
-  float3x3 const mat3x3_f32 = (*(tint_symbol_1)).mat3x3_f32;
+  float3x3 const mat3x3_f32 = tint_unpack_vec3_in_composite_1((*(tint_symbol_1)).mat3x3_f32);
   float3x4 const mat3x4_f32 = (*(tint_symbol_1)).mat3x4_f32;
   float4x2 const mat4x2_f32 = (*(tint_symbol_1)).mat4x2_f32;
-  float4x3 const mat4x3_f32 = (*(tint_symbol_1)).mat4x3_f32;
+  float4x3 const mat4x3_f32 = tint_unpack_vec3_in_composite_2((*(tint_symbol_1)).mat4x3_f32);
   float4x4 const mat4x4_f32 = (*(tint_symbol_1)).mat4x4_f32;
   half2x2 const mat2x2_f16 = (*(tint_symbol_1)).mat2x2_f16;
-  half2x3 const mat2x3_f16 = (*(tint_symbol_1)).mat2x3_f16;
+  half2x3 const mat2x3_f16 = tint_unpack_vec3_in_composite_3((*(tint_symbol_1)).mat2x3_f16);
   half2x4 const mat2x4_f16 = (*(tint_symbol_1)).mat2x4_f16;
   half3x2 const mat3x2_f16 = (*(tint_symbol_1)).mat3x2_f16;
-  half3x3 const mat3x3_f16 = (*(tint_symbol_1)).mat3x3_f16;
+  half3x3 const mat3x3_f16 = tint_unpack_vec3_in_composite_4((*(tint_symbol_1)).mat3x3_f16);
   half3x4 const mat3x4_f16 = (*(tint_symbol_1)).mat3x4_f16;
   half4x2 const mat4x2_f16 = (*(tint_symbol_1)).mat4x2_f16;
-  half4x3 const mat4x3_f16 = (*(tint_symbol_1)).mat4x3_f16;
+  half4x3 const mat4x3_f16 = tint_unpack_vec3_in_composite_5((*(tint_symbol_1)).mat4x3_f16);
   half4x4 const mat4x4_f16 = (*(tint_symbol_1)).mat4x4_f16;
-  tint_array<float3, 2> const arr2_vec3_f32 = (*(tint_symbol_1)).arr2_vec3_f32;
+  tint_array<float3, 2> const arr2_vec3_f32 = tint_unpack_vec3_in_composite_6((*(tint_symbol_1)).arr2_vec3_f32);
   tint_array<half4x2, 2> const arr2_mat4x2_f16 = (*(tint_symbol_1)).arr2_mat4x2_f16;
   Inner const struct_inner = (*(tint_symbol_1)).struct_inner;
   tint_array<Inner, 4> const array_struct_inner = (*(tint_symbol_1)).array_struct_inner;
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_builtin.wgsl.expected.msl
index 5d165882..7c6987e 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_builtin.wgsl.expected.msl
@@ -16,8 +16,8 @@
 
 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]);
+  float const l = length((*(tint_symbol))[0][1].yx);
+  float const a = fabs((*(tint_symbol))[0][1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_fn.wgsl.expected.msl
index abc8d5d..9cd68ff 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_fn.wgsl.expected.msl
@@ -29,8 +29,8 @@
 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]);
+  c((*(tint_symbol))[1][0].yx);
+  d((*(tint_symbol))[1][0].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_private.wgsl.expected.msl
index c9084b3..bf586af 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_private.wgsl.expected.msl
@@ -18,7 +18,7 @@
   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] = (*(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_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_storage.wgsl.expected.msl
index 2a08172..cee92e4 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_storage.wgsl.expected.msl
@@ -17,7 +17,7 @@
 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] = (*(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_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_workgroup.wgsl.expected.msl
index 355d60e..ed5fb0c 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x2_f32/to_workgroup.wgsl.expected.msl
@@ -26,7 +26,7 @@
   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] = (*(tint_symbol_1))[0][1].yx;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
index 51600fc..1b83f6b 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,20 +14,41 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<half2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4> in) {
+  tint_array<half2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
 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<half2x3, 4>* tint_symbol_3 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 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<half2x3, 4> const l_a = *(tint_symbol_3);
-  half2x3 const l_a_i = (*(tint_symbol_3))[p_a_i_save];
-  half3 const l_a_i_i = (*(tint_symbol_3))[p_a_i_save][p_a_i_i_save];
+  tint_array<half2x3, 4> const l_a = tint_unpack_vec3_in_composite_1(*(tint_symbol_3));
+  half2x3 const l_a_i = tint_unpack_vec3_in_composite((*(tint_symbol_3))[p_a_i_save]);
+  half3 const l_a_i_i = half3((*(tint_symbol_3))[p_a_i_save][p_a_i_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl
index c864412..aceac06 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl
@@ -14,10 +14,31 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<half2x3, 4>* tint_symbol [[buffer(0)]]) {
-  tint_array<half2x3, 4> const l_a = *(tint_symbol);
-  half2x3 const l_a_i = (*(tint_symbol))[2];
-  half3 const l_a_i_i = (*(tint_symbol))[2][1];
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<half2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4> in) {
+  tint_array<half2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<half2x3, 4> const l_a = tint_unpack_vec3_in_composite_1(*(tint_symbol));
+  half2x3 const l_a_i = tint_unpack_vec3_in_composite((*(tint_symbol))[2]);
+  half3 const l_a_i_i = half3((*(tint_symbol))[2][1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_builtin.wgsl.expected.msl
index 205944f..83c7143 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_builtin.wgsl.expected.msl
@@ -14,10 +14,23 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<half2x3, 4>* tint_symbol [[buffer(0)]]) {
-  half3x2 const t = transpose((*(tint_symbol))[2]);
-  half const l = length(half3((*(tint_symbol))[0][1]).zxy);
-  half const a = fabs(half3((*(tint_symbol))[0][1]).zxy[0]);
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4>* tint_symbol [[buffer(0)]]) {
+  half3x2 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2]));
+  half const l = length(half3((*(tint_symbol))[0][1].elements).zxy);
+  half const a = fabs(half3((*(tint_symbol))[0][1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_fn.wgsl.expected.msl
index a1cefb5..d2da737 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_fn.wgsl.expected.msl
@@ -14,6 +14,27 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<half2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4> in) {
+  tint_array<half2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<half2x3, 4> a_1) {
 }
 
@@ -26,11 +47,11 @@
 void d(half f_1) {
 }
 
-kernel void f(const constant tint_array<half2x3, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  c(half3((*(tint_symbol))[1][0]).zxy);
-  d(half3((*(tint_symbol))[1][0]).zxy[0]);
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_1(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite((*(tint_symbol))[1]));
+  c(half3((*(tint_symbol))[1][0].elements).zxy);
+  d(half3((*(tint_symbol))[1][0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_private.wgsl.expected.msl
index f406191..e004d81 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_private.wgsl.expected.msl
@@ -14,12 +14,33 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<half2x3, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<half2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4> in) {
+  tint_array<half2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<half2x3, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = half3((*(tint_symbol_1))[0][1]).zxy;
-  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  tint_symbol = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]);
+  tint_symbol[1][0] = half3((*(tint_symbol_1))[0][1].elements).zxy;
+  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_storage.wgsl.expected.msl
index c24c518..afbab95 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_storage.wgsl.expected.msl
@@ -14,22 +14,43 @@
     T elements[N];
 };
 
-void assign_and_preserve_padding_1(device half2x3* const dest, half2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding(device tint_array<half2x3, 4>* const dest, tint_array<half2x3, 4> value) {
+tint_array<half2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4> in) {
+  tint_array<half2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_1(device tint_array<tint_packed_vec3_f16_array_element, 2>* const dest, half2x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+}
+
+void assign_and_preserve_padding(device tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4>* const dest, tint_array<half2x3, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<half2x3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<half2x3, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  (*(tint_symbol))[1][0] = half3((*(tint_symbol_1))[0][1]).zxy;
-  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+kernel void f(device tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4>* tint_symbol [[buffer(1)]], const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_1(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]));
+  (*(tint_symbol))[1][0].elements = packed_half3(half3((*(tint_symbol_1))[0][1].elements).zxy);
+  (*(tint_symbol))[1][0].elements[0] = (*(tint_symbol_1))[0][1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_workgroup.wgsl.expected.msl
index ac44a93..2d1d8b1 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f16/to_workgroup.wgsl.expected.msl
@@ -18,19 +18,40 @@
   tint_array<half2x3, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<half2x3, 4>* const tint_symbol, const constant tint_array<half2x3, 4>* const tint_symbol_1) {
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<half2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4> in) {
+  tint_array<half2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<half2x3, 4>* const tint_symbol, const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 4>* const tint_symbol_1) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     (*(tint_symbol))[i] = half2x3(half3(0.0h), half3(0.0h));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = half3((*(tint_symbol_1))[0][1]).zxy;
-  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
+  (*(tint_symbol))[1] = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]);
+  (*(tint_symbol))[1][0] = half3((*(tint_symbol_1))[0][1].elements).zxy;
+  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1].elements[0];
 }
 
-kernel void f(const constant tint_array<half2x3, 4>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 2>, 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<half2x3, 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/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
index ba4070a..1e8f133 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,20 +14,41 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4> in) {
+  tint_array<float2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
 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<float2x3, 4>* tint_symbol_3 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 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<float2x3, 4> const l_a = *(tint_symbol_3);
-  float2x3 const l_a_i = (*(tint_symbol_3))[p_a_i_save];
-  float3 const l_a_i_i = (*(tint_symbol_3))[p_a_i_save][p_a_i_i_save];
+  tint_array<float2x3, 4> const l_a = tint_unpack_vec3_in_composite_1(*(tint_symbol_3));
+  float2x3 const l_a_i = tint_unpack_vec3_in_composite((*(tint_symbol_3))[p_a_i_save]);
+  float3 const l_a_i_i = float3((*(tint_symbol_3))[p_a_i_save][p_a_i_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl
index 87f2879..e3655fb 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl
@@ -14,10 +14,31 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<float2x3, 4>* tint_symbol [[buffer(0)]]) {
-  tint_array<float2x3, 4> const l_a = *(tint_symbol);
-  float2x3 const l_a_i = (*(tint_symbol))[2];
-  float3 const l_a_i_i = (*(tint_symbol))[2][1];
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4> in) {
+  tint_array<float2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<float2x3, 4> const l_a = tint_unpack_vec3_in_composite_1(*(tint_symbol));
+  float2x3 const l_a_i = tint_unpack_vec3_in_composite((*(tint_symbol))[2]);
+  float3 const l_a_i_i = float3((*(tint_symbol))[2][1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_builtin.wgsl.expected.msl
index afe9bcc..ac6a186 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_builtin.wgsl.expected.msl
@@ -14,10 +14,23 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<float2x3, 4>* tint_symbol [[buffer(0)]]) {
-  float3x2 const t = transpose((*(tint_symbol))[2]);
-  float const l = length(float3((*(tint_symbol))[0][1]).zxy);
-  float const a = fabs(float3((*(tint_symbol))[0][1]).zxy[0]);
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4>* tint_symbol [[buffer(0)]]) {
+  float3x2 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2]));
+  float const l = length(float3((*(tint_symbol))[0][1].elements).zxy);
+  float const a = fabs(float3((*(tint_symbol))[0][1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_fn.wgsl.expected.msl
index e15cecf..471b2da 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_fn.wgsl.expected.msl
@@ -14,6 +14,27 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4> in) {
+  tint_array<float2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<float2x3, 4> a_1) {
 }
 
@@ -26,11 +47,11 @@
 void d(float f_1) {
 }
 
-kernel void f(const constant tint_array<float2x3, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  c(float3((*(tint_symbol))[1][0]).zxy);
-  d(float3((*(tint_symbol))[1][0]).zxy[0]);
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_1(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite((*(tint_symbol))[1]));
+  c(float3((*(tint_symbol))[1][0].elements).zxy);
+  d(float3((*(tint_symbol))[1][0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_private.wgsl.expected.msl
index 4fa5a85..8efe3f7 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_private.wgsl.expected.msl
@@ -14,12 +14,33 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<float2x3, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4> in) {
+  tint_array<float2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<float2x3, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = float3((*(tint_symbol_1))[0][1]).zxy;
-  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  tint_symbol = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]);
+  tint_symbol[1][0] = float3((*(tint_symbol_1))[0][1].elements).zxy;
+  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_storage.wgsl.expected.msl
index 09cbcc4..6adc305 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_storage.wgsl.expected.msl
@@ -14,22 +14,43 @@
     T elements[N];
 };
 
-void assign_and_preserve_padding_1(device float2x3* const dest, float2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding(device tint_array<float2x3, 4>* const dest, tint_array<float2x3, 4> value) {
+tint_array<float2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4> in) {
+  tint_array<float2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_1(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, float2x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+}
+
+void assign_and_preserve_padding(device tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4>* const dest, tint_array<float2x3, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<float2x3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<float2x3, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  (*(tint_symbol))[1][0] = float3((*(tint_symbol_1))[0][1]).zxy;
-  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+kernel void f(device tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4>* tint_symbol [[buffer(1)]], const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_1(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]));
+  (*(tint_symbol))[1][0].elements = packed_float3(float3((*(tint_symbol_1))[0][1].elements).zxy);
+  (*(tint_symbol))[1][0].elements[0] = (*(tint_symbol_1))[0][1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_workgroup.wgsl.expected.msl
index d63ff3d..3ff0a56 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x3_f32/to_workgroup.wgsl.expected.msl
@@ -18,19 +18,40 @@
   tint_array<float2x3, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<float2x3, 4>* const tint_symbol, const constant tint_array<float2x3, 4>* const tint_symbol_1) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float2x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4> in) {
+  tint_array<float2x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<float2x3, 4>* const tint_symbol, const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 4>* const tint_symbol_1) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     (*(tint_symbol))[i] = float2x3(float3(0.0f), float3(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = float3((*(tint_symbol_1))[0][1]).zxy;
-  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
+  (*(tint_symbol))[1] = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]);
+  (*(tint_symbol))[1][0] = float3((*(tint_symbol_1))[0][1].elements).zxy;
+  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1].elements[0];
 }
 
-kernel void f(const constant tint_array<float2x3, 4>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 2>, 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<float2x3, 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/mat2x4_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_builtin.wgsl.expected.msl
index d3fc1d4..ffdb249 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_builtin.wgsl.expected.msl
@@ -16,8 +16,8 @@
 
 kernel void f(const constant tint_array<half2x4, 4>* tint_symbol [[buffer(0)]]) {
   half4x2 const t = transpose((*(tint_symbol))[2]);
-  half const l = length(half4((*(tint_symbol))[0][1]).ywxz);
-  half const a = fabs(half4((*(tint_symbol))[0][1]).ywxz[0]);
+  half const l = length((*(tint_symbol))[0][1].ywxz);
+  half const a = fabs((*(tint_symbol))[0][1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_fn.wgsl.expected.msl
index c5b42bf..9d1c226 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_fn.wgsl.expected.msl
@@ -29,8 +29,8 @@
 kernel void f(const constant tint_array<half2x4, 4>* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  c(half4((*(tint_symbol))[1][0]).ywxz);
-  d(half4((*(tint_symbol))[1][0]).ywxz[0]);
+  c((*(tint_symbol))[1][0].ywxz);
+  d((*(tint_symbol))[1][0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_private.wgsl.expected.msl
index 2ebeac8..2187ceb 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_private.wgsl.expected.msl
@@ -18,7 +18,7 @@
   thread tint_array<half2x4, 4> tint_symbol = {};
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = half4((*(tint_symbol_1))[0][1]).ywxz;
+  tint_symbol[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_storage.wgsl.expected.msl
index 480eb6e..3fd47b1 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_storage.wgsl.expected.msl
@@ -17,7 +17,7 @@
 kernel void f(device tint_array<half2x4, 4>* tint_symbol [[buffer(1)]], const constant tint_array<half2x4, 4>* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = half4((*(tint_symbol_1))[0][1]).ywxz;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_workgroup.wgsl.expected.msl
index 3f9f184..01e1741 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x4_f16/to_workgroup.wgsl.expected.msl
@@ -26,7 +26,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = half4((*(tint_symbol_1))[0][1]).ywxz;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_builtin.wgsl.expected.msl
index 28b3230..8fe6098 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_builtin.wgsl.expected.msl
@@ -16,8 +16,8 @@
 
 kernel void f(const constant tint_array<float2x4, 4>* tint_symbol [[buffer(0)]]) {
   float4x2 const t = transpose((*(tint_symbol))[2]);
-  float const l = length(float4((*(tint_symbol))[0][1]).ywxz);
-  float const a = fabs(float4((*(tint_symbol))[0][1]).ywxz[0]);
+  float const l = length((*(tint_symbol))[0][1].ywxz);
+  float const a = fabs((*(tint_symbol))[0][1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_fn.wgsl.expected.msl
index 4280139..903aef5 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_fn.wgsl.expected.msl
@@ -29,8 +29,8 @@
 kernel void f(const constant tint_array<float2x4, 4>* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  c(float4((*(tint_symbol))[1][0]).ywxz);
-  d(float4((*(tint_symbol))[1][0]).ywxz[0]);
+  c((*(tint_symbol))[1][0].ywxz);
+  d((*(tint_symbol))[1][0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_private.wgsl.expected.msl
index f28eca1..147f578 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_private.wgsl.expected.msl
@@ -18,7 +18,7 @@
   thread tint_array<float2x4, 4> tint_symbol = {};
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = float4((*(tint_symbol_1))[0][1]).ywxz;
+  tint_symbol[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_storage.wgsl.expected.msl
index 859f287..c869d8c 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_storage.wgsl.expected.msl
@@ -17,7 +17,7 @@
 kernel void f(device tint_array<float2x4, 4>* tint_symbol [[buffer(1)]], const constant tint_array<float2x4, 4>* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = float4((*(tint_symbol_1))[0][1]).ywxz;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_workgroup.wgsl.expected.msl
index d84ba92..3ff1615 100644
--- a/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat2x4_f32/to_workgroup.wgsl.expected.msl
@@ -26,7 +26,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = float4((*(tint_symbol_1))[0][1]).ywxz;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
index 33dacb2..b5bbbfe 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,20 +14,41 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4> in) {
+  tint_array<float3x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
 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<float3x3, 4>* tint_symbol_3 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 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<float3x3, 4> const l_a = *(tint_symbol_3);
-  float3x3 const l_a_i = (*(tint_symbol_3))[p_a_i_save];
-  float3 const l_a_i_i = (*(tint_symbol_3))[p_a_i_save][p_a_i_i_save];
+  tint_array<float3x3, 4> const l_a = tint_unpack_vec3_in_composite_1(*(tint_symbol_3));
+  float3x3 const l_a_i = tint_unpack_vec3_in_composite((*(tint_symbol_3))[p_a_i_save]);
+  float3 const l_a_i_i = float3((*(tint_symbol_3))[p_a_i_save][p_a_i_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl
index 05a9ea9..376cd23 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl
@@ -14,10 +14,31 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<float3x3, 4>* tint_symbol [[buffer(0)]]) {
-  tint_array<float3x3, 4> const l_a = *(tint_symbol);
-  float3x3 const l_a_i = (*(tint_symbol))[2];
-  float3 const l_a_i_i = (*(tint_symbol))[2][1];
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4> in) {
+  tint_array<float3x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<float3x3, 4> const l_a = tint_unpack_vec3_in_composite_1(*(tint_symbol));
+  float3x3 const l_a_i = tint_unpack_vec3_in_composite((*(tint_symbol))[2]);
+  float3 const l_a_i_i = float3((*(tint_symbol))[2][1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_builtin.wgsl.expected.msl
index 16b5d79..1a1377b 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_builtin.wgsl.expected.msl
@@ -14,10 +14,23 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<float3x3, 4>* tint_symbol [[buffer(0)]]) {
-  float3x3 const t = transpose((*(tint_symbol))[2]);
-  float const l = length(float3((*(tint_symbol))[0][1]).zxy);
-  float const a = fabs(float3((*(tint_symbol))[0][1]).zxy[0]);
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4>* tint_symbol [[buffer(0)]]) {
+  float3x3 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2]));
+  float const l = length(float3((*(tint_symbol))[0][1].elements).zxy);
+  float const a = fabs(float3((*(tint_symbol))[0][1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_fn.wgsl.expected.msl
index 15297bd..24d26c0 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_fn.wgsl.expected.msl
@@ -14,6 +14,27 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4> in) {
+  tint_array<float3x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<float3x3, 4> a_1) {
 }
 
@@ -26,11 +47,11 @@
 void d(float f_1) {
 }
 
-kernel void f(const constant tint_array<float3x3, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  c(float3((*(tint_symbol))[1][0]).zxy);
-  d(float3((*(tint_symbol))[1][0]).zxy[0]);
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_1(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite((*(tint_symbol))[1]));
+  c(float3((*(tint_symbol))[1][0].elements).zxy);
+  d(float3((*(tint_symbol))[1][0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_private.wgsl.expected.msl
index 0c7a2db..591e132 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_private.wgsl.expected.msl
@@ -14,12 +14,33 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<float3x3, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4> in) {
+  tint_array<float3x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<float3x3, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = float3((*(tint_symbol_1))[0][1]).zxy;
-  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  tint_symbol = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]);
+  tint_symbol[1][0] = float3((*(tint_symbol_1))[0][1].elements).zxy;
+  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_storage.wgsl.expected.msl
index 39aa2fc..e77dbf1 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_storage.wgsl.expected.msl
@@ -14,23 +14,44 @@
     T elements[N];
 };
 
-void assign_and_preserve_padding_1(device float3x3* const dest, float3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding(device tint_array<float3x3, 4>* const dest, tint_array<float3x3, 4> value) {
+tint_array<float3x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4> in) {
+  tint_array<float3x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_1(device tint_array<tint_packed_vec3_f32_array_element, 3>* const dest, float3x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+}
+
+void assign_and_preserve_padding(device tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4>* const dest, tint_array<float3x3, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<float3x3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<float3x3, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  (*(tint_symbol))[1][0] = float3((*(tint_symbol_1))[0][1]).zxy;
-  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+kernel void f(device tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4>* tint_symbol [[buffer(1)]], const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_1(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]));
+  (*(tint_symbol))[1][0].elements = packed_float3(float3((*(tint_symbol_1))[0][1].elements).zxy);
+  (*(tint_symbol))[1][0].elements[0] = (*(tint_symbol_1))[0][1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_workgroup.wgsl.expected.msl
index d1bf3a7..e1653cd 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x3_f32/to_workgroup.wgsl.expected.msl
@@ -18,19 +18,40 @@
   tint_array<float3x3, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<float3x3, 4>* const tint_symbol, const constant tint_array<float3x3, 4>* const tint_symbol_1) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float3x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4> in) {
+  tint_array<float3x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<float3x3, 4>* const tint_symbol, const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 4>* const tint_symbol_1) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     (*(tint_symbol))[i] = float3x3(float3(0.0f), float3(0.0f), float3(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = float3((*(tint_symbol_1))[0][1]).zxy;
-  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
+  (*(tint_symbol))[1] = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]);
+  (*(tint_symbol))[1][0] = float3((*(tint_symbol_1))[0][1].elements).zxy;
+  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1].elements[0];
 }
 
-kernel void f(const constant tint_array<float3x3, 4>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 3>, 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<float3x3, 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/mat3x4_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_builtin.wgsl.expected.msl
index e7f5cd5..4d23983 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_builtin.wgsl.expected.msl
@@ -16,8 +16,8 @@
 
 kernel void f(const constant tint_array<float3x4, 4>* tint_symbol [[buffer(0)]]) {
   float4x3 const t = transpose((*(tint_symbol))[2]);
-  float const l = length(float4((*(tint_symbol))[0][1]).ywxz);
-  float const a = fabs(float4((*(tint_symbol))[0][1]).ywxz[0]);
+  float const l = length((*(tint_symbol))[0][1].ywxz);
+  float const a = fabs((*(tint_symbol))[0][1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_fn.wgsl.expected.msl
index cc6a3b7..e78e766 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_fn.wgsl.expected.msl
@@ -29,8 +29,8 @@
 kernel void f(const constant tint_array<float3x4, 4>* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  c(float4((*(tint_symbol))[1][0]).ywxz);
-  d(float4((*(tint_symbol))[1][0]).ywxz[0]);
+  c((*(tint_symbol))[1][0].ywxz);
+  d((*(tint_symbol))[1][0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_private.wgsl.expected.msl
index 478a68e..3ebf98c 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_private.wgsl.expected.msl
@@ -18,7 +18,7 @@
   thread tint_array<float3x4, 4> tint_symbol = {};
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = float4((*(tint_symbol_1))[0][1]).ywxz;
+  tint_symbol[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_storage.wgsl.expected.msl
index d659b7b..1ba2aa9 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_storage.wgsl.expected.msl
@@ -17,7 +17,7 @@
 kernel void f(device tint_array<float3x4, 4>* tint_symbol [[buffer(1)]], const constant tint_array<float3x4, 4>* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = float4((*(tint_symbol_1))[0][1]).ywxz;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_workgroup.wgsl.expected.msl
index f955a90..7351a09 100644
--- a/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat3x4_f32/to_workgroup.wgsl.expected.msl
@@ -26,7 +26,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = float4((*(tint_symbol_1))[0][1]).ywxz;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_builtin.wgsl.expected.msl
index 58f8a98..b607d41 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_builtin.wgsl.expected.msl
@@ -16,8 +16,8 @@
 
 kernel void f(const constant tint_array<half4x2, 4>* tint_symbol [[buffer(0)]]) {
   half2x4 const t = transpose((*(tint_symbol))[2]);
-  half const l = length(half2((*(tint_symbol))[0][1]).yx);
-  half const a = fabs(half2((*(tint_symbol))[0][1]).yx[0]);
+  half const l = length((*(tint_symbol))[0][1].yx);
+  half const a = fabs((*(tint_symbol))[0][1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_fn.wgsl.expected.msl
index 66b4cf5..7c971e4 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_fn.wgsl.expected.msl
@@ -29,8 +29,8 @@
 kernel void f(const constant tint_array<half4x2, 4>* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  c(half2((*(tint_symbol))[1][0]).yx);
-  d(half2((*(tint_symbol))[1][0]).yx[0]);
+  c((*(tint_symbol))[1][0].yx);
+  d((*(tint_symbol))[1][0].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_private.wgsl.expected.msl
index 0b1f07b..d7b60af 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_private.wgsl.expected.msl
@@ -18,7 +18,7 @@
   thread tint_array<half4x2, 4> tint_symbol = {};
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = half2((*(tint_symbol_1))[0][1]).yx;
+  tint_symbol[1][0] = (*(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_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_storage.wgsl.expected.msl
index 2b7f2a2..f7abcba 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_storage.wgsl.expected.msl
@@ -17,7 +17,7 @@
 kernel void f(device tint_array<half4x2, 4>* tint_symbol [[buffer(1)]], const constant tint_array<half4x2, 4>* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = half2((*(tint_symbol_1))[0][1]).yx;
+  (*(tint_symbol))[1][0] = (*(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_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_workgroup.wgsl.expected.msl
index 2fe9b38..0d29883 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x2_f16/to_workgroup.wgsl.expected.msl
@@ -26,7 +26,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = half2((*(tint_symbol_1))[0][1]).yx;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].yx;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_builtin.wgsl.expected.msl
index b8aac7e..3d31143 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_builtin.wgsl.expected.msl
@@ -16,8 +16,8 @@
 
 kernel void f(const constant tint_array<float4x2, 4>* tint_symbol [[buffer(0)]]) {
   float2x4 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]);
+  float const l = length((*(tint_symbol))[0][1].yx);
+  float const a = fabs((*(tint_symbol))[0][1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_fn.wgsl.expected.msl
index 4119424..c46a099 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_fn.wgsl.expected.msl
@@ -29,8 +29,8 @@
 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]);
+  c((*(tint_symbol))[1][0].yx);
+  d((*(tint_symbol))[1][0].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_private.wgsl.expected.msl
index 03a47ff..5aec084 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_private.wgsl.expected.msl
@@ -18,7 +18,7 @@
   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] = (*(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_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_storage.wgsl.expected.msl
index a3aff13..9f61df0 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_storage.wgsl.expected.msl
@@ -17,7 +17,7 @@
 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] = (*(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_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_workgroup.wgsl.expected.msl
index 9a7cc49..4f1df19 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x2_f32/to_workgroup.wgsl.expected.msl
@@ -26,7 +26,7 @@
   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] = (*(tint_symbol_1))[0][1].yx;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
index 5f57b03..e8d3f21 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,20 +14,41 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<half4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4> in) {
+  tint_array<half4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
 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<half4x3, 4>* tint_symbol_3 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 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<half4x3, 4> const l_a = *(tint_symbol_3);
-  half4x3 const l_a_i = (*(tint_symbol_3))[p_a_i_save];
-  half3 const l_a_i_i = (*(tint_symbol_3))[p_a_i_save][p_a_i_i_save];
+  tint_array<half4x3, 4> const l_a = tint_unpack_vec3_in_composite_1(*(tint_symbol_3));
+  half4x3 const l_a_i = tint_unpack_vec3_in_composite((*(tint_symbol_3))[p_a_i_save]);
+  half3 const l_a_i_i = half3((*(tint_symbol_3))[p_a_i_save][p_a_i_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl
index b7999ab..6a4bf26 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl
@@ -14,10 +14,31 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<half4x3, 4>* tint_symbol [[buffer(0)]]) {
-  tint_array<half4x3, 4> const l_a = *(tint_symbol);
-  half4x3 const l_a_i = (*(tint_symbol))[2];
-  half3 const l_a_i_i = (*(tint_symbol))[2][1];
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<half4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4> in) {
+  tint_array<half4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<half4x3, 4> const l_a = tint_unpack_vec3_in_composite_1(*(tint_symbol));
+  half4x3 const l_a_i = tint_unpack_vec3_in_composite((*(tint_symbol))[2]);
+  half3 const l_a_i_i = half3((*(tint_symbol))[2][1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_builtin.wgsl.expected.msl
index 39b9c1c..d29c64f 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_builtin.wgsl.expected.msl
@@ -14,10 +14,23 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<half4x3, 4>* tint_symbol [[buffer(0)]]) {
-  half3x4 const t = transpose((*(tint_symbol))[2]);
-  half const l = length(half3((*(tint_symbol))[0][1]).zxy);
-  half const a = fabs(half3((*(tint_symbol))[0][1]).zxy[0]);
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4>* tint_symbol [[buffer(0)]]) {
+  half3x4 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2]));
+  half const l = length(half3((*(tint_symbol))[0][1].elements).zxy);
+  half const a = fabs(half3((*(tint_symbol))[0][1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_fn.wgsl.expected.msl
index ed20c74..2eb0517 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_fn.wgsl.expected.msl
@@ -14,6 +14,27 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<half4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4> in) {
+  tint_array<half4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<half4x3, 4> a_1) {
 }
 
@@ -26,11 +47,11 @@
 void d(half f_1) {
 }
 
-kernel void f(const constant tint_array<half4x3, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  c(half3((*(tint_symbol))[1][0]).zxy);
-  d(half3((*(tint_symbol))[1][0]).zxy[0]);
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_1(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite((*(tint_symbol))[1]));
+  c(half3((*(tint_symbol))[1][0].elements).zxy);
+  d(half3((*(tint_symbol))[1][0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_private.wgsl.expected.msl
index 89c4a04..0f56e7a 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_private.wgsl.expected.msl
@@ -14,12 +14,33 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<half4x3, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<half4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4> in) {
+  tint_array<half4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<half4x3, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = half3((*(tint_symbol_1))[0][1]).zxy;
-  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  tint_symbol = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]);
+  tint_symbol[1][0] = half3((*(tint_symbol_1))[0][1].elements).zxy;
+  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_storage.wgsl.expected.msl
index 3e19776..daef935 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_storage.wgsl.expected.msl
@@ -14,24 +14,45 @@
     T elements[N];
 };
 
-void assign_and_preserve_padding_1(device half4x3* const dest, half4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding(device tint_array<half4x3, 4>* const dest, tint_array<half4x3, 4> value) {
+tint_array<half4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4> in) {
+  tint_array<half4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_1(device tint_array<tint_packed_vec3_f16_array_element, 4>* const dest, half4x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
+  (*(dest))[3u].elements = packed_half3(value[3u]);
+}
+
+void assign_and_preserve_padding(device tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4>* const dest, tint_array<half4x3, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<half4x3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<half4x3, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  (*(tint_symbol))[1][0] = half3((*(tint_symbol_1))[0][1]).zxy;
-  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+kernel void f(device tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4>* tint_symbol [[buffer(1)]], const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_1(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]));
+  (*(tint_symbol))[1][0].elements = packed_half3(half3((*(tint_symbol_1))[0][1].elements).zxy);
+  (*(tint_symbol))[1][0].elements[0] = (*(tint_symbol_1))[0][1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_workgroup.wgsl.expected.msl
index 5db2fda..67f78b0 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f16/to_workgroup.wgsl.expected.msl
@@ -18,19 +18,40 @@
   tint_array<half4x3, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<half4x3, 4>* const tint_symbol, const constant tint_array<half4x3, 4>* const tint_symbol_1) {
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<half4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4> in) {
+  tint_array<half4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<half4x3, 4>* const tint_symbol, const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 4>* const tint_symbol_1) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     (*(tint_symbol))[i] = half4x3(half3(0.0h), half3(0.0h), half3(0.0h), half3(0.0h));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = half3((*(tint_symbol_1))[0][1]).zxy;
-  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
+  (*(tint_symbol))[1] = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]);
+  (*(tint_symbol))[1][0] = half3((*(tint_symbol_1))[0][1].elements).zxy;
+  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1].elements[0];
 }
 
-kernel void f(const constant tint_array<half4x3, 4>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f16_array_element, 4>, 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<half4x3, 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/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
index 0c60210..4f340ac 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,20 +14,41 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4> in) {
+  tint_array<float4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
 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<float4x3, 4>* tint_symbol_3 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 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<float4x3, 4> const l_a = *(tint_symbol_3);
-  float4x3 const l_a_i = (*(tint_symbol_3))[p_a_i_save];
-  float3 const l_a_i_i = (*(tint_symbol_3))[p_a_i_save][p_a_i_i_save];
+  tint_array<float4x3, 4> const l_a = tint_unpack_vec3_in_composite_1(*(tint_symbol_3));
+  float4x3 const l_a_i = tint_unpack_vec3_in_composite((*(tint_symbol_3))[p_a_i_save]);
+  float3 const l_a_i_i = float3((*(tint_symbol_3))[p_a_i_save][p_a_i_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl
index 0b5148e..ade51a6 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl
@@ -14,10 +14,31 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<float4x3, 4>* tint_symbol [[buffer(0)]]) {
-  tint_array<float4x3, 4> const l_a = *(tint_symbol);
-  float4x3 const l_a_i = (*(tint_symbol))[2];
-  float3 const l_a_i_i = (*(tint_symbol))[2][1];
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4> in) {
+  tint_array<float4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<float4x3, 4> const l_a = tint_unpack_vec3_in_composite_1(*(tint_symbol));
+  float4x3 const l_a_i = tint_unpack_vec3_in_composite((*(tint_symbol))[2]);
+  float3 const l_a_i_i = float3((*(tint_symbol))[2][1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_builtin.wgsl.expected.msl
index 3edd8e3..83f80b7 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_builtin.wgsl.expected.msl
@@ -14,10 +14,23 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<float4x3, 4>* tint_symbol [[buffer(0)]]) {
-  float3x4 const t = transpose((*(tint_symbol))[2]);
-  float const l = length(float3((*(tint_symbol))[0][1]).zxy);
-  float const a = fabs(float3((*(tint_symbol))[0][1]).zxy[0]);
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4>* tint_symbol [[buffer(0)]]) {
+  float3x4 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2]));
+  float const l = length(float3((*(tint_symbol))[0][1].elements).zxy);
+  float const a = fabs(float3((*(tint_symbol))[0][1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_fn.wgsl.expected.msl
index f2f446e..471d98e 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_fn.wgsl.expected.msl
@@ -14,6 +14,27 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4> in) {
+  tint_array<float4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<float4x3, 4> a_1) {
 }
 
@@ -26,11 +47,11 @@
 void d(float f_1) {
 }
 
-kernel void f(const constant tint_array<float4x3, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  c(float3((*(tint_symbol))[1][0]).zxy);
-  d(float3((*(tint_symbol))[1][0]).zxy[0]);
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_1(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite((*(tint_symbol))[1]));
+  c(float3((*(tint_symbol))[1][0].elements).zxy);
+  d(float3((*(tint_symbol))[1][0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_private.wgsl.expected.msl
index cfb8e04..bfb7be1 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_private.wgsl.expected.msl
@@ -14,12 +14,33 @@
     T elements[N];
 };
 
-kernel void f(const constant tint_array<float4x3, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4> in) {
+  tint_array<float4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<float4x3, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = float3((*(tint_symbol_1))[0][1]).zxy;
-  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  tint_symbol = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]);
+  tint_symbol[1][0] = float3((*(tint_symbol_1))[0][1].elements).zxy;
+  tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_storage.wgsl.expected.msl
index d9eba4b..bdc44ad 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_storage.wgsl.expected.msl
@@ -14,24 +14,45 @@
     T elements[N];
 };
 
-void assign_and_preserve_padding_1(device float4x3* const dest, float4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding(device tint_array<float4x3, 4>* const dest, tint_array<float4x3, 4> value) {
+tint_array<float4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4> in) {
+  tint_array<float4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_1(device tint_array<tint_packed_vec3_f32_array_element, 4>* const dest, float4x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+  (*(dest))[3u].elements = packed_float3(value[3u]);
+}
+
+void assign_and_preserve_padding(device tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4>* const dest, tint_array<float4x3, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<float4x3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<float4x3, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  (*(tint_symbol))[1][0] = float3((*(tint_symbol_1))[0][1]).zxy;
-  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+kernel void f(device tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4>* tint_symbol [[buffer(1)]], const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_1(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]));
+  (*(tint_symbol))[1][0].elements = packed_float3(float3((*(tint_symbol_1))[0][1].elements).zxy);
+  (*(tint_symbol))[1][0].elements[0] = (*(tint_symbol_1))[0][1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_workgroup.wgsl.expected.msl
index b6e7f8c..e178ef7 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x3_f32/to_workgroup.wgsl.expected.msl
@@ -18,19 +18,40 @@
   tint_array<float4x3, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<float4x3, 4>* const tint_symbol, const constant tint_array<float4x3, 4>* const tint_symbol_1) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+tint_array<float4x3, 4> tint_unpack_vec3_in_composite_1(tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4> in) {
+  tint_array<float4x3, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<float4x3, 4>* const tint_symbol, const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 4>* const tint_symbol_1) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     (*(tint_symbol))[i] = float4x3(float3(0.0f), float3(0.0f), float3(0.0f), float3(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = float3((*(tint_symbol_1))[0][1]).zxy;
-  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
+  (*(tint_symbol))[1] = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2]);
+  (*(tint_symbol))[1][0] = float3((*(tint_symbol_1))[0][1].elements).zxy;
+  (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1].elements[0];
 }
 
-kernel void f(const constant tint_array<float4x3, 4>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_array<tint_packed_vec3_f32_array_element, 4>, 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<float4x3, 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/mat4x4_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_builtin.wgsl.expected.msl
index f1b041d..f761031 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_builtin.wgsl.expected.msl
@@ -16,8 +16,8 @@
 
 kernel void f(const constant tint_array<half4x4, 4>* tint_symbol [[buffer(0)]]) {
   half4x4 const t = transpose((*(tint_symbol))[2]);
-  half const l = length(half4((*(tint_symbol))[0][1]).ywxz);
-  half const a = fabs(half4((*(tint_symbol))[0][1]).ywxz[0]);
+  half const l = length((*(tint_symbol))[0][1].ywxz);
+  half const a = fabs((*(tint_symbol))[0][1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_fn.wgsl.expected.msl
index 7824fac..b87067b 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_fn.wgsl.expected.msl
@@ -29,8 +29,8 @@
 kernel void f(const constant tint_array<half4x4, 4>* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  c(half4((*(tint_symbol))[1][0]).ywxz);
-  d(half4((*(tint_symbol))[1][0]).ywxz[0]);
+  c((*(tint_symbol))[1][0].ywxz);
+  d((*(tint_symbol))[1][0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_private.wgsl.expected.msl
index 7cc2442..f6a14dc 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_private.wgsl.expected.msl
@@ -18,7 +18,7 @@
   thread tint_array<half4x4, 4> tint_symbol = {};
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = half4((*(tint_symbol_1))[0][1]).ywxz;
+  tint_symbol[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_storage.wgsl.expected.msl
index a1a1e39..5a24c4f 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_storage.wgsl.expected.msl
@@ -17,7 +17,7 @@
 kernel void f(device tint_array<half4x4, 4>* tint_symbol [[buffer(1)]], const constant tint_array<half4x4, 4>* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = half4((*(tint_symbol_1))[0][1]).ywxz;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_workgroup.wgsl.expected.msl
index bd1f293..e22baa8 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x4_f16/to_workgroup.wgsl.expected.msl
@@ -26,7 +26,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = half4((*(tint_symbol_1))[0][1]).ywxz;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_builtin.wgsl.expected.msl
index b7a398b..d862de4 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_builtin.wgsl.expected.msl
@@ -16,8 +16,8 @@
 
 kernel void f(const constant tint_array<float4x4, 4>* tint_symbol [[buffer(0)]]) {
   float4x4 const t = transpose((*(tint_symbol))[2]);
-  float const l = length(float4((*(tint_symbol))[0][1]).ywxz);
-  float const a = fabs(float4((*(tint_symbol))[0][1]).ywxz[0]);
+  float const l = length((*(tint_symbol))[0][1].ywxz);
+  float const a = fabs((*(tint_symbol))[0][1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_fn.wgsl.expected.msl
index 1d08324..5638c28 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_fn.wgsl.expected.msl
@@ -29,8 +29,8 @@
 kernel void f(const constant tint_array<float4x4, 4>* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  c(float4((*(tint_symbol))[1][0]).ywxz);
-  d(float4((*(tint_symbol))[1][0]).ywxz[0]);
+  c((*(tint_symbol))[1][0].ywxz);
+  d((*(tint_symbol))[1][0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_private.wgsl.expected.msl
index 9e7e72c..eb69666 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_private.wgsl.expected.msl
@@ -18,7 +18,7 @@
   thread tint_array<float4x4, 4> tint_symbol = {};
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[1][0] = float4((*(tint_symbol_1))[0][1]).ywxz;
+  tint_symbol[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   tint_symbol[1][0][0] = (*(tint_symbol_1))[0][1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_storage.wgsl.expected.msl
index 99338a6..10354d0 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_storage.wgsl.expected.msl
@@ -17,7 +17,7 @@
 kernel void f(device tint_array<float4x4, 4>* tint_symbol [[buffer(1)]], const constant tint_array<float4x4, 4>* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = float4((*(tint_symbol_1))[0][1]).ywxz;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_workgroup.wgsl.expected.msl
index 2e14882..eb1b0fe 100644
--- a/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/array/mat4x4_f32/to_workgroup.wgsl.expected.msl
@@ -26,7 +26,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[2];
-  (*(tint_symbol))[1][0] = float4((*(tint_symbol_1))[0][1]).ywxz;
+  (*(tint_symbol))[1][0] = (*(tint_symbol_1))[0][1].ywxz;
   (*(tint_symbol))[1][0][0] = (*(tint_symbol_1))[0][1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_builtin.wgsl.expected.msl
index f2a8adb..1d080df 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_builtin.wgsl.expected.msl
@@ -24,8 +24,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   half2x2 const t = transpose((*(tint_symbol))[2].m);
-  half const l = length(half2((*(tint_symbol))[0].m[1]).yx);
-  half const a = fabs(half2((*(tint_symbol))[0].m[1]).yx[0]);
+  half const l = length((*(tint_symbol))[0].m[1].yx);
+  half const a = fabs((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_fn.wgsl.expected.msl
index 377d72a..a5d0ade 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_fn.wgsl.expected.msl
@@ -41,8 +41,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(half2((*(tint_symbol))[0].m[1]).yx);
-  e(half2((*(tint_symbol))[0].m[1]).yx[0]);
+  d((*(tint_symbol))[0].m[1].yx);
+  e((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_private.wgsl.expected.msl
index a5d8527..37fd98a 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_private.wgsl.expected.msl
@@ -27,7 +27,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = half2((*(tint_symbol_1))[0].m[1]).yx;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_storage.wgsl.expected.msl
index 3ebbf2b..1cc33f8 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_storage.wgsl.expected.msl
@@ -38,7 +38,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = half2((*(tint_symbol_1))[0].m[1]).yx;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_workgroup.wgsl.expected.msl
index 6411d47..5b50787 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2_f16/to_workgroup.wgsl.expected.msl
@@ -36,7 +36,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = half2((*(tint_symbol_2))[0].m[1]).yx;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].yx;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_builtin.wgsl.expected.msl
index b2a40b3..6a91752 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_builtin.wgsl.expected.msl
@@ -25,8 +25,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   float2x2 const t = transpose((*(tint_symbol))[2].m);
-  float const l = length(float2((*(tint_symbol))[0].m[1]).yx);
-  float const a = fabs(float2((*(tint_symbol))[0].m[1]).yx[0]);
+  float const l = length((*(tint_symbol))[0].m[1].yx);
+  float const a = fabs((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_fn.wgsl.expected.msl
index caa1fb9..1674698 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_fn.wgsl.expected.msl
@@ -42,8 +42,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(float2((*(tint_symbol))[0].m[1]).yx);
-  e(float2((*(tint_symbol))[0].m[1]).yx[0]);
+  d((*(tint_symbol))[0].m[1].yx);
+  e((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_private.wgsl.expected.msl
index a1c599c..db4c6db 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_private.wgsl.expected.msl
@@ -28,7 +28,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = float2((*(tint_symbol_1))[0].m[1]).yx;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_storage.wgsl.expected.msl
index 1603638..8165cd0 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_storage.wgsl.expected.msl
@@ -39,7 +39,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = float2((*(tint_symbol_1))[0].m[1]).yx;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_workgroup.wgsl.expected.msl
index 667db2d..f2303f8 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x2_f32/to_workgroup.wgsl.expected.msl
@@ -37,7 +37,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = float2((*(tint_symbol_2))[0].m[1]).yx;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].yx;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
index 322c363..8afb558 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,36 +14,85 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ half2x3 m;
-  /* 0x0010 */ tint_array<int8_t, 48> tint_pad;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f16_array_element, 2> m;
+  /* 0x0010 */ tint_array<int8_t, 48> tint_pad_1;
 };
 
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  half2x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+struct Outer {
+  tint_array<Inner, 4> a;
+};
+
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
 int i() {
   thread int tint_symbol_4 = 0;
   tint_symbol_4 = as_type<int>((as_type<uint>(tint_symbol_4) + as_type<uint>(1)));
   return tint_symbol_4;
 }
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol_5 [[buffer(0)]]) {
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol_5 [[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_a_i_save = tint_symbol_1;
   int const tint_symbol_2 = i();
   int const p_a_i_a_i_m_i_save = tint_symbol_2;
-  tint_array<Outer, 4> const l_a = *(tint_symbol_5);
-  Outer const l_a_i = (*(tint_symbol_5))[p_a_i_save];
-  tint_array<Inner, 4> const l_a_i_a = (*(tint_symbol_5))[p_a_i_save].a;
-  Inner const l_a_i_a_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save];
-  half2x3 const l_a_i_a_i_m = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m;
-  half3 const l_a_i_a_i_m_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save];
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol_5));
+  Outer const l_a_i = tint_unpack_vec3_in_composite_3((*(tint_symbol_5))[p_a_i_save]);
+  tint_array<Inner, 4> const l_a_i_a = tint_unpack_vec3_in_composite_2((*(tint_symbol_5))[p_a_i_save].a);
+  Inner const l_a_i_a_i = tint_unpack_vec3_in_composite_1((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save]);
+  half2x3 const l_a_i_a_i_m = tint_unpack_vec3_in_composite((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m);
+  half3 const l_a_i_a_i_m_i = half3((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements);
   int const tint_symbol_3 = i();
-  half const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save][tint_symbol_3];
+  half const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements[tint_symbol_3];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl
index 646eacf..0e5d8a6 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl
@@ -14,23 +14,72 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ half2x3 m;
-  /* 0x0010 */ tint_array<int8_t, 48> tint_pad;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f16_array_element, 2> m;
+  /* 0x0010 */ tint_array<int8_t, 48> tint_pad_1;
+};
+
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  half2x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+  tint_array<Inner, 4> a;
 };
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol [[buffer(0)]]) {
-  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;
-  Inner const l_a_3_a_2 = (*(tint_symbol))[3].a[2];
-  half2x3 const l_a_3_a_2_m = (*(tint_symbol))[3].a[2].m;
-  half3 const l_a_3_a_2_m_1 = (*(tint_symbol))[3].a[2].m[1];
-  half const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1][0];
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol));
+  Outer const l_a_3 = tint_unpack_vec3_in_composite_3((*(tint_symbol))[3]);
+  tint_array<Inner, 4> const l_a_3_a = tint_unpack_vec3_in_composite_2((*(tint_symbol))[3].a);
+  Inner const l_a_3_a_2 = tint_unpack_vec3_in_composite_1((*(tint_symbol))[3].a[2]);
+  half2x3 const l_a_3_a_2_m = tint_unpack_vec3_in_composite((*(tint_symbol))[3].a[2].m);
+  half3 const l_a_3_a_2_m_1 = half3((*(tint_symbol))[3].a[2].m[1].elements);
+  half const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_builtin.wgsl.expected.msl
index 7f897eb..e71cfaa 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_builtin.wgsl.expected.msl
@@ -14,19 +14,38 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half2x3 m;
-  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  half3x2 const t = transpose((*(tint_symbol))[2].m);
-  half const l = length(half3((*(tint_symbol))[0].m[1]).zxy);
-  half const a = fabs(half3((*(tint_symbol))[0].m[1]).zxy[0]);
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 2> m;
+  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  half2x3 m;
+  int after;
+};
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  half3x2 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  half const l = length(half3((*(tint_symbol))[0].m[1].elements).zxy);
+  half const a = fabs(half3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_fn.wgsl.expected.msl
index 9031d44..0fc03a4 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_fn.wgsl.expected.msl
@@ -14,15 +14,50 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half2x3 m;
-  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 2> m;
+  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  half2x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<S, 4> a_1) {
 }
 
@@ -38,12 +73,12 @@
 void e(half f_1) {
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[2]);
-  c((*(tint_symbol))[2].m);
-  d(half3((*(tint_symbol))[0].m[1]).zxy);
-  e(half3((*(tint_symbol))[0].m[1]).zxy[0]);
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_2(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite_1((*(tint_symbol))[2]));
+  c(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  d(half3((*(tint_symbol))[0].m[1].elements).zxy);
+  e(half3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_private.wgsl.expected.msl
index 53a16ab..30e2743 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_private.wgsl.expected.msl
@@ -14,21 +14,56 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half2x3 m;
-  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 2> m;
+  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  half2x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<S, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = half3((*(tint_symbol_1))[0].m[1]).zxy;
+  tint_symbol = tint_unpack_vec3_in_composite_2(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]);
+  tint_symbol[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m);
+  tint_symbol[1].m[0] = half3((*(tint_symbol_1))[0].m[1].elements).zxy;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_storage.wgsl.expected.msl
index a574012..fe2e439 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_storage.wgsl.expected.msl
@@ -14,37 +14,72 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half2x3 m;
-  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-void assign_and_preserve_padding_2(device half2x3* const dest, half2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 2> m;
+  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding_1(device S* const dest, S value) {
+struct S {
+  int before;
+  half2x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_2(device tint_array<tint_packed_vec3_f16_array_element, 2>* const dest, half2x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+}
+
+void assign_and_preserve_padding_1(device S_tint_packed_vec3* const dest, S value) {
   (*(dest)).before = value.before;
   assign_and_preserve_padding_2(&((*(dest)).m), value.m);
   (*(dest)).after = value.after;
 }
 
-void assign_and_preserve_padding(device tint_array<S, 4>* const dest, tint_array<S, 4> value) {
+void assign_and_preserve_padding(device tint_array<S_tint_packed_vec3, 4>* const dest, tint_array<S, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<S, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), (*(tint_symbol_1))[2].m);
-  (*(tint_symbol))[1].m[0] = half3((*(tint_symbol_1))[0].m[1]).zxy;
+kernel void f(device tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_2(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]));
+  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m));
+  (*(tint_symbol))[1].m[0].elements = packed_half3(half3((*(tint_symbol_1))[0].m[1].elements).zxy);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_workgroup.wgsl.expected.msl
index 816c6c6..3235501 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f16/to_workgroup.wgsl.expected.msl
@@ -15,32 +15,67 @@
 };
 
 struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half2x3 m;
-  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+  int before;
+  half2x3 m;
+  int after;
 };
 
 struct tint_symbol_6 {
   tint_array<S, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S, 4>* const tint_symbol_2) {
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 2> m;
+  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S_tint_packed_vec3, 4>* const tint_symbol_2) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     S const tint_symbol = S{};
     (*(tint_symbol_1))[i] = tint_symbol;
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol_1) = *(tint_symbol_2);
-  (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
-  (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = half3((*(tint_symbol_2))[0].m[1]).zxy;
+  *(tint_symbol_1) = tint_unpack_vec3_in_composite_2(*(tint_symbol_2));
+  (*(tint_symbol_1))[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_2))[2]);
+  (*(tint_symbol_1))[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_2))[2].m);
+  (*(tint_symbol_1))[1].m[0] = half3((*(tint_symbol_2))[0].m[1].elements).zxy;
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup tint_array<S, 4>* const tint_symbol_3 = &((*(tint_symbol_4)).w);
   f_inner(local_invocation_index, tint_symbol_3, tint_symbol_5);
   return;
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
index d4767f8..ad6de23 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,36 +14,85 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ float2x3 m;
-  /* 0x0020 */ tint_array<int8_t, 32> tint_pad;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f32_array_element, 2> m;
+  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_1;
 };
 
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  float2x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+struct Outer {
+  tint_array<Inner, 4> a;
+};
+
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
 int i() {
   thread int tint_symbol_4 = 0;
   tint_symbol_4 = as_type<int>((as_type<uint>(tint_symbol_4) + as_type<uint>(1)));
   return tint_symbol_4;
 }
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol_5 [[buffer(0)]]) {
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol_5 [[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_a_i_save = tint_symbol_1;
   int const tint_symbol_2 = i();
   int const p_a_i_a_i_m_i_save = tint_symbol_2;
-  tint_array<Outer, 4> const l_a = *(tint_symbol_5);
-  Outer const l_a_i = (*(tint_symbol_5))[p_a_i_save];
-  tint_array<Inner, 4> const l_a_i_a = (*(tint_symbol_5))[p_a_i_save].a;
-  Inner const l_a_i_a_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save];
-  float2x3 const l_a_i_a_i_m = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m;
-  float3 const l_a_i_a_i_m_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save];
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol_5));
+  Outer const l_a_i = tint_unpack_vec3_in_composite_3((*(tint_symbol_5))[p_a_i_save]);
+  tint_array<Inner, 4> const l_a_i_a = tint_unpack_vec3_in_composite_2((*(tint_symbol_5))[p_a_i_save].a);
+  Inner const l_a_i_a_i = tint_unpack_vec3_in_composite_1((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save]);
+  float2x3 const l_a_i_a_i_m = tint_unpack_vec3_in_composite((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m);
+  float3 const l_a_i_a_i_m_i = float3((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements);
   int const tint_symbol_3 = i();
-  float const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save][tint_symbol_3];
+  float const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements[tint_symbol_3];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl
index b36ca6e..526d744 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl
@@ -14,23 +14,72 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ float2x3 m;
-  /* 0x0020 */ tint_array<int8_t, 32> tint_pad;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f32_array_element, 2> m;
+  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_1;
+};
+
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  float2x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+  tint_array<Inner, 4> a;
 };
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol [[buffer(0)]]) {
-  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;
-  Inner const l_a_3_a_2 = (*(tint_symbol))[3].a[2];
-  float2x3 const l_a_3_a_2_m = (*(tint_symbol))[3].a[2].m;
-  float3 const l_a_3_a_2_m_1 = (*(tint_symbol))[3].a[2].m[1];
-  float const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1][0];
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol));
+  Outer const l_a_3 = tint_unpack_vec3_in_composite_3((*(tint_symbol))[3]);
+  tint_array<Inner, 4> const l_a_3_a = tint_unpack_vec3_in_composite_2((*(tint_symbol))[3].a);
+  Inner const l_a_3_a_2 = tint_unpack_vec3_in_composite_1((*(tint_symbol))[3].a[2]);
+  float2x3 const l_a_3_a_2_m = tint_unpack_vec3_in_composite((*(tint_symbol))[3].a[2].m);
+  float3 const l_a_3_a_2_m_1 = float3((*(tint_symbol))[3].a[2].m[1].elements);
+  float const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_builtin.wgsl.expected.msl
index febc7d5..5734e29 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_builtin.wgsl.expected.msl
@@ -14,19 +14,38 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float2x3 m;
-  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  float3x2 const t = transpose((*(tint_symbol))[2].m);
-  float const l = length(float3((*(tint_symbol))[0].m[1]).zxy);
-  float const a = fabs(float3((*(tint_symbol))[0].m[1]).zxy[0]);
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 2> m;
+  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  float2x3 m;
+  int after;
+};
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  float3x2 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  float const l = length(float3((*(tint_symbol))[0].m[1].elements).zxy);
+  float const a = fabs(float3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_fn.wgsl.expected.msl
index 5835b92..05f8a07 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_fn.wgsl.expected.msl
@@ -14,15 +14,50 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float2x3 m;
-  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 2> m;
+  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  float2x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<S, 4> a_1) {
 }
 
@@ -38,12 +73,12 @@
 void e(float f_1) {
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[2]);
-  c((*(tint_symbol))[2].m);
-  d(float3((*(tint_symbol))[0].m[1]).zxy);
-  e(float3((*(tint_symbol))[0].m[1]).zxy[0]);
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_2(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite_1((*(tint_symbol))[2]));
+  c(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  d(float3((*(tint_symbol))[0].m[1].elements).zxy);
+  e(float3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_private.wgsl.expected.msl
index 40d4274..a4125c9 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_private.wgsl.expected.msl
@@ -14,21 +14,56 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float2x3 m;
-  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 2> m;
+  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  float2x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<S, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = float3((*(tint_symbol_1))[0].m[1]).zxy;
+  tint_symbol = tint_unpack_vec3_in_composite_2(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]);
+  tint_symbol[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m);
+  tint_symbol[1].m[0] = float3((*(tint_symbol_1))[0].m[1].elements).zxy;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_storage.wgsl.expected.msl
index 07e0d6b..40c8ff5 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_storage.wgsl.expected.msl
@@ -14,37 +14,72 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float2x3 m;
-  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-void assign_and_preserve_padding_2(device float2x3* const dest, float2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 2> m;
+  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding_1(device S* const dest, S value) {
+struct S {
+  int before;
+  float2x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_2(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, float2x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+}
+
+void assign_and_preserve_padding_1(device S_tint_packed_vec3* const dest, S value) {
   (*(dest)).before = value.before;
   assign_and_preserve_padding_2(&((*(dest)).m), value.m);
   (*(dest)).after = value.after;
 }
 
-void assign_and_preserve_padding(device tint_array<S, 4>* const dest, tint_array<S, 4> value) {
+void assign_and_preserve_padding(device tint_array<S_tint_packed_vec3, 4>* const dest, tint_array<S, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<S, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), (*(tint_symbol_1))[2].m);
-  (*(tint_symbol))[1].m[0] = float3((*(tint_symbol_1))[0].m[1]).zxy;
+kernel void f(device tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_2(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]));
+  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m));
+  (*(tint_symbol))[1].m[0].elements = packed_float3(float3((*(tint_symbol_1))[0].m[1].elements).zxy);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_workgroup.wgsl.expected.msl
index 6e4d54e..bf3193b 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x3_f32/to_workgroup.wgsl.expected.msl
@@ -15,32 +15,67 @@
 };
 
 struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float2x3 m;
-  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+  int before;
+  float2x3 m;
+  int after;
 };
 
 struct tint_symbol_6 {
   tint_array<S, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S, 4>* const tint_symbol_2) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 2> m;
+  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S_tint_packed_vec3, 4>* const tint_symbol_2) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     S const tint_symbol = S{};
     (*(tint_symbol_1))[i] = tint_symbol;
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol_1) = *(tint_symbol_2);
-  (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
-  (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = float3((*(tint_symbol_2))[0].m[1]).zxy;
+  *(tint_symbol_1) = tint_unpack_vec3_in_composite_2(*(tint_symbol_2));
+  (*(tint_symbol_1))[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_2))[2]);
+  (*(tint_symbol_1))[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_2))[2].m);
+  (*(tint_symbol_1))[1].m[0] = float3((*(tint_symbol_2))[0].m[1].elements).zxy;
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup tint_array<S, 4>* const tint_symbol_3 = &((*(tint_symbol_4)).w);
   f_inner(local_invocation_index, tint_symbol_3, tint_symbol_5);
   return;
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_builtin.wgsl.expected.msl
index 4be54f8..3ac68ce 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_builtin.wgsl.expected.msl
@@ -25,8 +25,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   half4x2 const t = transpose((*(tint_symbol))[2].m);
-  half const l = length(half4((*(tint_symbol))[0].m[1]).ywxz);
-  half const a = fabs(half4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  half const l = length((*(tint_symbol))[0].m[1].ywxz);
+  half const a = fabs((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_fn.wgsl.expected.msl
index d555b48..613d587 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_fn.wgsl.expected.msl
@@ -42,8 +42,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(half4((*(tint_symbol))[0].m[1]).ywxz);
-  e(half4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  d((*(tint_symbol))[0].m[1].ywxz);
+  e((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_private.wgsl.expected.msl
index c25d4bb..401d59c 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_private.wgsl.expected.msl
@@ -28,7 +28,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = half4((*(tint_symbol_1))[0].m[1]).ywxz;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_storage.wgsl.expected.msl
index dce5189..719237a 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_storage.wgsl.expected.msl
@@ -39,7 +39,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = half4((*(tint_symbol_1))[0].m[1]).ywxz;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_workgroup.wgsl.expected.msl
index 0e256d8..03151ea 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x4_f16/to_workgroup.wgsl.expected.msl
@@ -37,7 +37,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = half4((*(tint_symbol_2))[0].m[1]).ywxz;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].ywxz;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_builtin.wgsl.expected.msl
index 5b9dd4cf..fd2d6bb 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_builtin.wgsl.expected.msl
@@ -25,8 +25,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   float4x2 const t = transpose((*(tint_symbol))[2].m);
-  float const l = length(float4((*(tint_symbol))[0].m[1]).ywxz);
-  float const a = fabs(float4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  float const l = length((*(tint_symbol))[0].m[1].ywxz);
+  float const a = fabs((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_fn.wgsl.expected.msl
index 1914a9d..5af58de 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_fn.wgsl.expected.msl
@@ -42,8 +42,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(float4((*(tint_symbol))[0].m[1]).ywxz);
-  e(float4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  d((*(tint_symbol))[0].m[1].ywxz);
+  e((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_private.wgsl.expected.msl
index 4732140..7fb9918 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_private.wgsl.expected.msl
@@ -28,7 +28,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = float4((*(tint_symbol_1))[0].m[1]).ywxz;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_storage.wgsl.expected.msl
index 9aba404..52d9404 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_storage.wgsl.expected.msl
@@ -39,7 +39,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = float4((*(tint_symbol_1))[0].m[1]).ywxz;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_workgroup.wgsl.expected.msl
index d3138fa..5ddb92f 100644
--- a/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat2x4_f32/to_workgroup.wgsl.expected.msl
@@ -37,7 +37,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = float4((*(tint_symbol_2))[0].m[1]).ywxz;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].ywxz;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_builtin.wgsl.expected.msl
index d2ab552..b7fd25c 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_builtin.wgsl.expected.msl
@@ -24,8 +24,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   half2x3 const t = transpose((*(tint_symbol))[2].m);
-  half const l = length(half2((*(tint_symbol))[0].m[1]).yx);
-  half const a = fabs(half2((*(tint_symbol))[0].m[1]).yx[0]);
+  half const l = length((*(tint_symbol))[0].m[1].yx);
+  half const a = fabs((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_fn.wgsl.expected.msl
index f0a5dce..3ec4557 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_fn.wgsl.expected.msl
@@ -41,8 +41,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(half2((*(tint_symbol))[0].m[1]).yx);
-  e(half2((*(tint_symbol))[0].m[1]).yx[0]);
+  d((*(tint_symbol))[0].m[1].yx);
+  e((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_private.wgsl.expected.msl
index 52627dc..1fbb90c 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_private.wgsl.expected.msl
@@ -27,7 +27,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = half2((*(tint_symbol_1))[0].m[1]).yx;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_storage.wgsl.expected.msl
index f5c6d51..369c335 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_storage.wgsl.expected.msl
@@ -38,7 +38,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = half2((*(tint_symbol_1))[0].m[1]).yx;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_workgroup.wgsl.expected.msl
index 1ebcfae..3b789e9 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2_f16/to_workgroup.wgsl.expected.msl
@@ -36,7 +36,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = half2((*(tint_symbol_2))[0].m[1]).yx;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].yx;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_builtin.wgsl.expected.msl
index d42da49..956b1dd 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_builtin.wgsl.expected.msl
@@ -25,8 +25,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   float2x3 const t = transpose((*(tint_symbol))[2].m);
-  float const l = length(float2((*(tint_symbol))[0].m[1]).yx);
-  float const a = fabs(float2((*(tint_symbol))[0].m[1]).yx[0]);
+  float const l = length((*(tint_symbol))[0].m[1].yx);
+  float const a = fabs((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_fn.wgsl.expected.msl
index c42c800..b50bc7d 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_fn.wgsl.expected.msl
@@ -42,8 +42,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(float2((*(tint_symbol))[0].m[1]).yx);
-  e(float2((*(tint_symbol))[0].m[1]).yx[0]);
+  d((*(tint_symbol))[0].m[1].yx);
+  e((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_private.wgsl.expected.msl
index deefeba..118705a 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_private.wgsl.expected.msl
@@ -28,7 +28,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = float2((*(tint_symbol_1))[0].m[1]).yx;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_storage.wgsl.expected.msl
index 52a6429..3b94d66 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_storage.wgsl.expected.msl
@@ -39,7 +39,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = float2((*(tint_symbol_1))[0].m[1]).yx;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_workgroup.wgsl.expected.msl
index 03a5ba8..210510c 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x2_f32/to_workgroup.wgsl.expected.msl
@@ -37,7 +37,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = float2((*(tint_symbol_2))[0].m[1]).yx;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].yx;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
index 5fbd9f0..0cf67e3 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,36 +14,85 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ half3x3 m;
-  /* 0x0018 */ tint_array<int8_t, 40> tint_pad;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f16_array_element, 3> m;
+  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_1;
 };
 
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  half3x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+struct Outer {
+  tint_array<Inner, 4> a;
+};
+
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
 int i() {
   thread int tint_symbol_4 = 0;
   tint_symbol_4 = as_type<int>((as_type<uint>(tint_symbol_4) + as_type<uint>(1)));
   return tint_symbol_4;
 }
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol_5 [[buffer(0)]]) {
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol_5 [[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_a_i_save = tint_symbol_1;
   int const tint_symbol_2 = i();
   int const p_a_i_a_i_m_i_save = tint_symbol_2;
-  tint_array<Outer, 4> const l_a = *(tint_symbol_5);
-  Outer const l_a_i = (*(tint_symbol_5))[p_a_i_save];
-  tint_array<Inner, 4> const l_a_i_a = (*(tint_symbol_5))[p_a_i_save].a;
-  Inner const l_a_i_a_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save];
-  half3x3 const l_a_i_a_i_m = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m;
-  half3 const l_a_i_a_i_m_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save];
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol_5));
+  Outer const l_a_i = tint_unpack_vec3_in_composite_3((*(tint_symbol_5))[p_a_i_save]);
+  tint_array<Inner, 4> const l_a_i_a = tint_unpack_vec3_in_composite_2((*(tint_symbol_5))[p_a_i_save].a);
+  Inner const l_a_i_a_i = tint_unpack_vec3_in_composite_1((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save]);
+  half3x3 const l_a_i_a_i_m = tint_unpack_vec3_in_composite((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m);
+  half3 const l_a_i_a_i_m_i = half3((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements);
   int const tint_symbol_3 = i();
-  half const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save][tint_symbol_3];
+  half const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements[tint_symbol_3];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/static_index_via_ptr.wgsl.expected.msl
index b7594a9..a707c60 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/static_index_via_ptr.wgsl.expected.msl
@@ -14,23 +14,72 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ half3x3 m;
-  /* 0x0018 */ tint_array<int8_t, 40> tint_pad;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f16_array_element, 3> m;
+  /* 0x0018 */ tint_array<int8_t, 40> tint_pad_1;
+};
+
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  half3x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+  tint_array<Inner, 4> a;
 };
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol [[buffer(0)]]) {
-  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;
-  Inner const l_a_3_a_2 = (*(tint_symbol))[3].a[2];
-  half3x3 const l_a_3_a_2_m = (*(tint_symbol))[3].a[2].m;
-  half3 const l_a_3_a_2_m_1 = (*(tint_symbol))[3].a[2].m[1];
-  half const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1][0];
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol));
+  Outer const l_a_3 = tint_unpack_vec3_in_composite_3((*(tint_symbol))[3]);
+  tint_array<Inner, 4> const l_a_3_a = tint_unpack_vec3_in_composite_2((*(tint_symbol))[3].a);
+  Inner const l_a_3_a_2 = tint_unpack_vec3_in_composite_1((*(tint_symbol))[3].a[2]);
+  half3x3 const l_a_3_a_2_m = tint_unpack_vec3_in_composite((*(tint_symbol))[3].a[2].m);
+  half3 const l_a_3_a_2_m_1 = half3((*(tint_symbol))[3].a[2].m[1].elements);
+  half const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_builtin.wgsl.expected.msl
index 350c296..b1bbaf9 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_builtin.wgsl.expected.msl
@@ -14,19 +14,38 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half3x3 m;
-  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  half3x3 const t = transpose((*(tint_symbol))[2].m);
-  half const l = length(half3((*(tint_symbol))[0].m[1]).zxy);
-  half const a = fabs(half3((*(tint_symbol))[0].m[1]).zxy[0]);
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 3> m;
+  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  half3x3 m;
+  int after;
+};
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  half3x3 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  half const l = length(half3((*(tint_symbol))[0].m[1].elements).zxy);
+  half const a = fabs(half3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_fn.wgsl.expected.msl
index 89e6084..3520432 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_fn.wgsl.expected.msl
@@ -14,15 +14,50 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half3x3 m;
-  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 3> m;
+  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  half3x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<S, 4> a_1) {
 }
 
@@ -38,12 +73,12 @@
 void e(half f_1) {
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[2]);
-  c((*(tint_symbol))[2].m);
-  d(half3((*(tint_symbol))[0].m[1]).zxy);
-  e(half3((*(tint_symbol))[0].m[1]).zxy[0]);
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_2(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite_1((*(tint_symbol))[2]));
+  c(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  d(half3((*(tint_symbol))[0].m[1].elements).zxy);
+  e(half3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_private.wgsl.expected.msl
index ff2ae9b..55bcb6a 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_private.wgsl.expected.msl
@@ -14,21 +14,56 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half3x3 m;
-  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 3> m;
+  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  half3x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<S, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = half3((*(tint_symbol_1))[0].m[1]).zxy;
+  tint_symbol = tint_unpack_vec3_in_composite_2(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]);
+  tint_symbol[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m);
+  tint_symbol[1].m[0] = half3((*(tint_symbol_1))[0].m[1].elements).zxy;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_storage.wgsl.expected.msl
index bd652de..f9022fc 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_storage.wgsl.expected.msl
@@ -14,38 +14,73 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half3x3 m;
-  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-void assign_and_preserve_padding_2(device half3x3* const dest, half3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 3> m;
+  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding_1(device S* const dest, S value) {
+struct S {
+  int before;
+  half3x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_2(device tint_array<tint_packed_vec3_f16_array_element, 3>* const dest, half3x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
+}
+
+void assign_and_preserve_padding_1(device S_tint_packed_vec3* const dest, S value) {
   (*(dest)).before = value.before;
   assign_and_preserve_padding_2(&((*(dest)).m), value.m);
   (*(dest)).after = value.after;
 }
 
-void assign_and_preserve_padding(device tint_array<S, 4>* const dest, tint_array<S, 4> value) {
+void assign_and_preserve_padding(device tint_array<S_tint_packed_vec3, 4>* const dest, tint_array<S, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<S, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), (*(tint_symbol_1))[2].m);
-  (*(tint_symbol))[1].m[0] = half3((*(tint_symbol_1))[0].m[1]).zxy;
+kernel void f(device tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_2(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]));
+  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m));
+  (*(tint_symbol))[1].m[0].elements = packed_half3(half3((*(tint_symbol_1))[0].m[1].elements).zxy);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_workgroup.wgsl.expected.msl
index 0e181df..454e443 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f16/to_workgroup.wgsl.expected.msl
@@ -15,32 +15,67 @@
 };
 
 struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half3x3 m;
-  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+  int before;
+  half3x3 m;
+  int after;
 };
 
 struct tint_symbol_6 {
   tint_array<S, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S, 4>* const tint_symbol_2) {
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 3> m;
+  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S_tint_packed_vec3, 4>* const tint_symbol_2) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     S const tint_symbol = S{};
     (*(tint_symbol_1))[i] = tint_symbol;
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol_1) = *(tint_symbol_2);
-  (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
-  (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = half3((*(tint_symbol_2))[0].m[1]).zxy;
+  *(tint_symbol_1) = tint_unpack_vec3_in_composite_2(*(tint_symbol_2));
+  (*(tint_symbol_1))[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_2))[2]);
+  (*(tint_symbol_1))[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_2))[2].m);
+  (*(tint_symbol_1))[1].m[0] = half3((*(tint_symbol_2))[0].m[1].elements).zxy;
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup tint_array<S, 4>* const tint_symbol_3 = &((*(tint_symbol_4)).w);
   f_inner(local_invocation_index, tint_symbol_3, tint_symbol_5);
   return;
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
index ec3d690..fd95ea8 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,36 +14,85 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ float3x3 m;
-  /* 0x0030 */ tint_array<int8_t, 16> tint_pad;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f32_array_element, 3> m;
+  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_1;
 };
 
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  float3x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+struct Outer {
+  tint_array<Inner, 4> a;
+};
+
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
 int i() {
   thread int tint_symbol_4 = 0;
   tint_symbol_4 = as_type<int>((as_type<uint>(tint_symbol_4) + as_type<uint>(1)));
   return tint_symbol_4;
 }
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol_5 [[buffer(0)]]) {
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol_5 [[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_a_i_save = tint_symbol_1;
   int const tint_symbol_2 = i();
   int const p_a_i_a_i_m_i_save = tint_symbol_2;
-  tint_array<Outer, 4> const l_a = *(tint_symbol_5);
-  Outer const l_a_i = (*(tint_symbol_5))[p_a_i_save];
-  tint_array<Inner, 4> const l_a_i_a = (*(tint_symbol_5))[p_a_i_save].a;
-  Inner const l_a_i_a_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save];
-  float3x3 const l_a_i_a_i_m = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m;
-  float3 const l_a_i_a_i_m_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save];
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol_5));
+  Outer const l_a_i = tint_unpack_vec3_in_composite_3((*(tint_symbol_5))[p_a_i_save]);
+  tint_array<Inner, 4> const l_a_i_a = tint_unpack_vec3_in_composite_2((*(tint_symbol_5))[p_a_i_save].a);
+  Inner const l_a_i_a_i = tint_unpack_vec3_in_composite_1((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save]);
+  float3x3 const l_a_i_a_i_m = tint_unpack_vec3_in_composite((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m);
+  float3 const l_a_i_a_i_m_i = float3((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements);
   int const tint_symbol_3 = i();
-  float const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save][tint_symbol_3];
+  float const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements[tint_symbol_3];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl
index 4092ef5..4b0a579 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl
@@ -14,23 +14,72 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ float3x3 m;
-  /* 0x0030 */ tint_array<int8_t, 16> tint_pad;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f32_array_element, 3> m;
+  /* 0x0030 */ tint_array<int8_t, 16> tint_pad_1;
+};
+
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  float3x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+  tint_array<Inner, 4> a;
 };
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol [[buffer(0)]]) {
-  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;
-  Inner const l_a_3_a_2 = (*(tint_symbol))[3].a[2];
-  float3x3 const l_a_3_a_2_m = (*(tint_symbol))[3].a[2].m;
-  float3 const l_a_3_a_2_m_1 = (*(tint_symbol))[3].a[2].m[1];
-  float const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1][0];
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol));
+  Outer const l_a_3 = tint_unpack_vec3_in_composite_3((*(tint_symbol))[3]);
+  tint_array<Inner, 4> const l_a_3_a = tint_unpack_vec3_in_composite_2((*(tint_symbol))[3].a);
+  Inner const l_a_3_a_2 = tint_unpack_vec3_in_composite_1((*(tint_symbol))[3].a[2]);
+  float3x3 const l_a_3_a_2_m = tint_unpack_vec3_in_composite((*(tint_symbol))[3].a[2].m);
+  float3 const l_a_3_a_2_m_1 = float3((*(tint_symbol))[3].a[2].m[1].elements);
+  float const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_builtin.wgsl.expected.msl
index 08a4ad4..3fdbccc 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_builtin.wgsl.expected.msl
@@ -14,18 +14,37 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float3x3 m;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_1;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  float3x3 const t = transpose((*(tint_symbol))[2].m);
-  float const l = length(float3((*(tint_symbol))[0].m[1]).zxy);
-  float const a = fabs(float3((*(tint_symbol))[0].m[1]).zxy[0]);
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 3> m;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  float3x3 m;
+  int after;
+};
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  float3x3 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  float const l = length(float3((*(tint_symbol))[0].m[1].elements).zxy);
+  float const a = fabs(float3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_fn.wgsl.expected.msl
index bd1b6bd..82b8bfc 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_fn.wgsl.expected.msl
@@ -14,14 +14,49 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float3x3 m;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_1;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 3> m;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  float3x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<S, 4> a_1) {
 }
 
@@ -37,12 +72,12 @@
 void e(float f_1) {
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[2]);
-  c((*(tint_symbol))[2].m);
-  d(float3((*(tint_symbol))[0].m[1]).zxy);
-  e(float3((*(tint_symbol))[0].m[1]).zxy[0]);
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_2(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite_1((*(tint_symbol))[2]));
+  c(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  d(float3((*(tint_symbol))[0].m[1].elements).zxy);
+  e(float3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_private.wgsl.expected.msl
index 7e169af..f6812b4 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_private.wgsl.expected.msl
@@ -14,20 +14,55 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float3x3 m;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_1;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 3> m;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  float3x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<S, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = float3((*(tint_symbol_1))[0].m[1]).zxy;
+  tint_symbol = tint_unpack_vec3_in_composite_2(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]);
+  tint_symbol[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m);
+  tint_symbol[1].m[0] = float3((*(tint_symbol_1))[0].m[1].elements).zxy;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_storage.wgsl.expected.msl
index dc53f2a..27d1919 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_storage.wgsl.expected.msl
@@ -14,37 +14,72 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float3x3 m;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_1;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-void assign_and_preserve_padding_2(device float3x3* const dest, float3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 3> m;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding_1(device S* const dest, S value) {
+struct S {
+  int before;
+  float3x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_2(device tint_array<tint_packed_vec3_f32_array_element, 3>* const dest, float3x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+}
+
+void assign_and_preserve_padding_1(device S_tint_packed_vec3* const dest, S value) {
   (*(dest)).before = value.before;
   assign_and_preserve_padding_2(&((*(dest)).m), value.m);
   (*(dest)).after = value.after;
 }
 
-void assign_and_preserve_padding(device tint_array<S, 4>* const dest, tint_array<S, 4> value) {
+void assign_and_preserve_padding(device tint_array<S_tint_packed_vec3, 4>* const dest, tint_array<S, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<S, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), (*(tint_symbol_1))[2].m);
-  (*(tint_symbol))[1].m[0] = float3((*(tint_symbol_1))[0].m[1]).zxy;
+kernel void f(device tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_2(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]));
+  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m));
+  (*(tint_symbol))[1].m[0].elements = packed_float3(float3((*(tint_symbol_1))[0].m[1].elements).zxy);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_workgroup.wgsl.expected.msl
index 1fddc70..4987aac 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x3_f32/to_workgroup.wgsl.expected.msl
@@ -15,31 +15,66 @@
 };
 
 struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float3x3 m;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_1;
+  int before;
+  float3x3 m;
+  int after;
 };
 
 struct tint_symbol_6 {
   tint_array<S, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S, 4>* const tint_symbol_2) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 3> m;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S_tint_packed_vec3, 4>* const tint_symbol_2) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     S const tint_symbol = S{};
     (*(tint_symbol_1))[i] = tint_symbol;
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol_1) = *(tint_symbol_2);
-  (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
-  (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = float3((*(tint_symbol_2))[0].m[1]).zxy;
+  *(tint_symbol_1) = tint_unpack_vec3_in_composite_2(*(tint_symbol_2));
+  (*(tint_symbol_1))[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_2))[2]);
+  (*(tint_symbol_1))[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_2))[2].m);
+  (*(tint_symbol_1))[1].m[0] = float3((*(tint_symbol_2))[0].m[1].elements).zxy;
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup tint_array<S, 4>* const tint_symbol_3 = &((*(tint_symbol_4)).w);
   f_inner(local_invocation_index, tint_symbol_3, tint_symbol_5);
   return;
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_builtin.wgsl.expected.msl
index 0c0b9e8..e881869 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_builtin.wgsl.expected.msl
@@ -25,8 +25,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   half4x3 const t = transpose((*(tint_symbol))[2].m);
-  half const l = length(half4((*(tint_symbol))[0].m[1]).ywxz);
-  half const a = fabs(half4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  half const l = length((*(tint_symbol))[0].m[1].ywxz);
+  half const a = fabs((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_fn.wgsl.expected.msl
index abf6c24..fdb8bfc 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_fn.wgsl.expected.msl
@@ -42,8 +42,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(half4((*(tint_symbol))[0].m[1]).ywxz);
-  e(half4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  d((*(tint_symbol))[0].m[1].ywxz);
+  e((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_private.wgsl.expected.msl
index 23983c5..6146923 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_private.wgsl.expected.msl
@@ -28,7 +28,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = half4((*(tint_symbol_1))[0].m[1]).ywxz;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_storage.wgsl.expected.msl
index 1076dd7..c9bca39 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_storage.wgsl.expected.msl
@@ -39,7 +39,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = half4((*(tint_symbol_1))[0].m[1]).ywxz;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_workgroup.wgsl.expected.msl
index 444e7ca..065dd48 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x4_f16/to_workgroup.wgsl.expected.msl
@@ -37,7 +37,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = half4((*(tint_symbol_2))[0].m[1]).ywxz;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].ywxz;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_builtin.wgsl.expected.msl
index c93494d..d5a4bca 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_builtin.wgsl.expected.msl
@@ -24,8 +24,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   float4x3 const t = transpose((*(tint_symbol))[2].m);
-  float const l = length(float4((*(tint_symbol))[0].m[1]).ywxz);
-  float const a = fabs(float4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  float const l = length((*(tint_symbol))[0].m[1].ywxz);
+  float const a = fabs((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_fn.wgsl.expected.msl
index b2034ef..e2b42df 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_fn.wgsl.expected.msl
@@ -41,8 +41,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(float4((*(tint_symbol))[0].m[1]).ywxz);
-  e(float4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  d((*(tint_symbol))[0].m[1].ywxz);
+  e((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_private.wgsl.expected.msl
index 53a32ac..d59f443 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_private.wgsl.expected.msl
@@ -27,7 +27,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = float4((*(tint_symbol_1))[0].m[1]).ywxz;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_storage.wgsl.expected.msl
index e743ea3..e349da5 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_storage.wgsl.expected.msl
@@ -38,7 +38,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = float4((*(tint_symbol_1))[0].m[1]).ywxz;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_workgroup.wgsl.expected.msl
index 8fb8e97..421719c 100644
--- a/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat3x4_f32/to_workgroup.wgsl.expected.msl
@@ -36,7 +36,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = float4((*(tint_symbol_2))[0].m[1]).ywxz;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].ywxz;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_builtin.wgsl.expected.msl
index 49c1370..0b2fb53 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_builtin.wgsl.expected.msl
@@ -24,8 +24,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   half2x4 const t = transpose((*(tint_symbol))[2].m);
-  half const l = length(half2((*(tint_symbol))[0].m[1]).yx);
-  half const a = fabs(half2((*(tint_symbol))[0].m[1]).yx[0]);
+  half const l = length((*(tint_symbol))[0].m[1].yx);
+  half const a = fabs((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_fn.wgsl.expected.msl
index 527770e..f0552f3 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_fn.wgsl.expected.msl
@@ -41,8 +41,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(half2((*(tint_symbol))[0].m[1]).yx);
-  e(half2((*(tint_symbol))[0].m[1]).yx[0]);
+  d((*(tint_symbol))[0].m[1].yx);
+  e((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_private.wgsl.expected.msl
index a941446..6141107 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_private.wgsl.expected.msl
@@ -27,7 +27,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = half2((*(tint_symbol_1))[0].m[1]).yx;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_storage.wgsl.expected.msl
index 718c21a..b80bfe1 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_storage.wgsl.expected.msl
@@ -38,7 +38,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = half2((*(tint_symbol_1))[0].m[1]).yx;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_workgroup.wgsl.expected.msl
index 41f9255..8c98cfc 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2_f16/to_workgroup.wgsl.expected.msl
@@ -36,7 +36,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = half2((*(tint_symbol_2))[0].m[1]).yx;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].yx;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_builtin.wgsl.expected.msl
index 9684c69..579a046 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_builtin.wgsl.expected.msl
@@ -25,8 +25,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   float2x4 const t = transpose((*(tint_symbol))[2].m);
-  float const l = length(float2((*(tint_symbol))[0].m[1]).yx);
-  float const a = fabs(float2((*(tint_symbol))[0].m[1]).yx[0]);
+  float const l = length((*(tint_symbol))[0].m[1].yx);
+  float const a = fabs((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_fn.wgsl.expected.msl
index e8c64c3..551abb8 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_fn.wgsl.expected.msl
@@ -42,8 +42,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(float2((*(tint_symbol))[0].m[1]).yx);
-  e(float2((*(tint_symbol))[0].m[1]).yx[0]);
+  d((*(tint_symbol))[0].m[1].yx);
+  e((*(tint_symbol))[0].m[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_private.wgsl.expected.msl
index 017641a..727a883 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_private.wgsl.expected.msl
@@ -28,7 +28,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = float2((*(tint_symbol_1))[0].m[1]).yx;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_storage.wgsl.expected.msl
index 8b6fd34..16ec5d1 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_storage.wgsl.expected.msl
@@ -39,7 +39,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = float2((*(tint_symbol_1))[0].m[1]).yx;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].yx;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_workgroup.wgsl.expected.msl
index 02501da..5931951 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x2_f32/to_workgroup.wgsl.expected.msl
@@ -37,7 +37,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = float2((*(tint_symbol_2))[0].m[1]).yx;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].yx;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
index 1369d42..5b3d6f8 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,36 +14,85 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ half4x3 m;
-  /* 0x0020 */ tint_array<int8_t, 32> tint_pad;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f16_array_element, 4> m;
+  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_1;
 };
 
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  half4x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+struct Outer {
+  tint_array<Inner, 4> a;
+};
+
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
 int i() {
   thread int tint_symbol_4 = 0;
   tint_symbol_4 = as_type<int>((as_type<uint>(tint_symbol_4) + as_type<uint>(1)));
   return tint_symbol_4;
 }
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol_5 [[buffer(0)]]) {
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol_5 [[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_a_i_save = tint_symbol_1;
   int const tint_symbol_2 = i();
   int const p_a_i_a_i_m_i_save = tint_symbol_2;
-  tint_array<Outer, 4> const l_a = *(tint_symbol_5);
-  Outer const l_a_i = (*(tint_symbol_5))[p_a_i_save];
-  tint_array<Inner, 4> const l_a_i_a = (*(tint_symbol_5))[p_a_i_save].a;
-  Inner const l_a_i_a_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save];
-  half4x3 const l_a_i_a_i_m = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m;
-  half3 const l_a_i_a_i_m_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save];
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol_5));
+  Outer const l_a_i = tint_unpack_vec3_in_composite_3((*(tint_symbol_5))[p_a_i_save]);
+  tint_array<Inner, 4> const l_a_i_a = tint_unpack_vec3_in_composite_2((*(tint_symbol_5))[p_a_i_save].a);
+  Inner const l_a_i_a_i = tint_unpack_vec3_in_composite_1((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save]);
+  half4x3 const l_a_i_a_i_m = tint_unpack_vec3_in_composite((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m);
+  half3 const l_a_i_a_i_m_i = half3((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements);
   int const tint_symbol_3 = i();
-  half const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save][tint_symbol_3];
+  half const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements[tint_symbol_3];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl
index ee0c952..2c2086d 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl
@@ -14,23 +14,72 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ half4x3 m;
-  /* 0x0020 */ tint_array<int8_t, 32> tint_pad;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f16_array_element, 4> m;
+  /* 0x0020 */ tint_array<int8_t, 32> tint_pad_1;
+};
+
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  half4x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+  tint_array<Inner, 4> a;
 };
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol [[buffer(0)]]) {
-  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;
-  Inner const l_a_3_a_2 = (*(tint_symbol))[3].a[2];
-  half4x3 const l_a_3_a_2_m = (*(tint_symbol))[3].a[2].m;
-  half3 const l_a_3_a_2_m_1 = (*(tint_symbol))[3].a[2].m[1];
-  half const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1][0];
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol));
+  Outer const l_a_3 = tint_unpack_vec3_in_composite_3((*(tint_symbol))[3]);
+  tint_array<Inner, 4> const l_a_3_a = tint_unpack_vec3_in_composite_2((*(tint_symbol))[3].a);
+  Inner const l_a_3_a_2 = tint_unpack_vec3_in_composite_1((*(tint_symbol))[3].a[2]);
+  half4x3 const l_a_3_a_2_m = tint_unpack_vec3_in_composite((*(tint_symbol))[3].a[2].m);
+  half3 const l_a_3_a_2_m_1 = half3((*(tint_symbol))[3].a[2].m[1].elements);
+  half const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_builtin.wgsl.expected.msl
index 3a831cd..eea26e8 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_builtin.wgsl.expected.msl
@@ -14,19 +14,38 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half4x3 m;
-  /* 0x0028 */ tint_array<int8_t, 24> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  half3x4 const t = transpose((*(tint_symbol))[2].m);
-  half const l = length(half3((*(tint_symbol))[0].m[1]).zxy);
-  half const a = fabs(half3((*(tint_symbol))[0].m[1]).zxy[0]);
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 4> m;
+  /* 0x0028 */ tint_array<int8_t, 24> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  half4x3 m;
+  int after;
+};
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  half3x4 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  half const l = length(half3((*(tint_symbol))[0].m[1].elements).zxy);
+  half const a = fabs(half3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_fn.wgsl.expected.msl
index 821e522..8ff5b7c 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_fn.wgsl.expected.msl
@@ -14,15 +14,50 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half4x3 m;
-  /* 0x0028 */ tint_array<int8_t, 24> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 4> m;
+  /* 0x0028 */ tint_array<int8_t, 24> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  half4x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<S, 4> a_1) {
 }
 
@@ -38,12 +73,12 @@
 void e(half f_1) {
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[2]);
-  c((*(tint_symbol))[2].m);
-  d(half3((*(tint_symbol))[0].m[1]).zxy);
-  e(half3((*(tint_symbol))[0].m[1]).zxy[0]);
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_2(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite_1((*(tint_symbol))[2]));
+  c(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  d(half3((*(tint_symbol))[0].m[1].elements).zxy);
+  e(half3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_private.wgsl.expected.msl
index 175ed33..dae39c9 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_private.wgsl.expected.msl
@@ -14,21 +14,56 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half4x3 m;
-  /* 0x0028 */ tint_array<int8_t, 24> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 4> m;
+  /* 0x0028 */ tint_array<int8_t, 24> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  half4x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<S, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = half3((*(tint_symbol_1))[0].m[1]).zxy;
+  tint_symbol = tint_unpack_vec3_in_composite_2(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]);
+  tint_symbol[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m);
+  tint_symbol[1].m[0] = half3((*(tint_symbol_1))[0].m[1].elements).zxy;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_storage.wgsl.expected.msl
index 448f2693..6f84630 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_storage.wgsl.expected.msl
@@ -14,39 +14,74 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half4x3 m;
-  /* 0x0028 */ tint_array<int8_t, 24> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-void assign_and_preserve_padding_2(device half4x3* const dest, half4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 4> m;
+  /* 0x0028 */ tint_array<int8_t, 24> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding_1(device S* const dest, S value) {
+struct S {
+  int before;
+  half4x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_2(device tint_array<tint_packed_vec3_f16_array_element, 4>* const dest, half4x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
+  (*(dest))[3u].elements = packed_half3(value[3u]);
+}
+
+void assign_and_preserve_padding_1(device S_tint_packed_vec3* const dest, S value) {
   (*(dest)).before = value.before;
   assign_and_preserve_padding_2(&((*(dest)).m), value.m);
   (*(dest)).after = value.after;
 }
 
-void assign_and_preserve_padding(device tint_array<S, 4>* const dest, tint_array<S, 4> value) {
+void assign_and_preserve_padding(device tint_array<S_tint_packed_vec3, 4>* const dest, tint_array<S, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<S, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), (*(tint_symbol_1))[2].m);
-  (*(tint_symbol))[1].m[0] = half3((*(tint_symbol_1))[0].m[1]).zxy;
+kernel void f(device tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_2(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]));
+  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m));
+  (*(tint_symbol))[1].m[0].elements = packed_half3(half3((*(tint_symbol_1))[0].m[1].elements).zxy);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_workgroup.wgsl.expected.msl
index eedfd26..c460177 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f16/to_workgroup.wgsl.expected.msl
@@ -15,32 +15,67 @@
 };
 
 struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 4> tint_pad;
-  /* 0x0008 */ half4x3 m;
-  /* 0x0028 */ tint_array<int8_t, 24> tint_pad_1;
-  /* 0x0040 */ int after;
-  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_2;
+  int before;
+  half4x3 m;
+  int after;
 };
 
 struct tint_symbol_6 {
   tint_array<S, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S, 4>* const tint_symbol_2) {
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 4> tint_pad_1;
+  /* 0x0008 */ tint_array<tint_packed_vec3_f16_array_element, 4> m;
+  /* 0x0028 */ tint_array<int8_t, 24> tint_pad_2;
+  /* 0x0040 */ int after;
+  /* 0x0044 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S_tint_packed_vec3, 4>* const tint_symbol_2) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     S const tint_symbol = S{};
     (*(tint_symbol_1))[i] = tint_symbol;
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol_1) = *(tint_symbol_2);
-  (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
-  (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = half3((*(tint_symbol_2))[0].m[1]).zxy;
+  *(tint_symbol_1) = tint_unpack_vec3_in_composite_2(*(tint_symbol_2));
+  (*(tint_symbol_1))[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_2))[2]);
+  (*(tint_symbol_1))[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_2))[2].m);
+  (*(tint_symbol_1))[1].m[0] = half3((*(tint_symbol_2))[0].m[1].elements).zxy;
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup tint_array<S, 4>* const tint_symbol_3 = &((*(tint_symbol_4)).w);
   f_inner(local_invocation_index, tint_symbol_3, tint_symbol_5);
   return;
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
index ea70250..0a6b698 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
@@ -14,35 +14,84 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ float4x3 m;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f32_array_element, 4> m;
 };
 
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  float4x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+struct Outer {
+  tint_array<Inner, 4> a;
+};
+
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
 int i() {
   thread int tint_symbol_4 = 0;
   tint_symbol_4 = as_type<int>((as_type<uint>(tint_symbol_4) + as_type<uint>(1)));
   return tint_symbol_4;
 }
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol_5 [[buffer(0)]]) {
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol_5 [[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_a_i_save = tint_symbol_1;
   int const tint_symbol_2 = i();
   int const p_a_i_a_i_m_i_save = tint_symbol_2;
-  tint_array<Outer, 4> const l_a = *(tint_symbol_5);
-  Outer const l_a_i = (*(tint_symbol_5))[p_a_i_save];
-  tint_array<Inner, 4> const l_a_i_a = (*(tint_symbol_5))[p_a_i_save].a;
-  Inner const l_a_i_a_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save];
-  float4x3 const l_a_i_a_i_m = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m;
-  float3 const l_a_i_a_i_m_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save];
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol_5));
+  Outer const l_a_i = tint_unpack_vec3_in_composite_3((*(tint_symbol_5))[p_a_i_save]);
+  tint_array<Inner, 4> const l_a_i_a = tint_unpack_vec3_in_composite_2((*(tint_symbol_5))[p_a_i_save].a);
+  Inner const l_a_i_a_i = tint_unpack_vec3_in_composite_1((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save]);
+  float4x3 const l_a_i_a_i_m = tint_unpack_vec3_in_composite((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m);
+  float3 const l_a_i_a_i_m_i = float3((*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements);
   int const tint_symbol_3 = i();
-  float const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save][tint_symbol_3];
+  float const l_a_i_a_i_m_i_i = (*(tint_symbol_5))[p_a_i_save].a[p_a_i_a_i_save].m[p_a_i_a_i_m_i_save].elements[tint_symbol_3];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl
index a7fb219..479a398 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl
@@ -14,22 +14,71 @@
     T elements[N];
 };
 
-struct Inner {
-  /* 0x0000 */ float4x3 m;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
+struct Inner_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f32_array_element, 4> m;
+};
+
+struct Outer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Inner_tint_packed_vec3, 4> a;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Inner {
+  float4x3 m;
+};
+
+Inner tint_unpack_vec3_in_composite_1(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  return result;
+}
+
+tint_array<Inner, 4> tint_unpack_vec3_in_composite_2(tint_array<Inner_tint_packed_vec3, 4> in) {
+  tint_array<Inner, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 struct Outer {
-  /* 0x0000 */ tint_array<Inner, 4> a;
+  tint_array<Inner, 4> a;
 };
 
-kernel void f(const constant tint_array<Outer, 4>* tint_symbol [[buffer(0)]]) {
-  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;
-  Inner const l_a_3_a_2 = (*(tint_symbol))[3].a[2];
-  float4x3 const l_a_3_a_2_m = (*(tint_symbol))[3].a[2].m;
-  float3 const l_a_3_a_2_m_1 = (*(tint_symbol))[3].a[2].m[1];
-  float const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1][0];
+Outer tint_unpack_vec3_in_composite_3(Outer_tint_packed_vec3 in) {
+  Outer result = {};
+  result.a = tint_unpack_vec3_in_composite_2(in.a);
+  return result;
+}
+
+tint_array<Outer, 4> tint_unpack_vec3_in_composite_4(tint_array<Outer_tint_packed_vec3, 4> in) {
+  tint_array<Outer, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<Outer_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  tint_array<Outer, 4> const l_a = tint_unpack_vec3_in_composite_4(*(tint_symbol));
+  Outer const l_a_3 = tint_unpack_vec3_in_composite_3((*(tint_symbol))[3]);
+  tint_array<Inner, 4> const l_a_3_a = tint_unpack_vec3_in_composite_2((*(tint_symbol))[3].a);
+  Inner const l_a_3_a_2 = tint_unpack_vec3_in_composite_1((*(tint_symbol))[3].a[2]);
+  float4x3 const l_a_3_a_2_m = tint_unpack_vec3_in_composite((*(tint_symbol))[3].a[2].m);
+  float3 const l_a_3_a_2_m_1 = float3((*(tint_symbol))[3].a[2].m[1].elements);
+  float const l_a_3_a_2_m_1_0 = (*(tint_symbol))[3].a[2].m[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_builtin.wgsl.expected.msl
index 90364fc..ddd7ad1 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_builtin.wgsl.expected.msl
@@ -14,19 +14,38 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float4x3 m;
-  /* 0x0050 */ tint_array<int8_t, 48> tint_pad_1;
-  /* 0x0080 */ int after;
-  /* 0x0084 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  float3x4 const t = transpose((*(tint_symbol))[2].m);
-  float const l = length(float3((*(tint_symbol))[0].m[1]).zxy);
-  float const a = fabs(float3((*(tint_symbol))[0].m[1]).zxy[0]);
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 4> m;
+  /* 0x0050 */ tint_array<int8_t, 48> tint_pad_2;
+  /* 0x0080 */ int after;
+  /* 0x0084 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  float4x3 m;
+  int after;
+};
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  float3x4 const t = transpose(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  float const l = length(float3((*(tint_symbol))[0].m[1].elements).zxy);
+  float const a = fabs(float3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_fn.wgsl.expected.msl
index 2406d51..e8c56ff 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_fn.wgsl.expected.msl
@@ -14,15 +14,50 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float4x3 m;
-  /* 0x0050 */ tint_array<int8_t, 48> tint_pad_1;
-  /* 0x0080 */ int after;
-  /* 0x0084 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 4> m;
+  /* 0x0050 */ tint_array<int8_t, 48> tint_pad_2;
+  /* 0x0080 */ int after;
+  /* 0x0084 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  float4x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
 void a(tint_array<S, 4> a_1) {
 }
 
@@ -38,12 +73,12 @@
 void e(float f_1) {
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[2]);
-  c((*(tint_symbol))[2].m);
-  d(float3((*(tint_symbol))[0].m[1]).zxy);
-  e(float3((*(tint_symbol))[0].m[1]).zxy[0]);
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite_2(*(tint_symbol)));
+  b(tint_unpack_vec3_in_composite_1((*(tint_symbol))[2]));
+  c(tint_unpack_vec3_in_composite((*(tint_symbol))[2].m));
+  d(float3((*(tint_symbol))[0].m[1].elements).zxy);
+  e(float3((*(tint_symbol))[0].m[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_private.wgsl.expected.msl
index 2392000..f8b9e4a 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_private.wgsl.expected.msl
@@ -14,21 +14,56 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float4x3 m;
-  /* 0x0050 */ tint_array<int8_t, 48> tint_pad_1;
-  /* 0x0080 */ int after;
-  /* 0x0084 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 4> m;
+  /* 0x0050 */ tint_array<int8_t, 48> tint_pad_2;
+  /* 0x0080 */ int after;
+  /* 0x0084 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  int before;
+  float4x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread tint_array<S, 4> tint_symbol = {};
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[2];
-  tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = float3((*(tint_symbol_1))[0].m[1]).zxy;
+  tint_symbol = tint_unpack_vec3_in_composite_2(*(tint_symbol_1));
+  tint_symbol[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]);
+  tint_symbol[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m);
+  tint_symbol[1].m[0] = float3((*(tint_symbol_1))[0].m[1].elements).zxy;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_storage.wgsl.expected.msl
index 6014fc4..37070d6 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_storage.wgsl.expected.msl
@@ -14,39 +14,74 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float4x3 m;
-  /* 0x0050 */ tint_array<int8_t, 48> tint_pad_1;
-  /* 0x0080 */ int after;
-  /* 0x0084 */ tint_array<int8_t, 60> tint_pad_2;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-void assign_and_preserve_padding_2(device float4x3* const dest, float4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 4> m;
+  /* 0x0050 */ tint_array<int8_t, 48> tint_pad_2;
+  /* 0x0080 */ int after;
+  /* 0x0084 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-void assign_and_preserve_padding_1(device S* const dest, S value) {
+struct S {
+  int before;
+  float4x3 m;
+  int after;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void assign_and_preserve_padding_2(device tint_array<tint_packed_vec3_f32_array_element, 4>* const dest, float4x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+  (*(dest))[3u].elements = packed_float3(value[3u]);
+}
+
+void assign_and_preserve_padding_1(device S_tint_packed_vec3* const dest, S value) {
   (*(dest)).before = value.before;
   assign_and_preserve_padding_2(&((*(dest)).m), value.m);
   (*(dest)).after = value.after;
 }
 
-void assign_and_preserve_padding(device tint_array<S, 4>* const dest, tint_array<S, 4> value) {
+void assign_and_preserve_padding(device tint_array<S_tint_packed_vec3, 4>* const dest, tint_array<S, 4> value) {
   for(uint i = 0u; (i < 4u); i = (i + 1u)) {
     assign_and_preserve_padding_1(&((*(dest))[i]), value[i]);
   }
 }
 
-kernel void f(device tint_array<S, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S, 4>* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
-  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), (*(tint_symbol_1))[2].m);
-  (*(tint_symbol))[1].m[0] = float3((*(tint_symbol_1))[0].m[1]).zxy;
+kernel void f(device tint_array<S_tint_packed_vec3, 4>* tint_symbol [[buffer(1)]], const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite_2(*(tint_symbol_1)));
+  assign_and_preserve_padding_1(&((*(tint_symbol))[1]), tint_unpack_vec3_in_composite_1((*(tint_symbol_1))[2]));
+  assign_and_preserve_padding_2(&((*(tint_symbol))[3].m), tint_unpack_vec3_in_composite((*(tint_symbol_1))[2].m));
+  (*(tint_symbol))[1].m[0].elements = packed_float3(float3((*(tint_symbol_1))[0].m[1].elements).zxy);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_workgroup.wgsl.expected.msl
index 17fa37d..c86e1dd 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x3_f32/to_workgroup.wgsl.expected.msl
@@ -15,32 +15,67 @@
 };
 
 struct S {
-  /* 0x0000 */ int before;
-  /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0010 */ float4x3 m;
-  /* 0x0050 */ tint_array<int8_t, 48> tint_pad_1;
-  /* 0x0080 */ int after;
-  /* 0x0084 */ tint_array<int8_t, 60> tint_pad_2;
+  int before;
+  float4x3 m;
+  int after;
 };
 
 struct tint_symbol_6 {
   tint_array<S, 4> w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S, 4>* const tint_symbol_2) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ int before;
+  /* 0x0004 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0010 */ tint_array<tint_packed_vec3_f32_array_element, 4> m;
+  /* 0x0050 */ tint_array<int8_t, 48> tint_pad_2;
+  /* 0x0080 */ int after;
+  /* 0x0084 */ tint_array<int8_t, 60> tint_pad_3;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.before = in.before;
+  result.m = tint_unpack_vec3_in_composite(in.m);
+  result.after = in.after;
+  return result;
+}
+
+tint_array<S, 4> tint_unpack_vec3_in_composite_2(tint_array<S_tint_packed_vec3, 4> in) {
+  tint_array<S, 4> result = {};
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = tint_unpack_vec3_in_composite_1(in[i]);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup tint_array<S, 4>* const tint_symbol_1, const constant tint_array<S_tint_packed_vec3, 4>* const tint_symbol_2) {
   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     uint const i = idx;
     S const tint_symbol = S{};
     (*(tint_symbol_1))[i] = tint_symbol;
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol_1) = *(tint_symbol_2);
-  (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
-  (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = float3((*(tint_symbol_2))[0].m[1]).zxy;
+  *(tint_symbol_1) = tint_unpack_vec3_in_composite_2(*(tint_symbol_2));
+  (*(tint_symbol_1))[1] = tint_unpack_vec3_in_composite_1((*(tint_symbol_2))[2]);
+  (*(tint_symbol_1))[3].m = tint_unpack_vec3_in_composite((*(tint_symbol_2))[2].m);
+  (*(tint_symbol_1))[1].m[0] = float3((*(tint_symbol_2))[0].m[1].elements).zxy;
 }
 
-kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<S_tint_packed_vec3, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup tint_array<S, 4>* const tint_symbol_3 = &((*(tint_symbol_4)).w);
   f_inner(local_invocation_index, tint_symbol_3, tint_symbol_5);
   return;
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_builtin.wgsl.expected.msl
index 7f59502..760774a 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_builtin.wgsl.expected.msl
@@ -25,8 +25,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   half4x4 const t = transpose((*(tint_symbol))[2].m);
-  half const l = length(half4((*(tint_symbol))[0].m[1]).ywxz);
-  half const a = fabs(half4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  half const l = length((*(tint_symbol))[0].m[1].ywxz);
+  half const a = fabs((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_fn.wgsl.expected.msl
index 7524e8b..5dc1428 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_fn.wgsl.expected.msl
@@ -42,8 +42,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(half4((*(tint_symbol))[0].m[1]).ywxz);
-  e(half4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  d((*(tint_symbol))[0].m[1].ywxz);
+  e((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_private.wgsl.expected.msl
index 4b6869d..94334df 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_private.wgsl.expected.msl
@@ -28,7 +28,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = half4((*(tint_symbol_1))[0].m[1]).ywxz;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_storage.wgsl.expected.msl
index fe9a40a..4d16bf6 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_storage.wgsl.expected.msl
@@ -39,7 +39,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = half4((*(tint_symbol_1))[0].m[1]).ywxz;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_workgroup.wgsl.expected.msl
index f1d4c32..0b6c9ea 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x4_f16/to_workgroup.wgsl.expected.msl
@@ -37,7 +37,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = half4((*(tint_symbol_2))[0].m[1]).ywxz;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].ywxz;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_builtin.wgsl.expected.msl
index e7981db..575a081 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_builtin.wgsl.expected.msl
@@ -25,8 +25,8 @@
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol [[buffer(0)]]) {
   float4x4 const t = transpose((*(tint_symbol))[2].m);
-  float const l = length(float4((*(tint_symbol))[0].m[1]).ywxz);
-  float const a = fabs(float4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  float const l = length((*(tint_symbol))[0].m[1].ywxz);
+  float const a = fabs((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_fn.wgsl.expected.msl
index 032931f..34dbc7c 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_fn.wgsl.expected.msl
@@ -42,8 +42,8 @@
   a(*(tint_symbol));
   b((*(tint_symbol))[2]);
   c((*(tint_symbol))[2].m);
-  d(float4((*(tint_symbol))[0].m[1]).ywxz);
-  e(float4((*(tint_symbol))[0].m[1]).ywxz[0]);
+  d((*(tint_symbol))[0].m[1].ywxz);
+  e((*(tint_symbol))[0].m[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_private.wgsl.expected.msl
index ebaafb7..c124b5b 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_private.wgsl.expected.msl
@@ -28,7 +28,7 @@
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[2];
   tint_symbol[3].m = (*(tint_symbol_1))[2].m;
-  tint_symbol[1].m[0] = float4((*(tint_symbol_1))[0].m[1]).ywxz;
+  tint_symbol[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_storage.wgsl.expected.msl
index d99a1a4..bc5986c 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_storage.wgsl.expected.msl
@@ -39,7 +39,7 @@
   assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
   assign_and_preserve_padding_1(&((*(tint_symbol))[1]), (*(tint_symbol_1))[2]);
   (*(tint_symbol))[3].m = (*(tint_symbol_1))[2].m;
-  (*(tint_symbol))[1].m[0] = float4((*(tint_symbol_1))[0].m[1]).ywxz;
+  (*(tint_symbol))[1].m[0] = (*(tint_symbol_1))[0].m[1].ywxz;
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_workgroup.wgsl.expected.msl
index 302c388..832baa2 100644
--- a/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/struct/mat4x4_f32/to_workgroup.wgsl.expected.msl
@@ -37,7 +37,7 @@
   *(tint_symbol_1) = *(tint_symbol_2);
   (*(tint_symbol_1))[1] = (*(tint_symbol_2))[2];
   (*(tint_symbol_1))[3].m = (*(tint_symbol_2))[2].m;
-  (*(tint_symbol_1))[1].m[0] = float4((*(tint_symbol_2))[0].m[1]).ywxz;
+  (*(tint_symbol_1))[1].m[0] = (*(tint_symbol_2))[0].m[1].ywxz;
 }
 
 kernel void f(const constant tint_array<S, 4>* tint_symbol_5 [[buffer(0)]], threadgroup tint_symbol_6* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_builtin.wgsl.expected.msl
index 2b5e676..d2e2d7f 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(const constant half2x2* tint_symbol [[buffer(0)]]) {
   half2x2 const t = transpose(*(tint_symbol));
   half const l = length((*(tint_symbol))[1]);
-  half const a = fabs(half2((*(tint_symbol))[0]).yx[0]);
+  half const a = fabs((*(tint_symbol))[0].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_fn.wgsl.expected.msl
index 8c3ff4f..2775d97 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant half2x2* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(half2((*(tint_symbol))[1]).yx);
+  b((*(tint_symbol))[1].yx);
   c((*(tint_symbol))[1][0]);
-  c(half2((*(tint_symbol))[1]).yx[0]);
+  c((*(tint_symbol))[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_private.wgsl.expected.msl
index 4d82450..748687f 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   thread half2x2 tint_symbol = half2x2(0.0h);
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = half2((*(tint_symbol_1))[0]).yx;
+  tint_symbol[1] = (*(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_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_storage.wgsl.expected.msl
index 52b1327..bfe91a3 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(device half2x2* tint_symbol [[buffer(1)]], const constant half2x2* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[1] = (*(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_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_workgroup.wgsl.expected.msl
index 270a66d..6dc41f8 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2_f16/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].yx;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_builtin.wgsl.expected.msl
index 1a4d22e..49f7ac3 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 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]);
+  float const a = fabs((*(tint_symbol))[0].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_fn.wgsl.expected.msl
index f160d72..4b9fe8c 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant float2x2* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(float2((*(tint_symbol))[1]).yx);
+  b((*(tint_symbol))[1].yx);
   c((*(tint_symbol))[1][0]);
-  c(float2((*(tint_symbol))[1]).yx[0]);
+  c((*(tint_symbol))[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_private.wgsl.expected.msl
index 76bf1ad..e80a8b6 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   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[1] = (*(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_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_storage.wgsl.expected.msl
index c265005..d2f3d70 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 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))[1] = (*(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_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_workgroup.wgsl.expected.msl
index 44993bc..e2c5083 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x2_f32/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   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))[1] = (*(tint_symbol_1))[0].yx;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
index f4a04e8..4b6e675 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
@@ -1,17 +1,43 @@
 #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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
 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 half2x3* tint_symbol_2 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol_2 [[buffer(0)]]) {
   int const tint_symbol = i();
   int const p_m_i_save = tint_symbol;
-  half2x3 const l_m = *(tint_symbol_2);
-  half3 const l_m_i = (*(tint_symbol_2))[p_m_i_save];
+  half2x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_2));
+  half3 const l_m_i = half3((*(tint_symbol_2))[p_m_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl
index 036bb82..20f1196 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/static_index_via_ptr.wgsl.expected.msl
@@ -1,15 +1,41 @@
 #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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
 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 half2x3* tint_symbol_1 [[buffer(0)]]) {
-  half2x3 const l_m = *(tint_symbol_1);
-  half3 const l_m_1 = (*(tint_symbol_1))[1];
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol_1 [[buffer(0)]]) {
+  half2x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  half3 const l_m_1 = half3((*(tint_symbol_1))[1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_builtin.wgsl.expected.msl
index c81aee4..bc97605 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_builtin.wgsl.expected.msl
@@ -1,10 +1,36 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant half2x3* tint_symbol [[buffer(0)]]) {
-  half3x2 const t = transpose(*(tint_symbol));
-  half const l = length((*(tint_symbol))[1]);
-  half const a = fabs(half3((*(tint_symbol))[0]).zxy[0]);
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol [[buffer(0)]]) {
+  half3x2 const t = transpose(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  half const l = length(half3((*(tint_symbol))[1].elements));
+  half const a = fabs(half3((*(tint_symbol))[0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_fn.wgsl.expected.msl
index 339491e..f0ce93c 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_fn.wgsl.expected.msl
@@ -1,6 +1,32 @@
 #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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
 void a(half2x3 m) {
 }
 
@@ -10,12 +36,12 @@
 void c(half f_1) {
 }
 
-kernel void f(const constant half2x3* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  b(half3((*(tint_symbol))[1]).zxy);
-  c((*(tint_symbol))[1][0]);
-  c(half3((*(tint_symbol))[1]).zxy[0]);
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  b(half3((*(tint_symbol))[1].elements));
+  b(half3((*(tint_symbol))[1].elements).zxy);
+  c((*(tint_symbol))[1].elements[0]);
+  c(half3((*(tint_symbol))[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_private.wgsl.expected.msl
index a233531..2889fe9 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_private.wgsl.expected.msl
@@ -1,12 +1,38 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant half2x3* tint_symbol_1 [[buffer(0)]]) {
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol_1 [[buffer(0)]]) {
   thread half2x3 tint_symbol = half2x3(0.0h);
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = half3((*(tint_symbol_1))[0]).zxy;
-  tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
+  tint_symbol = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  tint_symbol[1] = half3((*(tint_symbol_1))[0].elements);
+  tint_symbol[1] = half3((*(tint_symbol_1))[0].elements).zxy;
+  tint_symbol[0][1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_storage.wgsl.expected.msl
index 4661a71..bcd5c22 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_storage.wgsl.expected.msl
@@ -1,16 +1,42 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device half2x3* const dest, half2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void f(device half2x3* tint_symbol [[buffer(1)]], const constant half2x3* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f16_array_element, 2>* const dest, half2x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+}
+
+kernel void f(device tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol [[buffer(1)]], const constant tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite(*(tint_symbol_1)));
+  (*(tint_symbol))[1].elements = (*(tint_symbol_1))[0].elements;
+  (*(tint_symbol))[1].elements = packed_half3(half3((*(tint_symbol_1))[0].elements).zxy);
+  (*(tint_symbol))[0].elements[1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_workgroup.wgsl.expected.msl
index 4ccd046..f501690 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f16/to_workgroup.wgsl.expected.msl
@@ -1,22 +1,48 @@
 #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 {
   half2x3 w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup half2x3* const tint_symbol, const constant half2x3* const tint_symbol_1) {
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup half2x3* const tint_symbol, const constant tint_array<tint_packed_vec3_f16_array_element, 2>* const tint_symbol_1) {
   {
     *(tint_symbol) = half2x3(half3(0.0h), half3(0.0h));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0].elements);
+  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0].elements).zxy;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1].elements[0];
 }
 
-kernel void f(const constant half2x3* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup half2x3* 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/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
index cecbfbb..04c5d41 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
@@ -1,17 +1,43 @@
 #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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
 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 float2x3* tint_symbol_2 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol_2 [[buffer(0)]]) {
   int const tint_symbol = i();
   int const p_m_i_save = tint_symbol;
-  float2x3 const l_m = *(tint_symbol_2);
-  float3 const l_m_i = (*(tint_symbol_2))[p_m_i_save];
+  float2x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_2));
+  float3 const l_m_i = float3((*(tint_symbol_2))[p_m_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl
index 68130f7..6ab436c 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/static_index_via_ptr.wgsl.expected.msl
@@ -1,15 +1,41 @@
 #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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
 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 float2x3* tint_symbol_1 [[buffer(0)]]) {
-  float2x3 const l_m = *(tint_symbol_1);
-  float3 const l_m_1 = (*(tint_symbol_1))[1];
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol_1 [[buffer(0)]]) {
+  float2x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  float3 const l_m_1 = float3((*(tint_symbol_1))[1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_builtin.wgsl.expected.msl
index 96989c8..997bc9c 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_builtin.wgsl.expected.msl
@@ -1,10 +1,36 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant float2x3* tint_symbol [[buffer(0)]]) {
-  float3x2 const t = transpose(*(tint_symbol));
-  float const l = length((*(tint_symbol))[1]);
-  float const a = fabs(float3((*(tint_symbol))[0]).zxy[0]);
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol [[buffer(0)]]) {
+  float3x2 const t = transpose(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  float const l = length(float3((*(tint_symbol))[1].elements));
+  float const a = fabs(float3((*(tint_symbol))[0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_fn.wgsl.expected.msl
index 9d84e31..35a013f 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_fn.wgsl.expected.msl
@@ -1,6 +1,32 @@
 #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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
 void a(float2x3 m) {
 }
 
@@ -10,12 +36,12 @@
 void c(float f_1) {
 }
 
-kernel void f(const constant float2x3* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  b(float3((*(tint_symbol))[1]).zxy);
-  c((*(tint_symbol))[1][0]);
-  c(float3((*(tint_symbol))[1]).zxy[0]);
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  b(float3((*(tint_symbol))[1].elements));
+  b(float3((*(tint_symbol))[1].elements).zxy);
+  c((*(tint_symbol))[1].elements[0]);
+  c(float3((*(tint_symbol))[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_private.wgsl.expected.msl
index d2181af..8bc9638 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_private.wgsl.expected.msl
@@ -1,12 +1,38 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant float2x3* tint_symbol_1 [[buffer(0)]]) {
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol_1 [[buffer(0)]]) {
   thread float2x3 tint_symbol = float2x3(0.0f);
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = float3((*(tint_symbol_1))[0]).zxy;
-  tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
+  tint_symbol = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  tint_symbol[1] = float3((*(tint_symbol_1))[0].elements);
+  tint_symbol[1] = float3((*(tint_symbol_1))[0].elements).zxy;
+  tint_symbol[0][1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_storage.wgsl.expected.msl
index 670bceb..28c4697 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_storage.wgsl.expected.msl
@@ -1,16 +1,42 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device float2x3* const dest, float2x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void f(device float2x3* tint_symbol [[buffer(1)]], const constant float2x3* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f32_array_element, 2>* const dest, float2x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+}
+
+kernel void f(device tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol [[buffer(1)]], const constant tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite(*(tint_symbol_1)));
+  (*(tint_symbol))[1].elements = (*(tint_symbol_1))[0].elements;
+  (*(tint_symbol))[1].elements = packed_float3(float3((*(tint_symbol_1))[0].elements).zxy);
+  (*(tint_symbol))[0].elements[1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_workgroup.wgsl.expected.msl
index 9bf471f..87a4247 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x3_f32/to_workgroup.wgsl.expected.msl
@@ -1,22 +1,48 @@
 #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 {
   float2x3 w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup float2x3* const tint_symbol, const constant float2x3* const tint_symbol_1) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup float2x3* const tint_symbol, const constant tint_array<tint_packed_vec3_f32_array_element, 2>* const tint_symbol_1) {
   {
     *(tint_symbol) = float2x3(float3(0.0f), float3(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0].elements);
+  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0].elements).zxy;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1].elements[0];
 }
 
-kernel void f(const constant float2x3* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup float2x3* 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/mat2x4_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_builtin.wgsl.expected.msl
index ab20cc5..0bd67d5 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(const constant half2x4* tint_symbol [[buffer(0)]]) {
   half4x2 const t = transpose(*(tint_symbol));
   half const l = length((*(tint_symbol))[1]);
-  half const a = fabs(half4((*(tint_symbol))[0]).ywxz[0]);
+  half const a = fabs((*(tint_symbol))[0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_fn.wgsl.expected.msl
index e58cdf3..0e3bc70 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant half2x4* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(half4((*(tint_symbol))[1]).ywxz);
+  b((*(tint_symbol))[1].ywxz);
   c((*(tint_symbol))[1][0]);
-  c(half4((*(tint_symbol))[1]).ywxz[0]);
+  c((*(tint_symbol))[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_private.wgsl.expected.msl
index 5042d02..4c18d53 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   thread half2x4 tint_symbol = half2x4(0.0h);
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = half4((*(tint_symbol_1))[0]).ywxz;
+  tint_symbol[1] = (*(tint_symbol_1))[0].ywxz;
   tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_storage.wgsl.expected.msl
index 44e2bbb..bbeb9a9 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(device half2x4* tint_symbol [[buffer(1)]], const constant half2x4* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_workgroup.wgsl.expected.msl
index 879dc14..ead159e 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x4_f16/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_builtin.wgsl.expected.msl
index e4ca0da..2763dca 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(const constant float2x4* tint_symbol [[buffer(0)]]) {
   float4x2 const t = transpose(*(tint_symbol));
   float const l = length((*(tint_symbol))[1]);
-  float const a = fabs(float4((*(tint_symbol))[0]).ywxz[0]);
+  float const a = fabs((*(tint_symbol))[0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_fn.wgsl.expected.msl
index c0abb91..d1dac89 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant float2x4* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(float4((*(tint_symbol))[1]).ywxz);
+  b((*(tint_symbol))[1].ywxz);
   c((*(tint_symbol))[1][0]);
-  c(float4((*(tint_symbol))[1]).ywxz[0]);
+  c((*(tint_symbol))[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_private.wgsl.expected.msl
index 8405e42..5351247 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   thread float2x4 tint_symbol = float2x4(0.0f);
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = float4((*(tint_symbol_1))[0]).ywxz;
+  tint_symbol[1] = (*(tint_symbol_1))[0].ywxz;
   tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_storage.wgsl.expected.msl
index a99b798..53503fc 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(device float2x4* tint_symbol [[buffer(1)]], const constant float2x4* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_workgroup.wgsl.expected.msl
index 35d7ce5..68fd2d3 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat2x4_f32/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_builtin.wgsl.expected.msl
index 5a86f0d..1237681 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(const constant half3x2* tint_symbol [[buffer(0)]]) {
   half2x3 const t = transpose(*(tint_symbol));
   half const l = length((*(tint_symbol))[1]);
-  half const a = fabs(half2((*(tint_symbol))[0]).yx[0]);
+  half const a = fabs((*(tint_symbol))[0].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_fn.wgsl.expected.msl
index 04006cd..5a74893 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant half3x2* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(half2((*(tint_symbol))[1]).yx);
+  b((*(tint_symbol))[1].yx);
   c((*(tint_symbol))[1][0]);
-  c(half2((*(tint_symbol))[1]).yx[0]);
+  c((*(tint_symbol))[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_private.wgsl.expected.msl
index 85a9952..f88a3fa 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   thread half3x2 tint_symbol = half3x2(0.0h);
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = half2((*(tint_symbol_1))[0]).yx;
+  tint_symbol[1] = (*(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_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_storage.wgsl.expected.msl
index 2109a16..f087d43 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(device half3x2* tint_symbol [[buffer(1)]], const constant half3x2* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[1] = (*(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_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_workgroup.wgsl.expected.msl
index bfd1bb3..4b1abf7 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2_f16/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].yx;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_builtin.wgsl.expected.msl
index 009f12e..1fe1d6c 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 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]);
+  float const a = fabs((*(tint_symbol))[0].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_fn.wgsl.expected.msl
index 278a0f4..b4bd277 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant float3x2* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(float2((*(tint_symbol))[1]).yx);
+  b((*(tint_symbol))[1].yx);
   c((*(tint_symbol))[1][0]);
-  c(float2((*(tint_symbol))[1]).yx[0]);
+  c((*(tint_symbol))[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_private.wgsl.expected.msl
index c95e5b0..f0f39fe 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   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[1] = (*(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_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_storage.wgsl.expected.msl
index 2d27746..4e471bb 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 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))[1] = (*(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_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_workgroup.wgsl.expected.msl
index 59f976e..b8b1ab3 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x2_f32/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   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))[1] = (*(tint_symbol_1))[0].yx;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
index 7d5c27c..52ad632 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
@@ -1,17 +1,43 @@
 #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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
 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 half3x3* tint_symbol_2 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol_2 [[buffer(0)]]) {
   int const tint_symbol = i();
   int const p_m_i_save = tint_symbol;
-  half3x3 const l_m = *(tint_symbol_2);
-  half3 const l_m_i = (*(tint_symbol_2))[p_m_i_save];
+  half3x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_2));
+  half3 const l_m_i = half3((*(tint_symbol_2))[p_m_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/static_index_via_ptr.wgsl.expected.msl
index 8950017..0840049 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/static_index_via_ptr.wgsl.expected.msl
@@ -1,15 +1,41 @@
 #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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
 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 half3x3* tint_symbol_1 [[buffer(0)]]) {
-  half3x3 const l_m = *(tint_symbol_1);
-  half3 const l_m_1 = (*(tint_symbol_1))[1];
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol_1 [[buffer(0)]]) {
+  half3x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  half3 const l_m_1 = half3((*(tint_symbol_1))[1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_builtin.wgsl.expected.msl
index 3b7e954..2416843 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_builtin.wgsl.expected.msl
@@ -1,10 +1,36 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant half3x3* tint_symbol [[buffer(0)]]) {
-  half3x3 const t = transpose(*(tint_symbol));
-  half const l = length((*(tint_symbol))[1]);
-  half const a = fabs(half3((*(tint_symbol))[0]).zxy[0]);
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol [[buffer(0)]]) {
+  half3x3 const t = transpose(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  half const l = length(half3((*(tint_symbol))[1].elements));
+  half const a = fabs(half3((*(tint_symbol))[0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_fn.wgsl.expected.msl
index 3ae8932..1c6b945 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_fn.wgsl.expected.msl
@@ -1,6 +1,32 @@
 #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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
 void a(half3x3 m) {
 }
 
@@ -10,12 +36,12 @@
 void c(half f_1) {
 }
 
-kernel void f(const constant half3x3* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  b(half3((*(tint_symbol))[1]).zxy);
-  c((*(tint_symbol))[1][0]);
-  c(half3((*(tint_symbol))[1]).zxy[0]);
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  b(half3((*(tint_symbol))[1].elements));
+  b(half3((*(tint_symbol))[1].elements).zxy);
+  c((*(tint_symbol))[1].elements[0]);
+  c(half3((*(tint_symbol))[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_private.wgsl.expected.msl
index 7e3877d..3249af1 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_private.wgsl.expected.msl
@@ -1,12 +1,38 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant half3x3* tint_symbol_1 [[buffer(0)]]) {
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol_1 [[buffer(0)]]) {
   thread half3x3 tint_symbol = half3x3(0.0h);
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = half3((*(tint_symbol_1))[0]).zxy;
-  tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
+  tint_symbol = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  tint_symbol[1] = half3((*(tint_symbol_1))[0].elements);
+  tint_symbol[1] = half3((*(tint_symbol_1))[0].elements).zxy;
+  tint_symbol[0][1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_storage.wgsl.expected.msl
index e621117..a2c2764 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_storage.wgsl.expected.msl
@@ -1,17 +1,43 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device half3x3* const dest, half3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void f(device half3x3* tint_symbol [[buffer(1)]], const constant half3x3* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f16_array_element, 3>* const dest, half3x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
+}
+
+kernel void f(device tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol [[buffer(1)]], const constant tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite(*(tint_symbol_1)));
+  (*(tint_symbol))[1].elements = (*(tint_symbol_1))[0].elements;
+  (*(tint_symbol))[1].elements = packed_half3(half3((*(tint_symbol_1))[0].elements).zxy);
+  (*(tint_symbol))[0].elements[1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_workgroup.wgsl.expected.msl
index 849494f..b6b09a3 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f16/to_workgroup.wgsl.expected.msl
@@ -1,22 +1,48 @@
 #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 {
   half3x3 w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup half3x3* const tint_symbol, const constant half3x3* const tint_symbol_1) {
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup half3x3* const tint_symbol, const constant tint_array<tint_packed_vec3_f16_array_element, 3>* const tint_symbol_1) {
   {
     *(tint_symbol) = half3x3(half3(0.0h), half3(0.0h), half3(0.0h));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0].elements);
+  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0].elements).zxy;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1].elements[0];
 }
 
-kernel void f(const constant half3x3* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup half3x3* 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/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
index f7cf012..98e4aa7 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
@@ -1,17 +1,43 @@
 #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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
 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 float3x3* tint_symbol_2 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol_2 [[buffer(0)]]) {
   int const tint_symbol = i();
   int const p_m_i_save = tint_symbol;
-  float3x3 const l_m = *(tint_symbol_2);
-  float3 const l_m_i = (*(tint_symbol_2))[p_m_i_save];
+  float3x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_2));
+  float3 const l_m_i = float3((*(tint_symbol_2))[p_m_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl
index 8d47ca6..06ae933 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/static_index_via_ptr.wgsl.expected.msl
@@ -1,15 +1,41 @@
 #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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
 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 float3x3* tint_symbol_1 [[buffer(0)]]) {
-  float3x3 const l_m = *(tint_symbol_1);
-  float3 const l_m_1 = (*(tint_symbol_1))[1];
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol_1 [[buffer(0)]]) {
+  float3x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  float3 const l_m_1 = float3((*(tint_symbol_1))[1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_builtin.wgsl.expected.msl
index 448c8e0..01c6635 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_builtin.wgsl.expected.msl
@@ -1,10 +1,36 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant float3x3* tint_symbol [[buffer(0)]]) {
-  float3x3 const t = transpose(*(tint_symbol));
-  float const l = length((*(tint_symbol))[1]);
-  float const a = fabs(float3((*(tint_symbol))[0]).zxy[0]);
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol [[buffer(0)]]) {
+  float3x3 const t = transpose(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  float const l = length(float3((*(tint_symbol))[1].elements));
+  float const a = fabs(float3((*(tint_symbol))[0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_fn.wgsl.expected.msl
index e0131fb..ca1223e 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_fn.wgsl.expected.msl
@@ -1,6 +1,32 @@
 #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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
 void a(float3x3 m) {
 }
 
@@ -10,12 +36,12 @@
 void c(float f_1) {
 }
 
-kernel void f(const constant float3x3* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  b(float3((*(tint_symbol))[1]).zxy);
-  c((*(tint_symbol))[1][0]);
-  c(float3((*(tint_symbol))[1]).zxy[0]);
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  b(float3((*(tint_symbol))[1].elements));
+  b(float3((*(tint_symbol))[1].elements).zxy);
+  c((*(tint_symbol))[1].elements[0]);
+  c(float3((*(tint_symbol))[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_private.wgsl.expected.msl
index 4471b02..0b5388c 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_private.wgsl.expected.msl
@@ -1,12 +1,38 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant float3x3* tint_symbol_1 [[buffer(0)]]) {
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol_1 [[buffer(0)]]) {
   thread float3x3 tint_symbol = float3x3(0.0f);
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = float3((*(tint_symbol_1))[0]).zxy;
-  tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
+  tint_symbol = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  tint_symbol[1] = float3((*(tint_symbol_1))[0].elements);
+  tint_symbol[1] = float3((*(tint_symbol_1))[0].elements).zxy;
+  tint_symbol[0][1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_storage.wgsl.expected.msl
index f7b9608..ebe399b 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_storage.wgsl.expected.msl
@@ -1,17 +1,43 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device float3x3* const dest, float3x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void f(device float3x3* tint_symbol [[buffer(1)]], const constant float3x3* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f32_array_element, 3>* const dest, float3x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+}
+
+kernel void f(device tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol [[buffer(1)]], const constant tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite(*(tint_symbol_1)));
+  (*(tint_symbol))[1].elements = (*(tint_symbol_1))[0].elements;
+  (*(tint_symbol))[1].elements = packed_float3(float3((*(tint_symbol_1))[0].elements).zxy);
+  (*(tint_symbol))[0].elements[1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_workgroup.wgsl.expected.msl
index 9c73286..8a82992 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x3_f32/to_workgroup.wgsl.expected.msl
@@ -1,22 +1,48 @@
 #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 {
   float3x3 w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup float3x3* const tint_symbol, const constant float3x3* const tint_symbol_1) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup float3x3* const tint_symbol, const constant tint_array<tint_packed_vec3_f32_array_element, 3>* const tint_symbol_1) {
   {
     *(tint_symbol) = float3x3(float3(0.0f), float3(0.0f), float3(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0].elements);
+  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0].elements).zxy;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1].elements[0];
 }
 
-kernel void f(const constant float3x3* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup float3x3* 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/mat3x4_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_builtin.wgsl.expected.msl
index 45f91fd..83bdcd9 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(const constant half3x4* tint_symbol [[buffer(0)]]) {
   half4x3 const t = transpose(*(tint_symbol));
   half const l = length((*(tint_symbol))[1]);
-  half const a = fabs(half4((*(tint_symbol))[0]).ywxz[0]);
+  half const a = fabs((*(tint_symbol))[0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_fn.wgsl.expected.msl
index 8f44101..f23242a 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant half3x4* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(half4((*(tint_symbol))[1]).ywxz);
+  b((*(tint_symbol))[1].ywxz);
   c((*(tint_symbol))[1][0]);
-  c(half4((*(tint_symbol))[1]).ywxz[0]);
+  c((*(tint_symbol))[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_private.wgsl.expected.msl
index 2293b30..67376a0 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   thread half3x4 tint_symbol = half3x4(0.0h);
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = half4((*(tint_symbol_1))[0]).ywxz;
+  tint_symbol[1] = (*(tint_symbol_1))[0].ywxz;
   tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_storage.wgsl.expected.msl
index 7684631..18296e6 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(device half3x4* tint_symbol [[buffer(1)]], const constant half3x4* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_workgroup.wgsl.expected.msl
index 8291498..6c7199b 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x4_f16/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_builtin.wgsl.expected.msl
index 78ddda6..bda73e1 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(const constant float3x4* tint_symbol [[buffer(0)]]) {
   float4x3 const t = transpose(*(tint_symbol));
   float const l = length((*(tint_symbol))[1]);
-  float const a = fabs(float4((*(tint_symbol))[0]).ywxz[0]);
+  float const a = fabs((*(tint_symbol))[0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_fn.wgsl.expected.msl
index 1097f7e..a4af855 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant float3x4* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(float4((*(tint_symbol))[1]).ywxz);
+  b((*(tint_symbol))[1].ywxz);
   c((*(tint_symbol))[1][0]);
-  c(float4((*(tint_symbol))[1]).ywxz[0]);
+  c((*(tint_symbol))[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_private.wgsl.expected.msl
index a073777..7a8aed3 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   thread float3x4 tint_symbol = float3x4(0.0f);
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = float4((*(tint_symbol_1))[0]).ywxz;
+  tint_symbol[1] = (*(tint_symbol_1))[0].ywxz;
   tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_storage.wgsl.expected.msl
index d7903f5..85a4549 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(device float3x4* tint_symbol [[buffer(1)]], const constant float3x4* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_workgroup.wgsl.expected.msl
index 37ed55e..eea9373 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat3x4_f32/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_builtin.wgsl.expected.msl
index 1b137c5..ccf50b05 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(const constant half4x2* tint_symbol [[buffer(0)]]) {
   half2x4 const t = transpose(*(tint_symbol));
   half const l = length((*(tint_symbol))[1]);
-  half const a = fabs(half2((*(tint_symbol))[0]).yx[0]);
+  half const a = fabs((*(tint_symbol))[0].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_fn.wgsl.expected.msl
index 25b867f..48b6f20 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant half4x2* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(half2((*(tint_symbol))[1]).yx);
+  b((*(tint_symbol))[1].yx);
   c((*(tint_symbol))[1][0]);
-  c(half2((*(tint_symbol))[1]).yx[0]);
+  c((*(tint_symbol))[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_private.wgsl.expected.msl
index aac8ea7..50b8bd6 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   thread half4x2 tint_symbol = half4x2(0.0h);
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = half2((*(tint_symbol_1))[0]).yx;
+  tint_symbol[1] = (*(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_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_storage.wgsl.expected.msl
index e3cb6f6..c3277d6 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(device half4x2* tint_symbol [[buffer(1)]], const constant half4x2* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[1] = (*(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_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_workgroup.wgsl.expected.msl
index ccec071..d4c93f1 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2_f16/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half2((*(tint_symbol_1))[0]).yx;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].yx;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_builtin.wgsl.expected.msl
index 175bd3e..44e2124 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 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]);
+  float const a = fabs((*(tint_symbol))[0].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_fn.wgsl.expected.msl
index 4cec493..db90748 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant float4x2* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(float2((*(tint_symbol))[1]).yx);
+  b((*(tint_symbol))[1].yx);
   c((*(tint_symbol))[1][0]);
-  c(float2((*(tint_symbol))[1]).yx[0]);
+  c((*(tint_symbol))[1].yx[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_private.wgsl.expected.msl
index b2d3c55..9cfd512 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   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[1] = (*(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_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_storage.wgsl.expected.msl
index fab0f86..cb0341d 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 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))[1] = (*(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_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_workgroup.wgsl.expected.msl
index 6db4db2..543faab 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x2_f32/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   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))[1] = (*(tint_symbol_1))[0].yx;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
index 3e06cd5..7851572 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/dynamic_index_via_ptr.wgsl.expected.msl
@@ -1,17 +1,43 @@
 #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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
 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 half4x3* tint_symbol_2 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol_2 [[buffer(0)]]) {
   int const tint_symbol = i();
   int const p_m_i_save = tint_symbol;
-  half4x3 const l_m = *(tint_symbol_2);
-  half3 const l_m_i = (*(tint_symbol_2))[p_m_i_save];
+  half4x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_2));
+  half3 const l_m_i = half3((*(tint_symbol_2))[p_m_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl
index d08b0d9..97391f4 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/static_index_via_ptr.wgsl.expected.msl
@@ -1,15 +1,41 @@
 #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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
 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 half4x3* tint_symbol_1 [[buffer(0)]]) {
-  half4x3 const l_m = *(tint_symbol_1);
-  half3 const l_m_1 = (*(tint_symbol_1))[1];
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol_1 [[buffer(0)]]) {
+  half4x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  half3 const l_m_1 = half3((*(tint_symbol_1))[1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_builtin.wgsl.expected.msl
index 6bd3adc..4c19ba6 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_builtin.wgsl.expected.msl
@@ -1,10 +1,36 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant half4x3* tint_symbol [[buffer(0)]]) {
-  half3x4 const t = transpose(*(tint_symbol));
-  half const l = length((*(tint_symbol))[1]);
-  half const a = fabs(half3((*(tint_symbol))[0]).zxy[0]);
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol [[buffer(0)]]) {
+  half3x4 const t = transpose(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  half const l = length(half3((*(tint_symbol))[1].elements));
+  half const a = fabs(half3((*(tint_symbol))[0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_fn.wgsl.expected.msl
index 84e67e0..f8bf151 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_fn.wgsl.expected.msl
@@ -1,6 +1,32 @@
 #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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
 void a(half4x3 m) {
 }
 
@@ -10,12 +36,12 @@
 void c(half f_1) {
 }
 
-kernel void f(const constant half4x3* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  b(half3((*(tint_symbol))[1]).zxy);
-  c((*(tint_symbol))[1][0]);
-  c(half3((*(tint_symbol))[1]).zxy[0]);
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  b(half3((*(tint_symbol))[1].elements));
+  b(half3((*(tint_symbol))[1].elements).zxy);
+  c((*(tint_symbol))[1].elements[0]);
+  c(half3((*(tint_symbol))[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_private.wgsl.expected.msl
index 5aa938f..644a82a 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_private.wgsl.expected.msl
@@ -1,12 +1,38 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant half4x3* tint_symbol_1 [[buffer(0)]]) {
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread half4x3 tint_symbol = half4x3(0.0h);
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = half3((*(tint_symbol_1))[0]).zxy;
-  tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
+  tint_symbol = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  tint_symbol[1] = half3((*(tint_symbol_1))[0].elements);
+  tint_symbol[1] = half3((*(tint_symbol_1))[0].elements).zxy;
+  tint_symbol[0][1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_storage.wgsl.expected.msl
index 4b84184..e94bb82 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_storage.wgsl.expected.msl
@@ -1,18 +1,44 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device half4x3* const dest, half4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void f(device half4x3* tint_symbol [[buffer(1)]], const constant half4x3* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f16_array_element, 4>* const dest, half4x3 value) {
+  (*(dest))[0u].elements = packed_half3(value[0u]);
+  (*(dest))[1u].elements = packed_half3(value[1u]);
+  (*(dest))[2u].elements = packed_half3(value[2u]);
+  (*(dest))[3u].elements = packed_half3(value[3u]);
+}
+
+kernel void f(device tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol [[buffer(1)]], const constant tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite(*(tint_symbol_1)));
+  (*(tint_symbol))[1].elements = (*(tint_symbol_1))[0].elements;
+  (*(tint_symbol))[1].elements = packed_half3(half3((*(tint_symbol_1))[0].elements).zxy);
+  (*(tint_symbol))[0].elements[1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_workgroup.wgsl.expected.msl
index 6df9ce1..b96b38e 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f16/to_workgroup.wgsl.expected.msl
@@ -1,22 +1,48 @@
 #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 {
   half4x3 w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup half4x3* const tint_symbol, const constant half4x3* const tint_symbol_1) {
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup half4x3* const tint_symbol, const constant tint_array<tint_packed_vec3_f16_array_element, 4>* const tint_symbol_1) {
   {
     *(tint_symbol) = half4x3(half3(0.0h), half3(0.0h), half3(0.0h), half3(0.0h));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0].elements);
+  (*(tint_symbol))[1] = half3((*(tint_symbol_1))[0].elements).zxy;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1].elements[0];
 }
 
-kernel void f(const constant half4x3* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup half4x3* 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/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
index cb87975..ef30c00 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/dynamic_index_via_ptr.wgsl.expected.msl
@@ -1,17 +1,43 @@
 #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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
 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 float4x3* tint_symbol_2 [[buffer(0)]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol_2 [[buffer(0)]]) {
   int const tint_symbol = i();
   int const p_m_i_save = tint_symbol;
-  float4x3 const l_m = *(tint_symbol_2);
-  float3 const l_m_i = (*(tint_symbol_2))[p_m_i_save];
+  float4x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_2));
+  float3 const l_m_i = float3((*(tint_symbol_2))[p_m_i_save].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl
index 55af02e..313cd69 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/static_index_via_ptr.wgsl.expected.msl
@@ -1,15 +1,41 @@
 #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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
 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 float4x3* tint_symbol_1 [[buffer(0)]]) {
-  float4x3 const l_m = *(tint_symbol_1);
-  float3 const l_m_1 = (*(tint_symbol_1))[1];
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol_1 [[buffer(0)]]) {
+  float4x3 const l_m = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  float3 const l_m_1 = float3((*(tint_symbol_1))[1].elements);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_builtin.wgsl.expected.msl
index 803b6d8..2fd10cb 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_builtin.wgsl.expected.msl
@@ -1,10 +1,36 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant float4x3* tint_symbol [[buffer(0)]]) {
-  float3x4 const t = transpose(*(tint_symbol));
-  float const l = length((*(tint_symbol))[1]);
-  float const a = fabs(float3((*(tint_symbol))[0]).zxy[0]);
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol [[buffer(0)]]) {
+  float3x4 const t = transpose(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  float const l = length(float3((*(tint_symbol))[1].elements));
+  float const a = fabs(float3((*(tint_symbol))[0].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_fn.wgsl.expected.msl
index 2fdb2d1..6c3583e 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_fn.wgsl.expected.msl
@@ -1,6 +1,32 @@
 #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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
 void a(float4x3 m) {
 }
 
@@ -10,12 +36,12 @@
 void c(float f_1) {
 }
 
-kernel void f(const constant float4x3* tint_symbol [[buffer(0)]]) {
-  a(*(tint_symbol));
-  b((*(tint_symbol))[1]);
-  b(float3((*(tint_symbol))[1]).zxy);
-  c((*(tint_symbol))[1][0]);
-  c(float3((*(tint_symbol))[1]).zxy[0]);
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol [[buffer(0)]]) {
+  a(tint_unpack_vec3_in_composite(*(tint_symbol)));
+  b(float3((*(tint_symbol))[1].elements));
+  b(float3((*(tint_symbol))[1].elements).zxy);
+  c((*(tint_symbol))[1].elements[0]);
+  c(float3((*(tint_symbol))[1].elements).zxy[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_private.wgsl.expected.msl
index 904c327..c9b7814 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_private.wgsl.expected.msl
@@ -1,12 +1,38 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void f(const constant float4x3* tint_symbol_1 [[buffer(0)]]) {
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol_1 [[buffer(0)]]) {
   thread float4x3 tint_symbol = float4x3(0.0f);
-  tint_symbol = *(tint_symbol_1);
-  tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = float3((*(tint_symbol_1))[0]).zxy;
-  tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
+  tint_symbol = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  tint_symbol[1] = float3((*(tint_symbol_1))[0].elements);
+  tint_symbol[1] = float3((*(tint_symbol_1))[0].elements).zxy;
+  tint_symbol[0][1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_storage.wgsl.expected.msl
index 82834f0..d1bb402 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_storage.wgsl.expected.msl
@@ -1,18 +1,44 @@
 #include <metal_stdlib>
 
 using namespace metal;
-void assign_and_preserve_padding(device float4x3* const dest, float4x3 value) {
-  (*(dest))[0u] = value[0u];
-  (*(dest))[1u] = value[1u];
-  (*(dest))[2u] = value[2u];
-  (*(dest))[3u] = value[3u];
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
 }
 
-kernel void f(device float4x3* tint_symbol [[buffer(1)]], const constant float4x3* tint_symbol_1 [[buffer(0)]]) {
-  assign_and_preserve_padding(tint_symbol, *(tint_symbol_1));
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+void assign_and_preserve_padding(device tint_array<tint_packed_vec3_f32_array_element, 4>* const dest, float4x3 value) {
+  (*(dest))[0u].elements = packed_float3(value[0u]);
+  (*(dest))[1u].elements = packed_float3(value[1u]);
+  (*(dest))[2u].elements = packed_float3(value[2u]);
+  (*(dest))[3u].elements = packed_float3(value[3u]);
+}
+
+kernel void f(device tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol [[buffer(1)]], const constant tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol_1 [[buffer(0)]]) {
+  assign_and_preserve_padding(tint_symbol, tint_unpack_vec3_in_composite(*(tint_symbol_1)));
+  (*(tint_symbol))[1].elements = (*(tint_symbol_1))[0].elements;
+  (*(tint_symbol))[1].elements = packed_float3(float3((*(tint_symbol_1))[0].elements).zxy);
+  (*(tint_symbol))[0].elements[1] = (*(tint_symbol_1))[1].elements[0];
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_workgroup.wgsl.expected.msl
index ffc9775..93bb82a 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x3_f32/to_workgroup.wgsl.expected.msl
@@ -1,22 +1,48 @@
 #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 {
   float4x3 w;
 };
 
-void f_inner(uint local_invocation_index, threadgroup float4x3* const tint_symbol, const constant float4x3* const tint_symbol_1) {
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+void f_inner(uint local_invocation_index, threadgroup float4x3* const tint_symbol, const constant tint_array<tint_packed_vec3_f32_array_element, 4>* const tint_symbol_1) {
   {
     *(tint_symbol) = float4x3(float3(0.0f), float3(0.0f), float3(0.0f), float3(0.0f));
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
-  *(tint_symbol) = *(tint_symbol_1);
-  (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0]).zxy;
-  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
+  *(tint_symbol) = tint_unpack_vec3_in_composite(*(tint_symbol_1));
+  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0].elements);
+  (*(tint_symbol))[1] = float3((*(tint_symbol_1))[0].elements).zxy;
+  (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1].elements[0];
 }
 
-kernel void f(const constant float4x3* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
+kernel void f(const constant tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol_4 [[buffer(0)]], threadgroup tint_symbol_5* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
   threadgroup float4x3* 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/mat4x4_f16/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_builtin.wgsl.expected.msl
index f05f8a0..0144a11 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(const constant half4x4* tint_symbol [[buffer(0)]]) {
   half4x4 const t = transpose(*(tint_symbol));
   half const l = length((*(tint_symbol))[1]);
-  half const a = fabs(half4((*(tint_symbol))[0]).ywxz[0]);
+  half const a = fabs((*(tint_symbol))[0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_fn.wgsl.expected.msl
index d2d7153..7951bbd 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant half4x4* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(half4((*(tint_symbol))[1]).ywxz);
+  b((*(tint_symbol))[1].ywxz);
   c((*(tint_symbol))[1][0]);
-  c(half4((*(tint_symbol))[1]).ywxz[0]);
+  c((*(tint_symbol))[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_private.wgsl.expected.msl
index 7d4af8b..2d3c84a 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   thread half4x4 tint_symbol = half4x4(0.0h);
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = half4((*(tint_symbol_1))[0]).ywxz;
+  tint_symbol[1] = (*(tint_symbol_1))[0].ywxz;
   tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_storage.wgsl.expected.msl
index 4530643..4594764 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(device half4x4* tint_symbol [[buffer(1)]], const constant half4x4* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_workgroup.wgsl.expected.msl
index 57392de..b1f462d 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x4_f16/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = half4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_builtin.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_builtin.wgsl.expected.msl
index 61a809d..395e818 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_builtin.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_builtin.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(const constant float4x4* tint_symbol [[buffer(0)]]) {
   float4x4 const t = transpose(*(tint_symbol));
   float const l = length((*(tint_symbol))[1]);
-  float const a = fabs(float4((*(tint_symbol))[0]).ywxz[0]);
+  float const a = fabs((*(tint_symbol))[0].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_fn.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_fn.wgsl.expected.msl
index 8a08412..8b894df 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_fn.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_fn.wgsl.expected.msl
@@ -13,9 +13,9 @@
 kernel void f(const constant float4x4* tint_symbol [[buffer(0)]]) {
   a(*(tint_symbol));
   b((*(tint_symbol))[1]);
-  b(float4((*(tint_symbol))[1]).ywxz);
+  b((*(tint_symbol))[1].ywxz);
   c((*(tint_symbol))[1][0]);
-  c(float4((*(tint_symbol))[1]).ywxz[0]);
+  c((*(tint_symbol))[1].ywxz[0]);
   return;
 }
 
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_private.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_private.wgsl.expected.msl
index 1230ff9..85112c6 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_private.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_private.wgsl.expected.msl
@@ -5,7 +5,7 @@
   thread float4x4 tint_symbol = float4x4(0.0f);
   tint_symbol = *(tint_symbol_1);
   tint_symbol[1] = (*(tint_symbol_1))[0];
-  tint_symbol[1] = float4((*(tint_symbol_1))[0]).ywxz;
+  tint_symbol[1] = (*(tint_symbol_1))[0].ywxz;
   tint_symbol[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_storage.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_storage.wgsl.expected.msl
index c3e6062..0556aa1 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_storage.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_storage.wgsl.expected.msl
@@ -4,7 +4,7 @@
 kernel void f(device float4x4* tint_symbol [[buffer(1)]], const constant float4x4* tint_symbol_1 [[buffer(0)]]) {
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
   return;
 }
diff --git a/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_workgroup.wgsl.expected.msl b/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_workgroup.wgsl.expected.msl
index 172975e..2fdf697 100644
--- a/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_workgroup.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/std140/unnested/mat4x4_f32/to_workgroup.wgsl.expected.msl
@@ -12,7 +12,7 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   *(tint_symbol) = *(tint_symbol_1);
   (*(tint_symbol))[1] = (*(tint_symbol_1))[0];
-  (*(tint_symbol))[1] = float4((*(tint_symbol_1))[0]).ywxz;
+  (*(tint_symbol))[1] = (*(tint_symbol_1))[0].ywxz;
   (*(tint_symbol))[0][1] = (*(tint_symbol_1))[1][0];
 }
 
diff --git a/test/tint/buffer/uniform/types/mat2x3_f16.wgsl.expected.msl b/test/tint/buffer/uniform/types/mat2x3_f16.wgsl.expected.msl
index 58a4bff..655eaae 100644
--- a/test/tint/buffer/uniform/types/mat2x3_f16.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/mat2x3_f16.wgsl.expected.msl
@@ -1,8 +1,34 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(const constant half2x3* tint_symbol_1 [[buffer(0)]]) {
-  half2x3 const x = *(tint_symbol_1);
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 2> in) {
+  half2x3 result = half2x3(0.0h);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void tint_symbol(const constant tint_array<tint_packed_vec3_f16_array_element, 2>* tint_symbol_1 [[buffer(0)]]) {
+  half2x3 const x = tint_unpack_vec3_in_composite(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/mat2x3_f32.wgsl.expected.msl b/test/tint/buffer/uniform/types/mat2x3_f32.wgsl.expected.msl
index 1c226a8..3835123 100644
--- a/test/tint/buffer/uniform/types/mat2x3_f32.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/mat2x3_f32.wgsl.expected.msl
@@ -1,8 +1,34 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(const constant float2x3* tint_symbol_1 [[buffer(0)]]) {
-  float2x3 const x = *(tint_symbol_1);
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
+  float2x3 result = float2x3(0.0f);
+  for(uint i = 0u; (i < 2u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void tint_symbol(const constant tint_array<tint_packed_vec3_f32_array_element, 2>* tint_symbol_1 [[buffer(0)]]) {
+  float2x3 const x = tint_unpack_vec3_in_composite(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/mat3x3_f16.wgsl.expected.msl b/test/tint/buffer/uniform/types/mat3x3_f16.wgsl.expected.msl
index 060a4ff..d5f2446 100644
--- a/test/tint/buffer/uniform/types/mat3x3_f16.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/mat3x3_f16.wgsl.expected.msl
@@ -1,8 +1,34 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(const constant half3x3* tint_symbol_1 [[buffer(0)]]) {
-  half3x3 const x = *(tint_symbol_1);
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void tint_symbol(const constant tint_array<tint_packed_vec3_f16_array_element, 3>* tint_symbol_1 [[buffer(0)]]) {
+  half3x3 const x = tint_unpack_vec3_in_composite(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/mat3x3_f32.wgsl.expected.msl b/test/tint/buffer/uniform/types/mat3x3_f32.wgsl.expected.msl
index 328708c..c335d01 100644
--- a/test/tint/buffer/uniform/types/mat3x3_f32.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/mat3x3_f32.wgsl.expected.msl
@@ -1,8 +1,34 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(const constant float3x3* tint_symbol_1 [[buffer(0)]]) {
-  float3x3 const x = *(tint_symbol_1);
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void tint_symbol(const constant tint_array<tint_packed_vec3_f32_array_element, 3>* tint_symbol_1 [[buffer(0)]]) {
+  float3x3 const x = tint_unpack_vec3_in_composite(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/mat4x3_f16.wgsl.expected.msl b/test/tint/buffer/uniform/types/mat4x3_f16.wgsl.expected.msl
index 199ceee..a89a59d 100644
--- a/test/tint/buffer/uniform/types/mat4x3_f16.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/mat4x3_f16.wgsl.expected.msl
@@ -1,8 +1,34 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(const constant half4x3* tint_symbol_1 [[buffer(0)]]) {
-  half4x3 const x = *(tint_symbol_1);
+
+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_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void tint_symbol(const constant tint_array<tint_packed_vec3_f16_array_element, 4>* tint_symbol_1 [[buffer(0)]]) {
+  half4x3 const x = tint_unpack_vec3_in_composite(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/mat4x3_f32.wgsl.expected.msl b/test/tint/buffer/uniform/types/mat4x3_f32.wgsl.expected.msl
index 482db1c..71e4d24 100644
--- a/test/tint/buffer/uniform/types/mat4x3_f32.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/mat4x3_f32.wgsl.expected.msl
@@ -1,8 +1,34 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(const constant float4x3* tint_symbol_1 [[buffer(0)]]) {
-  float4x3 const x = *(tint_symbol_1);
+
+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_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+kernel void tint_symbol(const constant tint_array<tint_packed_vec3_f32_array_element, 4>* tint_symbol_1 [[buffer(0)]]) {
+  float4x3 const x = tint_unpack_vec3_in_composite(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/struct_f16.wgsl.expected.msl b/test/tint/buffer/uniform/types/struct_f16.wgsl.expected.msl
index fd9b0f2..e232a99 100644
--- a/test/tint/buffer/uniform/types/struct_f16.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/struct_f16.wgsl.expected.msl
@@ -14,7 +14,7 @@
     T elements[N];
 };
 
-struct Inner {
+struct Inner_tint_packed_vec3 {
   /* 0x0000 */ half scalar_f16;
   /* 0x0002 */ tint_array<int8_t, 6> tint_pad;
   /* 0x0008 */ packed_half3 vec3_f16;
@@ -22,12 +22,36 @@
   /* 0x0010 */ half2x4 mat2x4_f16;
 };
 
-struct S {
-  /* 0x0000 */ Inner inner;
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ Inner_tint_packed_vec3 inner;
 };
 
-kernel void tint_symbol(const constant S* tint_symbol_1 [[buffer(0)]]) {
-  S const x = *(tint_symbol_1);
+struct Inner {
+  half scalar_f16;
+  half3 vec3_f16;
+  half2x4 mat2x4_f16;
+};
+
+Inner tint_unpack_vec3_in_composite(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.scalar_f16 = in.scalar_f16;
+  result.vec3_f16 = half3(in.vec3_f16);
+  result.mat2x4_f16 = in.mat2x4_f16;
+  return result;
+}
+
+struct S {
+  Inner inner;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.inner = tint_unpack_vec3_in_composite(in.inner);
+  return result;
+}
+
+kernel void tint_symbol(const constant S_tint_packed_vec3* tint_symbol_1 [[buffer(0)]]) {
+  S const x = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/struct_f32.wgsl.expected.msl b/test/tint/buffer/uniform/types/struct_f32.wgsl.expected.msl
index ae03b60..fa127ff 100644
--- a/test/tint/buffer/uniform/types/struct_f32.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/struct_f32.wgsl.expected.msl
@@ -14,7 +14,7 @@
     T elements[N];
 };
 
-struct Inner {
+struct Inner_tint_packed_vec3 {
   /* 0x0000 */ float scalar_f32;
   /* 0x0004 */ tint_array<int8_t, 12> tint_pad;
   /* 0x0010 */ packed_float3 vec3_f32;
@@ -22,12 +22,36 @@
   /* 0x0020 */ float2x4 mat2x4_f32;
 };
 
-struct S {
-  /* 0x0000 */ Inner inner;
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ Inner_tint_packed_vec3 inner;
 };
 
-kernel void tint_symbol(const constant S* tint_symbol_1 [[buffer(0)]]) {
-  S const x = *(tint_symbol_1);
+struct Inner {
+  float scalar_f32;
+  float3 vec3_f32;
+  float2x4 mat2x4_f32;
+};
+
+Inner tint_unpack_vec3_in_composite(Inner_tint_packed_vec3 in) {
+  Inner result = {};
+  result.scalar_f32 = in.scalar_f32;
+  result.vec3_f32 = float3(in.vec3_f32);
+  result.mat2x4_f32 = in.mat2x4_f32;
+  return result;
+}
+
+struct S {
+  Inner inner;
+};
+
+S tint_unpack_vec3_in_composite_1(S_tint_packed_vec3 in) {
+  S result = {};
+  result.inner = tint_unpack_vec3_in_composite(in.inner);
+  return result;
+}
+
+kernel void tint_symbol(const constant S_tint_packed_vec3* tint_symbol_1 [[buffer(0)]]) {
+  S const x = tint_unpack_vec3_in_composite_1(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/vec3_f16.wgsl.expected.msl b/test/tint/buffer/uniform/types/vec3_f16.wgsl.expected.msl
index ce6a7ba6..8d23baa 100644
--- a/test/tint/buffer/uniform/types/vec3_f16.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/vec3_f16.wgsl.expected.msl
@@ -1,8 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(const constant half3* tint_symbol_1 [[buffer(0)]]) {
-  half3 const x = *(tint_symbol_1);
+kernel void tint_symbol(const constant packed_half3* tint_symbol_1 [[buffer(0)]]) {
+  half3 const x = half3(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/vec3_f32.wgsl.expected.msl b/test/tint/buffer/uniform/types/vec3_f32.wgsl.expected.msl
index b354a26..e186a3c 100644
--- a/test/tint/buffer/uniform/types/vec3_f32.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/vec3_f32.wgsl.expected.msl
@@ -1,8 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(const constant float3* tint_symbol_1 [[buffer(0)]]) {
-  float3 const x = *(tint_symbol_1);
+kernel void tint_symbol(const constant packed_float3* tint_symbol_1 [[buffer(0)]]) {
+  float3 const x = float3(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/vec3_i32.wgsl.expected.msl b/test/tint/buffer/uniform/types/vec3_i32.wgsl.expected.msl
index e014902..78a8027 100644
--- a/test/tint/buffer/uniform/types/vec3_i32.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/vec3_i32.wgsl.expected.msl
@@ -1,8 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(const constant int3* tint_symbol_1 [[buffer(0)]]) {
-  int3 const x = *(tint_symbol_1);
+kernel void tint_symbol(const constant packed_int3* tint_symbol_1 [[buffer(0)]]) {
+  int3 const x = int3(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/buffer/uniform/types/vec3_u32.wgsl.expected.msl b/test/tint/buffer/uniform/types/vec3_u32.wgsl.expected.msl
index 407c0e7..91f8ba9 100644
--- a/test/tint/buffer/uniform/types/vec3_u32.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/types/vec3_u32.wgsl.expected.msl
@@ -1,8 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-kernel void tint_symbol(const constant uint3* tint_symbol_1 [[buffer(0)]]) {
-  uint3 const x = *(tint_symbol_1);
+kernel void tint_symbol(const constant packed_uint3* tint_symbol_1 [[buffer(0)]]) {
+  uint3 const x = uint3(*(tint_symbol_1));
   return;
 }
 
diff --git a/test/tint/bug/chromium/1273230.wgsl.expected.msl b/test/tint/bug/chromium/1273230.wgsl.expected.msl
index 2312e14..03a998f 100644
--- a/test/tint/bug/chromium/1273230.wgsl.expected.msl
+++ b/test/tint/bug/chromium/1273230.wgsl.expected.msl
@@ -14,10 +14,7 @@
     T elements[N];
 };
 
-void marg8uintin() {
-}
-
-struct Uniforms {
+struct Uniforms_tint_packed_vec3 {
   /* 0x0000 */ uint numTriangles;
   /* 0x0004 */ uint gridSize;
   /* 0x0008 */ uint puuuuuuuuuuuuuuuuad1;
@@ -28,6 +25,18 @@
   /* 0x002c */ tint_array<int8_t, 4> tint_pad_1;
 };
 
+void marg8uintin() {
+}
+
+struct Uniforms {
+  uint numTriangles;
+  uint gridSize;
+  uint puuuuuuuuuuuuuuuuad1;
+  uint pad2;
+  float3 bbMin;
+  float3 bbMax;
+};
+
 struct Dbg {
   /* 0x0000 */ atomic_uint offsetCounter;
   /* 0x0004 */ uint pad0;
@@ -63,7 +72,7 @@
   /* 0x0000 */ tint_array<atomic_int, 1> values;
 };
 
-float3 toVoxelPos(float3 position, const constant Uniforms* const tint_symbol) {
+float3 toVoxelPos(float3 position, const constant Uniforms_tint_packed_vec3* const tint_symbol) {
   float3 bbMin = float3((*(tint_symbol)).bbMin[0], (*(tint_symbol)).bbMin[1], (*(tint_symbol)).bbMin[2]);
   float3 bbMax = float3((*(tint_symbol)).bbMax[0], (*(tint_symbol)).bbMax[1], (*(tint_symbol)).bbMax[2]);
   float3 bbSize = (bbMin - bbMin);
@@ -100,7 +109,7 @@
   return position;
 }
 
-void doIgnore(const constant Uniforms* const tint_symbol_2, device Dbg* const tint_symbol_3, device AU32s* const tint_symbol_4, device U32s* const tint_symbol_5, device F32s* const tint_symbol_6, device AI32s* const tint_symbol_7) {
+void doIgnore(const constant Uniforms_tint_packed_vec3* const tint_symbol_2, device Dbg* const tint_symbol_3, device AU32s* const tint_symbol_4, device U32s* const tint_symbol_5, device F32s* const tint_symbol_6, device AI32s* const tint_symbol_7) {
   uint g43 = (*(tint_symbol_2)).numTriangles;
   uint kj6 = (*(tint_symbol_3)).value1;
   uint b53 = atomic_load_explicit(&((*(tint_symbol_4)).values[0]), memory_order_relaxed);
@@ -109,7 +118,7 @@
   int g55 = atomic_load_explicit(&((*(tint_symbol_7)).values[0]), memory_order_relaxed);
 }
 
-void main_count_inner(uint3 GlobalInvocationID, const constant Uniforms* const tint_symbol_8, device Dbg* const tint_symbol_9, device AU32s* const tint_symbol_10, device U32s* const tint_symbol_11, device F32s* const tint_symbol_12, device AI32s* const tint_symbol_13) {
+void main_count_inner(uint3 GlobalInvocationID, const constant Uniforms_tint_packed_vec3* const tint_symbol_8, device Dbg* const tint_symbol_9, device AU32s* const tint_symbol_10, device U32s* const tint_symbol_11, device F32s* const tint_symbol_12, device AI32s* const tint_symbol_13) {
   uint triangleIndex = GlobalInvocationID[0];
   if ((triangleIndex >= (*(tint_symbol_8)).numTriangles)) {
     return;
@@ -127,7 +136,7 @@
   int triangleOffset = atomic_fetch_add_explicit(&((*(tint_symbol_13)).values[i1]), 1, memory_order_relaxed);
 }
 
-kernel void main_count(const constant Uniforms* tint_symbol_14 [[buffer(0)]], device Dbg* tint_symbol_15 [[buffer(1)]], device AU32s* tint_symbol_16 [[buffer(2)]], device U32s* tint_symbol_17 [[buffer(3)]], device F32s* tint_symbol_18 [[buffer(4)]], device AI32s* tint_symbol_19 [[buffer(5)]], uint3 GlobalInvocationID [[thread_position_in_grid]]) {
+kernel void main_count(const constant Uniforms_tint_packed_vec3* tint_symbol_14 [[buffer(0)]], device Dbg* tint_symbol_15 [[buffer(1)]], device AU32s* tint_symbol_16 [[buffer(2)]], device U32s* tint_symbol_17 [[buffer(3)]], device F32s* tint_symbol_18 [[buffer(4)]], device AI32s* tint_symbol_19 [[buffer(5)]], uint3 GlobalInvocationID [[thread_position_in_grid]]) {
   main_count_inner(GlobalInvocationID, tint_symbol_14, tint_symbol_15, tint_symbol_16, tint_symbol_17, tint_symbol_18, tint_symbol_19);
   return;
 }
diff --git a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.msl b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.msl
index 20479d9..b831db0 100644
--- a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.msl
+++ b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.msl
@@ -10,7 +10,7 @@
 };
 
 float4 tint_symbol_inner(float2 vUV, texture2d<float, access::sample> tint_symbol_4, sampler tint_symbol_5) {
-  float3 const random = float4(tint_symbol_4.sample(tint_symbol_5, vUV)).rgb;
+  float3 const random = tint_symbol_4.sample(tint_symbol_5, vUV).rgb;
   int i = 0;
   while (true) {
     if ((i < 1)) {
diff --git a/test/tint/bug/fxc/indexed_assign_to_array_in_struct/1206.wgsl.expected.msl b/test/tint/bug/fxc/indexed_assign_to_array_in_struct/1206.wgsl.expected.msl
index c63e9f1..b1e90cf 100644
--- a/test/tint/bug/fxc/indexed_assign_to_array_in_struct/1206.wgsl.expected.msl
+++ b/test/tint/bug/fxc/indexed_assign_to_array_in_struct/1206.wgsl.expected.msl
@@ -14,25 +14,58 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct Particle_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f32_array_element, 8> position;
+  /* 0x0080 */ float lifetime;
+  /* 0x0084 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0090 */ float4 color;
+  /* 0x00a0 */ packed_float3 velocity;
+  /* 0x00ac */ tint_array<int8_t, 4> tint_pad_2;
+};
+
+struct Particles_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<Particle_tint_packed_vec3, 1> p;
+};
+
+tint_array<float3, 8> tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 8> in) {
+  tint_array<float3, 8> result = {};
+  for(uint i = 0u; (i < 8u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct Particle {
+  tint_array<float3, 8> position;
+  float lifetime;
+  float4 color;
+  float3 velocity;
+};
+
+Particle tint_unpack_vec3_in_composite_1(Particle_tint_packed_vec3 in) {
+  Particle result = {};
+  result.position = tint_unpack_vec3_in_composite(in.position);
+  result.lifetime = in.lifetime;
+  result.color = in.color;
+  result.velocity = float3(in.velocity);
+  return result;
+}
+
 struct Simulation {
   /* 0x0000 */ uint i;
 };
 
-struct Particle {
-  /* 0x0000 */ tint_array<float3, 8> position;
-  /* 0x0080 */ float lifetime;
-  /* 0x0084 */ tint_array<int8_t, 12> tint_pad;
-  /* 0x0090 */ float4 color;
-  /* 0x00a0 */ packed_float3 velocity;
-  /* 0x00ac */ tint_array<int8_t, 4> tint_pad_1;
-};
-
 struct Particles {
-  /* 0x0000 */ tint_array<Particle, 1> p;
+  tint_array<Particle, 1> p;
 };
 
-kernel void tint_symbol(const device Particles* tint_symbol_1 [[buffer(1)]], const constant Simulation* tint_symbol_2 [[buffer(0)]]) {
-  Particle particle = (*(tint_symbol_1)).p[0];
+kernel void tint_symbol(const device Particles_tint_packed_vec3* tint_symbol_1 [[buffer(1)]], const constant Simulation* tint_symbol_2 [[buffer(0)]]) {
+  Particle particle = tint_unpack_vec3_in_composite_1((*(tint_symbol_1)).p[0]);
   particle.position[(*(tint_symbol_2)).i] = particle.position[(*(tint_symbol_2)).i];
   return;
 }
diff --git a/test/tint/bug/tint/1113.wgsl.expected.msl b/test/tint/bug/tint/1113.wgsl.expected.msl
index cd110c1..e46e361 100644
--- a/test/tint/bug/tint/1113.wgsl.expected.msl
+++ b/test/tint/bug/tint/1113.wgsl.expected.msl
@@ -14,7 +14,7 @@
     T elements[N];
 };
 
-struct Uniforms {
+struct Uniforms_tint_packed_vec3 {
   /* 0x0000 */ uint numTriangles;
   /* 0x0004 */ uint gridSize;
   /* 0x0008 */ uint pad1;
@@ -25,6 +25,15 @@
   /* 0x002c */ tint_array<int8_t, 4> tint_pad_1;
 };
 
+struct Uniforms {
+  uint numTriangles;
+  uint gridSize;
+  uint pad1;
+  uint pad2;
+  float3 bbMin;
+  float3 bbMax;
+};
+
 struct Dbg {
   /* 0x0000 */ atomic_uint offsetCounter;
   /* 0x0004 */ uint pad0;
@@ -60,7 +69,7 @@
   /* 0x0000 */ tint_array<atomic_int, 1> values;
 };
 
-float3 toVoxelPos(float3 position, const constant Uniforms* const tint_symbol_1) {
+float3 toVoxelPos(float3 position, const constant Uniforms_tint_packed_vec3* const tint_symbol_1) {
   float3 bbMin = float3((*(tint_symbol_1)).bbMin[0], (*(tint_symbol_1)).bbMin[1], (*(tint_symbol_1)).bbMin[2]);
   float3 bbMax = float3((*(tint_symbol_1)).bbMax[0], (*(tint_symbol_1)).bbMax[1], (*(tint_symbol_1)).bbMax[2]);
   float3 bbSize = (bbMax - bbMin);
@@ -97,7 +106,7 @@
   return position;
 }
 
-void doIgnore(const constant Uniforms* const tint_symbol_3, device Dbg* const tint_symbol_4, device AU32s* const tint_symbol_5, device U32s* const tint_symbol_6, device F32s* const tint_symbol_7, device AI32s* const tint_symbol_8) {
+void doIgnore(const constant Uniforms_tint_packed_vec3* const tint_symbol_3, device Dbg* const tint_symbol_4, device AU32s* const tint_symbol_5, device U32s* const tint_symbol_6, device F32s* const tint_symbol_7, device AI32s* const tint_symbol_8) {
   uint g42 = (*(tint_symbol_3)).numTriangles;
   uint kj6 = (*(tint_symbol_4)).value1;
   uint b53 = atomic_load_explicit(&((*(tint_symbol_5)).values[0]), memory_order_relaxed);
@@ -106,7 +115,7 @@
   int g55 = atomic_load_explicit(&((*(tint_symbol_8)).values[0]), memory_order_relaxed);
 }
 
-void main_count_inner(uint3 GlobalInvocationID, const constant Uniforms* const tint_symbol_9, device Dbg* const tint_symbol_10, device AU32s* const tint_symbol_11, device U32s* const tint_symbol_12, device F32s* const tint_symbol_13, device AI32s* const tint_symbol_14) {
+void main_count_inner(uint3 GlobalInvocationID, const constant Uniforms_tint_packed_vec3* const tint_symbol_9, device Dbg* const tint_symbol_10, device AU32s* const tint_symbol_11, device U32s* const tint_symbol_12, device F32s* const tint_symbol_13, device AI32s* const tint_symbol_14) {
   uint triangleIndex = GlobalInvocationID[0];
   if ((triangleIndex >= (*(tint_symbol_9)).numTriangles)) {
     return;
@@ -130,12 +139,12 @@
   }
 }
 
-kernel void main_count(const constant Uniforms* tint_symbol_15 [[buffer(0)]], device Dbg* tint_symbol_16 [[buffer(1)]], device AU32s* tint_symbol_17 [[buffer(2)]], device U32s* tint_symbol_18 [[buffer(3)]], device F32s* tint_symbol_19 [[buffer(4)]], device AI32s* tint_symbol_20 [[buffer(5)]], uint3 GlobalInvocationID [[thread_position_in_grid]]) {
+kernel void main_count(const constant Uniforms_tint_packed_vec3* tint_symbol_15 [[buffer(0)]], device Dbg* tint_symbol_16 [[buffer(1)]], device AU32s* tint_symbol_17 [[buffer(2)]], device U32s* tint_symbol_18 [[buffer(3)]], device F32s* tint_symbol_19 [[buffer(4)]], device AI32s* tint_symbol_20 [[buffer(5)]], uint3 GlobalInvocationID [[thread_position_in_grid]]) {
   main_count_inner(GlobalInvocationID, tint_symbol_15, tint_symbol_16, tint_symbol_17, tint_symbol_18, tint_symbol_19, tint_symbol_20);
   return;
 }
 
-void main_create_lut_inner(uint3 GlobalInvocationID, const constant Uniforms* const tint_symbol_21, device Dbg* const tint_symbol_22, device AU32s* const tint_symbol_23, device U32s* const tint_symbol_24, device F32s* const tint_symbol_25, device AI32s* const tint_symbol_26) {
+void main_create_lut_inner(uint3 GlobalInvocationID, const constant Uniforms_tint_packed_vec3* const tint_symbol_21, device Dbg* const tint_symbol_22, device AU32s* const tint_symbol_23, device U32s* const tint_symbol_24, device F32s* const tint_symbol_25, device AI32s* const tint_symbol_26) {
   uint voxelIndex = GlobalInvocationID[0];
   doIgnore(tint_symbol_21, tint_symbol_22, tint_symbol_23, tint_symbol_24, tint_symbol_25, tint_symbol_26);
   uint maxVoxels = (((*(tint_symbol_21)).gridSize * (*(tint_symbol_21)).gridSize) * (*(tint_symbol_21)).gridSize);
@@ -151,12 +160,12 @@
   atomic_store_explicit(&((*(tint_symbol_26)).values[voxelIndex]), offset, memory_order_relaxed);
 }
 
-kernel void main_create_lut(const constant Uniforms* tint_symbol_27 [[buffer(0)]], device Dbg* tint_symbol_28 [[buffer(1)]], device AU32s* tint_symbol_29 [[buffer(2)]], device U32s* tint_symbol_30 [[buffer(3)]], device F32s* tint_symbol_31 [[buffer(4)]], device AI32s* tint_symbol_32 [[buffer(5)]], uint3 GlobalInvocationID [[thread_position_in_grid]]) {
+kernel void main_create_lut(const constant Uniforms_tint_packed_vec3* tint_symbol_27 [[buffer(0)]], device Dbg* tint_symbol_28 [[buffer(1)]], device AU32s* tint_symbol_29 [[buffer(2)]], device U32s* tint_symbol_30 [[buffer(3)]], device F32s* tint_symbol_31 [[buffer(4)]], device AI32s* tint_symbol_32 [[buffer(5)]], uint3 GlobalInvocationID [[thread_position_in_grid]]) {
   main_create_lut_inner(GlobalInvocationID, tint_symbol_27, tint_symbol_28, tint_symbol_29, tint_symbol_30, tint_symbol_31, tint_symbol_32);
   return;
 }
 
-void main_sort_triangles_inner(uint3 GlobalInvocationID, const constant Uniforms* const tint_symbol_33, device Dbg* const tint_symbol_34, device AU32s* const tint_symbol_35, device U32s* const tint_symbol_36, device F32s* const tint_symbol_37, device AI32s* const tint_symbol_38) {
+void main_sort_triangles_inner(uint3 GlobalInvocationID, const constant Uniforms_tint_packed_vec3* const tint_symbol_33, device Dbg* const tint_symbol_34, device AU32s* const tint_symbol_35, device U32s* const tint_symbol_36, device F32s* const tint_symbol_37, device AI32s* const tint_symbol_38) {
   uint triangleIndex = GlobalInvocationID[0];
   doIgnore(tint_symbol_33, tint_symbol_34, tint_symbol_35, tint_symbol_36, tint_symbol_37, tint_symbol_38);
   if ((triangleIndex >= (*(tint_symbol_33)).numTriangles)) {
@@ -174,7 +183,7 @@
   int triangleOffset = atomic_fetch_add_explicit(&((*(tint_symbol_38)).values[voxelIndex]), 1, memory_order_relaxed);
 }
 
-kernel void main_sort_triangles(const constant Uniforms* tint_symbol_39 [[buffer(0)]], device Dbg* tint_symbol_40 [[buffer(1)]], device AU32s* tint_symbol_41 [[buffer(2)]], device U32s* tint_symbol_42 [[buffer(3)]], device F32s* tint_symbol_43 [[buffer(4)]], device AI32s* tint_symbol_44 [[buffer(5)]], uint3 GlobalInvocationID [[thread_position_in_grid]]) {
+kernel void main_sort_triangles(const constant Uniforms_tint_packed_vec3* tint_symbol_39 [[buffer(0)]], device Dbg* tint_symbol_40 [[buffer(1)]], device AU32s* tint_symbol_41 [[buffer(2)]], device U32s* tint_symbol_42 [[buffer(3)]], device F32s* tint_symbol_43 [[buffer(4)]], device AI32s* tint_symbol_44 [[buffer(5)]], uint3 GlobalInvocationID [[thread_position_in_grid]]) {
   main_sort_triangles_inner(GlobalInvocationID, tint_symbol_39, tint_symbol_40, tint_symbol_41, tint_symbol_42, tint_symbol_43, tint_symbol_44);
   return;
 }
diff --git a/test/tint/bug/tint/1118.wgsl.expected.msl b/test/tint/bug/tint/1118.wgsl.expected.msl
index 9dc50df..2b4c8d4 100644
--- a/test/tint/bug/tint/1118.wgsl.expected.msl
+++ b/test/tint/bug/tint/1118.wgsl.expected.msl
@@ -1,11 +1,7 @@
 #include <metal_stdlib>
 
 using namespace metal;
-struct Scene {
-  /* 0x0000 */ float4 vEyePosition;
-};
-
-struct Material {
+struct Material_tint_packed_vec3 {
   /* 0x0000 */ float4 vDiffuseColor;
   /* 0x0010 */ packed_float3 vAmbientColor;
   /* 0x001c */ float placeholder;
@@ -13,11 +9,23 @@
   /* 0x002c */ float placeholder2;
 };
 
+struct Scene {
+  /* 0x0000 */ float4 vEyePosition;
+};
+
+struct Material {
+  float4 vDiffuseColor;
+  float3 vAmbientColor;
+  float placeholder;
+  float3 vEmissiveColor;
+  float placeholder2;
+};
+
 struct Mesh {
   /* 0x0000 */ float visibility;
 };
 
-void main_1(thread float* const tint_symbol_5, thread bool* const tint_symbol_6, thread float* const tint_symbol_7, const constant Scene* const tint_symbol_8, const constant Material* const tint_symbol_9, const constant Mesh* const tint_symbol_10, thread float4* const tint_symbol_11) {
+void main_1(thread float* const tint_symbol_5, thread bool* const tint_symbol_6, thread float* const tint_symbol_7, const constant Scene* const tint_symbol_8, const constant Material_tint_packed_vec3* const tint_symbol_9, const constant Mesh* const tint_symbol_10, thread float4* const tint_symbol_11) {
   float3 viewDirectionW = 0.0f;
   float4 baseColor = 0.0f;
   float3 diffuseColor = 0.0f;
@@ -106,7 +114,7 @@
   float4 glFragColor_1 [[color(0)]];
 };
 
-main_out tint_symbol_inner(float fClipDistance3_param, float fClipDistance4_param, thread float* const tint_symbol_12, thread float* const tint_symbol_13, thread bool* const tint_symbol_14, const constant Scene* const tint_symbol_15, const constant Material* const tint_symbol_16, const constant Mesh* const tint_symbol_17, thread float4* const tint_symbol_18) {
+main_out tint_symbol_inner(float fClipDistance3_param, float fClipDistance4_param, thread float* const tint_symbol_12, thread float* const tint_symbol_13, thread bool* const tint_symbol_14, const constant Scene* const tint_symbol_15, const constant Material_tint_packed_vec3* const tint_symbol_16, const constant Mesh* const tint_symbol_17, thread float4* const tint_symbol_18) {
   *(tint_symbol_12) = fClipDistance3_param;
   *(tint_symbol_13) = fClipDistance4_param;
   main_1(tint_symbol_12, tint_symbol_14, tint_symbol_13, tint_symbol_15, tint_symbol_16, tint_symbol_17, tint_symbol_18);
@@ -114,7 +122,7 @@
   return tint_symbol_4;
 }
 
-fragment tint_symbol_3 tint_symbol(const constant Scene* tint_symbol_22 [[buffer(0)]], const constant Material* tint_symbol_23 [[buffer(1)]], const constant Mesh* tint_symbol_24 [[buffer(2)]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+fragment tint_symbol_3 tint_symbol(const constant Scene* tint_symbol_22 [[buffer(0)]], const constant Material_tint_packed_vec3* tint_symbol_23 [[buffer(1)]], const constant Mesh* tint_symbol_24 [[buffer(2)]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
   thread float tint_symbol_19 = 0.0f;
   thread float tint_symbol_20 = 0.0f;
   thread bool tint_symbol_21 = false;
diff --git a/test/tint/bug/tint/1121.wgsl.expected.msl b/test/tint/bug/tint/1121.wgsl.expected.msl
index 756cc43..64aeee3 100644
--- a/test/tint/bug/tint/1121.wgsl.expected.msl
+++ b/test/tint/bug/tint/1121.wgsl.expected.msl
@@ -14,14 +14,24 @@
     T elements[N];
 };
 
-struct LightData {
+struct LightData_tint_packed_vec3 {
   /* 0x0000 */ float4 position;
   /* 0x0010 */ packed_float3 color;
   /* 0x001c */ float radius;
 };
 
+struct LightsBuffer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<LightData_tint_packed_vec3, 1> lights;
+};
+
+struct LightData {
+  float4 position;
+  float3 color;
+  float radius;
+};
+
 struct LightsBuffer {
-  /* 0x0000 */ tint_array<LightData, 1> lights;
+  tint_array<LightData, 1> lights;
 };
 
 struct TileLightIdData {
@@ -50,7 +60,7 @@
   /* 0x00a0 */ float4 fullScreenSize;
 };
 
-void tint_symbol_inner(uint3 GlobalInvocationID, const constant Config* const tint_symbol_1, device LightsBuffer* const tint_symbol_2, const constant Uniforms* const tint_symbol_3, device Tiles* const tint_symbol_4) {
+void tint_symbol_inner(uint3 GlobalInvocationID, const constant Config* const tint_symbol_1, device LightsBuffer_tint_packed_vec3* const tint_symbol_2, const constant Uniforms* const tint_symbol_3, device Tiles* const tint_symbol_4) {
   uint index = GlobalInvocationID[0];
   if ((index >= (*(tint_symbol_1)).numLights)) {
     return;
@@ -77,8 +87,8 @@
   for(int y = 0; (y < TILE_COUNT_Y); y = as_type<int>((as_type<uint>(y) + as_type<uint>(1)))) {
     for(int x = 0; (x < TILE_COUNT_X); x = as_type<int>((as_type<uint>(x) + as_type<uint>(1)))) {
       int2 tilePixel0Idx = int2(as_type<int>((as_type<uint>(x) * as_type<uint>(TILE_SIZE))), as_type<int>((as_type<uint>(y) * as_type<uint>(TILE_SIZE))));
-      float2 floorCoord = (((2.0f * float2(tilePixel0Idx)) / float4((*(tint_symbol_3)).fullScreenSize).xy) - float2(1.0f));
-      float2 ceilCoord = (((2.0f * float2(as_type<int2>((as_type<uint2>(tilePixel0Idx) + as_type<uint2>(int2(TILE_SIZE)))))) / float4((*(tint_symbol_3)).fullScreenSize).xy) - float2(1.0f));
+      float2 floorCoord = (((2.0f * float2(tilePixel0Idx)) / (*(tint_symbol_3)).fullScreenSize.xy) - float2(1.0f));
+      float2 ceilCoord = (((2.0f * float2(as_type<int2>((as_type<uint2>(tilePixel0Idx) + as_type<uint2>(int2(TILE_SIZE)))))) / (*(tint_symbol_3)).fullScreenSize.xy) - float2(1.0f));
       float2 viewFloorCoord = float2((((-(viewNear) * floorCoord[0]) - (M[2][0] * viewNear)) / M[0][0]), (((-(viewNear) * floorCoord[1]) - (M[2][1] * viewNear)) / M[1][1]));
       float2 viewCeilCoord = float2((((-(viewNear) * ceilCoord[0]) - (M[2][0] * viewNear)) / M[0][0]), (((-(viewNear) * ceilCoord[1]) - (M[2][1] * viewNear)) / M[1][1]));
       frustumPlanes[0] = float4(1.0f, 0.0f, (-(viewFloorCoord[0]) / viewNear), 0.0f);
@@ -121,7 +131,7 @@
   }
 }
 
-kernel void tint_symbol(const constant Config* tint_symbol_5 [[buffer(0)]], device LightsBuffer* tint_symbol_6 [[buffer(2)]], const constant Uniforms* tint_symbol_7 [[buffer(1)]], device Tiles* tint_symbol_8 [[buffer(3)]], uint3 GlobalInvocationID [[thread_position_in_grid]]) {
+kernel void tint_symbol(const constant Config* tint_symbol_5 [[buffer(0)]], device LightsBuffer_tint_packed_vec3* tint_symbol_6 [[buffer(2)]], const constant Uniforms* tint_symbol_7 [[buffer(1)]], device Tiles* tint_symbol_8 [[buffer(3)]], uint3 GlobalInvocationID [[thread_position_in_grid]]) {
   tint_symbol_inner(GlobalInvocationID, tint_symbol_5, tint_symbol_6, tint_symbol_7, tint_symbol_8);
   return;
 }
diff --git a/test/tint/bug/tint/1520.spvasm.expected.msl b/test/tint/bug/tint/1520.spvasm.expected.msl
index 335a96b..472b6e8 100644
--- a/test/tint/bug/tint/1520.spvasm.expected.msl
+++ b/test/tint/bug/tint/1520.spvasm.expected.msl
@@ -14,20 +14,32 @@
     T elements[N];
 };
 
-struct UniformBuffer {
-  /* 0x0000 */ tint_array<int8_t, 16> tint_pad;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct UniformBuffer_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<int8_t, 16> tint_pad_1;
   /* 0x0010 */ float unknownInput_S1_c0;
-  /* 0x0014 */ tint_array<int8_t, 12> tint_pad_1;
+  /* 0x0014 */ tint_array<int8_t, 12> tint_pad_2;
   /* 0x0020 */ float4 ucolorRed_S1_c0;
   /* 0x0030 */ float4 ucolorGreen_S1_c0;
-  /* 0x0040 */ float3x3 umatrix_S1;
+  /* 0x0040 */ tint_array<tint_packed_vec3_f32_array_element, 3> umatrix_S1;
+};
+
+struct UniformBuffer {
+  float unknownInput_S1_c0;
+  float4 ucolorRed_S1_c0;
+  float4 ucolorGreen_S1_c0;
+  float3x3 umatrix_S1;
 };
 
 int4 tint_div(int4 lhs, int4 rhs) {
   return (lhs / select(rhs, int4(1), ((rhs == int4(0)) | ((lhs == int4((-2147483647 - 1))) & (rhs == int4(-1))))));
 }
 
-bool test_int_S1_c0_b(const constant UniformBuffer* const tint_symbol_6) {
+bool test_int_S1_c0_b(const constant UniformBuffer_tint_packed_vec3* const tint_symbol_6) {
   int unknown = 0;
   bool ok = false;
   int4 val = 0;
@@ -81,7 +93,7 @@
   return x_66;
 }
 
-void main_1(thread float4* const tint_symbol_7, const constant UniformBuffer* const tint_symbol_8, thread float4* const tint_symbol_9) {
+void main_1(thread float4* const tint_symbol_7, const constant UniformBuffer_tint_packed_vec3* const tint_symbol_8, thread float4* const tint_symbol_9) {
   float4 outputColor_S0 = 0.0f;
   float4 output_S1 = 0.0f;
   float x_8_unknown = 0.0f;
@@ -167,7 +179,7 @@
   float4 sk_FragColor_1 [[color(0)]];
 };
 
-main_out tint_symbol_inner(bool sk_Clockwise_param, float4 vcolor_S0_param, thread float4* const tint_symbol_11, const constant UniformBuffer* const tint_symbol_12, thread float4* const tint_symbol_13) {
+main_out tint_symbol_inner(bool sk_Clockwise_param, float4 vcolor_S0_param, thread float4* const tint_symbol_11, const constant UniformBuffer_tint_packed_vec3* const tint_symbol_12, thread float4* const tint_symbol_13) {
   thread bool tint_symbol_10 = false;
   tint_symbol_10 = sk_Clockwise_param;
   *(tint_symbol_11) = vcolor_S0_param;
@@ -176,7 +188,7 @@
   return tint_symbol_5;
 }
 
-fragment tint_symbol_3 tint_symbol(const constant UniformBuffer* tint_symbol_15 [[buffer(0)]], bool sk_Clockwise_param [[front_facing]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+fragment tint_symbol_3 tint_symbol(const constant UniformBuffer_tint_packed_vec3* tint_symbol_15 [[buffer(0)]], bool sk_Clockwise_param [[front_facing]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
   thread float4 tint_symbol_14 = 0.0f;
   thread float4 tint_symbol_16 = 0.0f;
   main_out const inner_result = tint_symbol_inner(sk_Clockwise_param, tint_symbol_1.vcolor_S0_param, &(tint_symbol_14), tint_symbol_15, &(tint_symbol_16));
diff --git a/test/tint/bug/tint/1534.wgsl.expected.msl b/test/tint/bug/tint/1534.wgsl.expected.msl
index 6f8a3de..ce8c000 100644
--- a/test/tint/bug/tint/1534.wgsl.expected.msl
+++ b/test/tint/bug/tint/1534.wgsl.expected.msl
@@ -18,16 +18,20 @@
 T tint_dot3(vec<T,3> a, vec<T,3> b) {
   return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
 }
-struct g {
+struct g_tint_packed_vec3 {
   /* 0x0000 */ packed_uint3 a;
   /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
+struct g {
+  uint3 a;
+};
+
 struct h {
   /* 0x0000 */ uint a;
 };
 
-kernel void tint_symbol(const constant g* tint_symbol_1 [[buffer(0)]], device h* tint_symbol_2 [[buffer(1)]]) {
+kernel void tint_symbol(const constant g_tint_packed_vec3* tint_symbol_1 [[buffer(0)]], device h* tint_symbol_2 [[buffer(1)]]) {
   uint const l = tint_dot3(uint3((*(tint_symbol_1)).a), uint3((*(tint_symbol_1)).a));
   (*(tint_symbol_2)).a = (*(tint_symbol_1)).a[0];
   return;
diff --git a/test/tint/bug/tint/1542.wgsl.expected.msl b/test/tint/bug/tint/1542.wgsl.expected.msl
index 7d8ffdd..94582f4 100644
--- a/test/tint/bug/tint/1542.wgsl.expected.msl
+++ b/test/tint/bug/tint/1542.wgsl.expected.msl
@@ -14,12 +14,16 @@
     T elements[N];
 };
 
-struct UniformBuffer {
+struct UniformBuffer_tint_packed_vec3 {
   /* 0x0000 */ packed_int3 d;
   /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-kernel void tint_symbol(const constant UniformBuffer* tint_symbol_1 [[buffer(0)]]) {
+struct UniformBuffer {
+  int3 d;
+};
+
+kernel void tint_symbol(const constant UniformBuffer_tint_packed_vec3* tint_symbol_1 [[buffer(0)]]) {
   int3 const temp = as_type<int3>((as_type<uint3>(int3((*(tint_symbol_1)).d)) << uint3(0u)));
   return;
 }
diff --git a/test/tint/bug/tint/1677.wgsl.expected.msl b/test/tint/bug/tint/1677.wgsl.expected.msl
index 580eba4..9d95b1e 100644
--- a/test/tint/bug/tint/1677.wgsl.expected.msl
+++ b/test/tint/bug/tint/1677.wgsl.expected.msl
@@ -14,16 +14,20 @@
     T elements[N];
 };
 
-struct Input {
+struct Input_tint_packed_vec3 {
   /* 0x0000 */ packed_int3 position;
   /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-void tint_symbol_inner(uint3 id, const device Input* const tint_symbol_1) {
+struct Input {
+  int3 position;
+};
+
+void tint_symbol_inner(uint3 id, const device Input_tint_packed_vec3* const tint_symbol_1) {
   int3 const pos = as_type<int3>((as_type<uint3>(int3((*(tint_symbol_1)).position)) - as_type<uint3>(int3(0))));
 }
 
-kernel void tint_symbol(const device Input* tint_symbol_2 [[buffer(0)]], uint3 id [[thread_position_in_grid]]) {
+kernel void tint_symbol(const device Input_tint_packed_vec3* tint_symbol_2 [[buffer(0)]], uint3 id [[thread_position_in_grid]]) {
   tint_symbol_inner(id, tint_symbol_2);
   return;
 }
diff --git a/test/tint/bug/tint/1739.wgsl.expected.msl b/test/tint/bug/tint/1739.wgsl.expected.msl
index e892cd9..cdd5da4 100644
--- a/test/tint/bug/tint/1739.wgsl.expected.msl
+++ b/test/tint/bug/tint/1739.wgsl.expected.msl
@@ -14,9 +14,10 @@
     T elements[N];
 };
 
-int2 tint_clamp(int2 e, int2 low, int2 high) {
-  return min(max(e, low), high);
-}
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
 
 struct GammaTransferParams {
   /* 0x0000 */ float G;
@@ -29,18 +30,52 @@
   /* 0x001c */ uint padding;
 };
 
-struct ExternalTextureParams {
+struct ExternalTextureParams_tint_packed_vec3 {
   /* 0x0000 */ uint numPlanes;
   /* 0x0004 */ uint doYuvToRgbConversionOnly;
-  /* 0x0008 */ tint_array<int8_t, 8> tint_pad;
+  /* 0x0008 */ tint_array<int8_t, 8> tint_pad_1;
   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix;
   /* 0x0040 */ GammaTransferParams gammaDecodeParams;
   /* 0x0060 */ GammaTransferParams gammaEncodeParams;
-  /* 0x0080 */ float3x3 gamutConversionMatrix;
+  /* 0x0080 */ tint_array<tint_packed_vec3_f32_array_element, 3> gamutConversionMatrix;
   /* 0x00b0 */ float3x2 coordTransformationMatrix;
-  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_2;
 };
 
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct ExternalTextureParams {
+  uint numPlanes;
+  uint doYuvToRgbConversionOnly;
+  float3x4 yuvToRgbConversionMatrix;
+  GammaTransferParams gammaDecodeParams;
+  GammaTransferParams gammaEncodeParams;
+  float3x3 gamutConversionMatrix;
+  float3x2 coordTransformationMatrix;
+};
+
+ExternalTextureParams tint_unpack_vec3_in_composite_1(ExternalTextureParams_tint_packed_vec3 in) {
+  ExternalTextureParams result = {};
+  result.numPlanes = in.numPlanes;
+  result.doYuvToRgbConversionOnly = in.doYuvToRgbConversionOnly;
+  result.yuvToRgbConversionMatrix = in.yuvToRgbConversionMatrix;
+  result.gammaDecodeParams = in.gammaDecodeParams;
+  result.gammaEncodeParams = in.gammaEncodeParams;
+  result.gamutConversionMatrix = tint_unpack_vec3_in_composite(in.gamutConversionMatrix);
+  result.coordTransformationMatrix = in.coordTransformationMatrix;
+  return result;
+}
+
+int2 tint_clamp(int2 e, int2 low, int2 high) {
+  return min(max(e, low), high);
+}
+
 float3 gammaCorrection(float3 v, GammaTransferParams params) {
   bool3 const cond = (fabs(v) < float3(params.D));
   float3 const t_1 = (sign(v) * ((params.C * fabs(v)) + params.F));
@@ -52,9 +87,9 @@
   int2 const coord1 = (coord >> uint2(1u));
   float3 color = 0.0f;
   if ((params.numPlanes == 1u)) {
-    color = float4(plane0.read(uint2(coord), 0)).rgb;
+    color = plane0.read(uint2(coord), 0).rgb;
   } else {
-    color = (float4(plane0.read(uint2(coord), 0)[0], float4(plane1.read(uint2(coord1), 0)).rg, 1.0f) * params.yuvToRgbConversionMatrix);
+    color = (float4(plane0.read(uint2(coord), 0)[0], plane1.read(uint2(coord1), 0).rg, 1.0f) * params.yuvToRgbConversionMatrix);
   }
   if ((params.doYuvToRgbConversionOnly == 0u)) {
     color = gammaCorrection(color, params.gammaDecodeParams);
@@ -64,13 +99,13 @@
   return float4(color, 1.0f);
 }
 
-kernel void tint_symbol(texture2d<float, access::sample> tint_symbol_5 [[texture(0)]], texture2d<float, access::sample> tint_symbol_6 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_7 [[buffer(0)]], texture2d<float, access::write> tint_symbol_8 [[texture(2)]]) {
+kernel void tint_symbol(texture2d<float, access::sample> tint_symbol_5 [[texture(0)]], texture2d<float, access::sample> tint_symbol_6 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_7 [[buffer(0)]], texture2d<float, access::write> tint_symbol_8 [[texture(2)]]) {
   int2 const tint_symbol_1 = tint_clamp(int2(10), int2(0), int2((uint2(uint2(tint_symbol_5.get_width(), tint_symbol_5.get_height())) - uint2(1u))));
-  float4 red = textureLoadExternal(tint_symbol_5, tint_symbol_6, tint_symbol_1, *(tint_symbol_7));
+  float4 red = textureLoadExternal(tint_symbol_5, tint_symbol_6, tint_symbol_1, tint_unpack_vec3_in_composite_1(*(tint_symbol_7)));
   int2 const tint_symbol_2 = tint_clamp(int2(0), int2(0), int2((uint2(uint2(tint_symbol_8.get_width(), tint_symbol_8.get_height())) - uint2(1u))));
   tint_symbol_8.write(red, uint2(tint_symbol_2));
   int2 const tint_symbol_3 = tint_clamp(int2(70, 118), int2(0), int2((uint2(uint2(tint_symbol_5.get_width(), tint_symbol_5.get_height())) - uint2(1u))));
-  float4 green = textureLoadExternal(tint_symbol_5, tint_symbol_6, tint_symbol_3, *(tint_symbol_7));
+  float4 green = textureLoadExternal(tint_symbol_5, tint_symbol_6, tint_symbol_3, tint_unpack_vec3_in_composite_1(*(tint_symbol_7)));
   int2 const tint_symbol_4 = tint_clamp(int2(1, 0), int2(0), int2((uint2(uint2(tint_symbol_8.get_width(), tint_symbol_8.get_height())) - uint2(1u))));
   tint_symbol_8.write(green, uint2(tint_symbol_4));
   return;
diff --git a/test/tint/bug/tint/294.wgsl.expected.msl b/test/tint/bug/tint/294.wgsl.expected.msl
index 77c8cea..919b455 100644
--- a/test/tint/bug/tint/294.wgsl.expected.msl
+++ b/test/tint/bug/tint/294.wgsl.expected.msl
@@ -14,6 +14,15 @@
     T elements[N];
 };
 
+struct Light_tint_packed_vec3 {
+  packed_float3 position;
+  packed_float3 colour;
+};
+
+struct Lights_tint_packed_vec3 {
+  tint_array<Light_tint_packed_vec3, 1> light;
+};
+
 struct Light {
   float3 position;
   float3 colour;
diff --git a/test/tint/bug/tint/453.wgsl.expected.msl b/test/tint/bug/tint/453.wgsl.expected.msl
index bde6be8..9cf9309 100644
--- a/test/tint/bug/tint/453.wgsl.expected.msl
+++ b/test/tint/bug/tint/453.wgsl.expected.msl
@@ -8,7 +8,7 @@
   uint const x_24 = srcValue[0];
   uint const x_25 = (x_24 + 1u);
   uint4 const x_27 = srcValue;
-  tint_symbol_2.write(uint4(x_27).xxxx, uint2(int2(0)));
+  tint_symbol_2.write(x_27.xxxx, uint2(int2(0)));
   return;
 }
 
diff --git a/test/tint/bug/tint/534.wgsl.expected.msl b/test/tint/bug/tint/534.wgsl.expected.msl
index 37b12cf..2fa76ad 100644
--- a/test/tint/bug/tint/534.wgsl.expected.msl
+++ b/test/tint/bug/tint/534.wgsl.expected.msl
@@ -31,7 +31,7 @@
 
 void tint_symbol_inner(uint3 GlobalInvocationID, texture2d<float, access::sample> tint_symbol_2, const constant Uniforms* const tint_symbol_3, texture2d<float, access::sample> tint_symbol_4, device OutputBuf* const tint_symbol_5) {
   uint2 size = uint2(tint_symbol_2.get_width(), tint_symbol_2.get_height());
-  uint2 dstTexCoord = uint3(GlobalInvocationID).xy;
+  uint2 dstTexCoord = GlobalInvocationID.xy;
   uint2 srcTexCoord = dstTexCoord;
   if (((*(tint_symbol_3)).dstTextureFlipY == 1u)) {
     srcTexCoord[1] = ((size[1] - dstTexCoord[1]) - 1u);
diff --git a/test/tint/bug/tint/757.wgsl.expected.msl b/test/tint/bug/tint/757.wgsl.expected.msl
index 0f16050..f9ee13b 100644
--- a/test/tint/bug/tint/757.wgsl.expected.msl
+++ b/test/tint/bug/tint/757.wgsl.expected.msl
@@ -25,7 +25,7 @@
 void tint_symbol_inner(uint3 GlobalInvocationID, texture2d_array<float, access::sample> tint_symbol_1, device Result* const tint_symbol_2) {
   uint flatIndex = (((4u * GlobalInvocationID[2]) + (2u * GlobalInvocationID[1])) + GlobalInvocationID[0]);
   flatIndex = (flatIndex * 1u);
-  float4 texel = tint_symbol_1.read(uint2(int2(uint3(GlobalInvocationID).xy)), 0, 0);
+  float4 texel = tint_symbol_1.read(uint2(int2(GlobalInvocationID.xy)), 0, 0);
   for(uint i = 0u; (i < 1u); i = (i + 1u)) {
     (*(tint_symbol_2)).values[(flatIndex + i)] = texel[0];
   }
diff --git a/test/tint/bug/tint/913.wgsl.expected.msl b/test/tint/bug/tint/913.wgsl.expected.msl
index 62aa83f..3520d9e 100644
--- a/test/tint/bug/tint/913.wgsl.expected.msl
+++ b/test/tint/bug/tint/913.wgsl.expected.msl
@@ -33,7 +33,7 @@
 void tint_symbol_inner(uint3 GlobalInvocationID, texture2d<float, access::sample> tint_symbol_7, texture2d<float, access::sample> tint_symbol_8, const constant Uniforms* const tint_symbol_9, device OutputBuf* const tint_symbol_10) {
   uint2 const srcSize = uint2(tint_symbol_7.get_width(), tint_symbol_7.get_height());
   uint2 const dstSize = uint2(tint_symbol_8.get_width(), tint_symbol_8.get_height());
-  uint2 const dstTexCoord = uint2(uint3(GlobalInvocationID).xy);
+  uint2 const dstTexCoord = uint2(GlobalInvocationID.xy);
   float4 const nonCoveredColor = float4(0.0f, 1.0f, 0.0f, 1.0f);
   bool success = true;
   if (((((dstTexCoord[0] < (*(tint_symbol_9)).dstCopyOrigin[0]) || (dstTexCoord[1] < (*(tint_symbol_9)).dstCopyOrigin[1])) || (dstTexCoord[0] >= ((*(tint_symbol_9)).dstCopyOrigin[0] + (*(tint_symbol_9)).copySize[0]))) || (dstTexCoord[1] >= ((*(tint_symbol_9)).dstCopyOrigin[1] + (*(tint_symbol_9)).copySize[1])))) {
diff --git a/test/tint/bug/tint/922.wgsl.expected.msl b/test/tint/bug/tint/922.wgsl.expected.msl
index 56d2fe7..11c4319 100644
--- a/test/tint/bug/tint/922.wgsl.expected.msl
+++ b/test/tint/bug/tint/922.wgsl.expected.msl
@@ -255,7 +255,7 @@
       Mat4x2_ const x_e64 = (*(tint_symbol_12)).u_TexMtx[0];
       float3 const x_e65 = *(tint_symbol_13);
       float2 const x_e68 = Mul2(x_e64, float4(x_e65, 1.0f));
-      *(tint_symbol_14) = float2(x_e68).xy;
+      *(tint_symbol_14) = x_e68.xy;
       return;
     }
   } else {
@@ -264,7 +264,7 @@
       Mat4x2_ const x_e79 = (*(tint_symbol_12)).u_TexMtx[0];
       float2 const x_e80 = *(tint_symbol_15);
       float2 const x_e84 = Mul2(x_e79, float4(x_e80, 1.0f, 1.0f));
-      *(tint_symbol_14) = float2(x_e84).xy;
+      *(tint_symbol_14) = x_e84.xy;
       return;
     }
   }
diff --git a/test/tint/bug/tint/942.wgsl.expected.msl b/test/tint/bug/tint/942.wgsl.expected.msl
index 991c4cf..6453075 100644
--- a/test/tint/bug/tint/942.wgsl.expected.msl
+++ b/test/tint/bug/tint/942.wgsl.expected.msl
@@ -36,14 +36,14 @@
   threadgroup_barrier(mem_flags::mem_threadgroup);
   uint const filterOffset = tint_div(((*(tint_symbol_2)).filterDim - 1u), 2u);
   uint2 const dims = uint2(tint_symbol_3.get_width(0), tint_symbol_3.get_height(0));
-  uint2 const baseIndex = (((uint3(WorkGroupID).xy * uint2((*(tint_symbol_2)).blockDim, 4u)) + (uint3(LocalInvocationID).xy * uint2(4u, 1u))) - uint2(filterOffset, 0u));
+  uint2 const baseIndex = (((WorkGroupID.xy * uint2((*(tint_symbol_2)).blockDim, 4u)) + (LocalInvocationID.xy * uint2(4u, 1u))) - uint2(filterOffset, 0u));
   for(uint r = 0u; (r < 4u); r = (r + 1u)) {
     for(uint c = 0u; (c < 4u); c = (c + 1u)) {
       uint2 loadIndex = (baseIndex + uint2(c, r));
       if (((*(tint_symbol_4)).value != 0u)) {
-        loadIndex = uint2(loadIndex).yx;
+        loadIndex = loadIndex.yx;
       }
-      (*(tint_symbol_1))[r][((4u * LocalInvocationID[0]) + c)] = float4(tint_symbol_3.sample(tint_symbol_5, ((float2(loadIndex) + float2(0.25f)) / float2(dims)), level(0.0f))).rgb;
+      (*(tint_symbol_1))[r][((4u * LocalInvocationID[0]) + c)] = tint_symbol_3.sample(tint_symbol_5, ((float2(loadIndex) + float2(0.25f)) / float2(dims)), level(0.0f)).rgb;
     }
   }
   threadgroup_barrier(mem_flags::mem_threadgroup);
@@ -51,7 +51,7 @@
     for(uint c = 0u; (c < 4u); c = (c + 1u)) {
       uint2 writeIndex = (baseIndex + uint2(c, r));
       if (((*(tint_symbol_4)).value != 0u)) {
-        writeIndex = uint2(writeIndex).yx;
+        writeIndex = writeIndex.yx;
       }
       uint const center = ((4u * LocalInvocationID[0]) + c);
       if ((((center >= filterOffset) && (center < (256u - filterOffset))) && all((writeIndex < dims)))) {
diff --git a/test/tint/bug/tint/948.wgsl.expected.msl b/test/tint/bug/tint/948.wgsl.expected.msl
index e77abf2..85775c9 100644
--- a/test/tint/bug/tint/948.wgsl.expected.msl
+++ b/test/tint/bug/tint/948.wgsl.expected.msl
@@ -14,7 +14,7 @@
     T elements[N];
 };
 
-struct LeftOver {
+struct LeftOver_tint_packed_vec3 {
   /* 0x0000 */ float time;
   /* 0x0004 */ uint padding;
   /* 0x0008 */ tint_array<int8_t, 8> tint_pad;
@@ -28,7 +28,19 @@
   /* 0x007c */ tint_array<int8_t, 4> tint_pad_1;
 };
 
-float4x4 getFrameData_f1_(thread float* const frameID, const constant LeftOver* const tint_symbol_5, texture2d<float, access::sample> tint_symbol_6, sampler tint_symbol_7) {
+struct LeftOver {
+  float time;
+  uint padding;
+  float4x4 worldViewProjection;
+  float2 outputSize;
+  float2 stageSize;
+  float2 spriteMapSize;
+  float stageScale;
+  float spriteCount;
+  float3 colorMul;
+};
+
+float4x4 getFrameData_f1_(thread float* const frameID, const constant LeftOver_tint_packed_vec3* const tint_symbol_5, texture2d<float, access::sample> tint_symbol_6, sampler tint_symbol_7) {
   float fX = 0.0f;
   float const x_15 = *(frameID);
   float const x_25 = (*(tint_symbol_5)).spriteCount;
@@ -42,7 +54,7 @@
   return float4x4(float4(x_40[0], x_40[1], x_40[2], x_40[3]), float4(x_47[0], x_47[1], x_47[2], x_47[3]), float4(x_54[0], x_54[1], x_54[2], x_54[3]), float4(0.0f));
 }
 
-void main_1(thread float2* const tint_symbol_8, const constant LeftOver* const tint_symbol_9, texture2d<float, access::sample> tint_symbol_10, sampler tint_symbol_11, texture2d<float, access::sample> tint_symbol_12, texture2d<float, access::sample> tint_symbol_13, sampler tint_symbol_14, texture2d<float, access::sample> tint_symbol_16, sampler tint_symbol_17, texture2d<float, access::sample> tint_symbol_18, sampler tint_symbol_19, thread float4* const tint_symbol_20) {
+void main_1(thread float2* const tint_symbol_8, const constant LeftOver_tint_packed_vec3* const tint_symbol_9, texture2d<float, access::sample> tint_symbol_10, sampler tint_symbol_11, texture2d<float, access::sample> tint_symbol_12, texture2d<float, access::sample> tint_symbol_13, sampler tint_symbol_14, texture2d<float, access::sample> tint_symbol_16, sampler tint_symbol_17, texture2d<float, access::sample> tint_symbol_18, sampler tint_symbol_19, thread float4* const tint_symbol_20) {
   thread float tint_symbol_15 = 0.0f;
   float4 color = 0.0f;
   float2 tileUV = 0.0f;
@@ -210,7 +222,7 @@
   float4 glFragColor_1 [[color(0)]];
 };
 
-main_out tint_symbol_inner(float2 tUV_param, float2 tileID_1_param, float2 levelUnits_param, float2 stageUnits_1_param, float3 vPosition_param, float2 vUV_param, thread float2* const tint_symbol_21, const constant LeftOver* const tint_symbol_27, texture2d<float, access::sample> tint_symbol_28, sampler tint_symbol_29, texture2d<float, access::sample> tint_symbol_30, texture2d<float, access::sample> tint_symbol_31, sampler tint_symbol_32, texture2d<float, access::sample> tint_symbol_33, sampler tint_symbol_34, texture2d<float, access::sample> tint_symbol_35, sampler tint_symbol_36, thread float4* const tint_symbol_37) {
+main_out tint_symbol_inner(float2 tUV_param, float2 tileID_1_param, float2 levelUnits_param, float2 stageUnits_1_param, float3 vPosition_param, float2 vUV_param, thread float2* const tint_symbol_21, const constant LeftOver_tint_packed_vec3* const tint_symbol_27, texture2d<float, access::sample> tint_symbol_28, sampler tint_symbol_29, texture2d<float, access::sample> tint_symbol_30, texture2d<float, access::sample> tint_symbol_31, sampler tint_symbol_32, texture2d<float, access::sample> tint_symbol_33, sampler tint_symbol_34, texture2d<float, access::sample> tint_symbol_35, sampler tint_symbol_36, thread float4* const tint_symbol_37) {
   thread float2 tint_symbol_22 = 0.0f;
   thread float2 tint_symbol_23 = 0.0f;
   thread float2 tint_symbol_24 = 0.0f;
@@ -227,7 +239,7 @@
   return tint_symbol_4;
 }
 
-fragment tint_symbol_3 tint_symbol(const constant LeftOver* tint_symbol_39 [[buffer(0)]], texture2d<float, access::sample> tint_symbol_40 [[texture(0)]], sampler tint_symbol_41 [[sampler(0)]], texture2d<float, access::sample> tint_symbol_42 [[texture(1)]], texture2d<float, access::sample> tint_symbol_43 [[texture(2)]], sampler tint_symbol_44 [[sampler(1)]], texture2d<float, access::sample> tint_symbol_45 [[texture(3)]], sampler tint_symbol_46 [[sampler(2)]], texture2d<float, access::sample> tint_symbol_47 [[texture(4)]], sampler tint_symbol_48 [[sampler(3)]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+fragment tint_symbol_3 tint_symbol(const constant LeftOver_tint_packed_vec3* tint_symbol_39 [[buffer(0)]], texture2d<float, access::sample> tint_symbol_40 [[texture(0)]], sampler tint_symbol_41 [[sampler(0)]], texture2d<float, access::sample> tint_symbol_42 [[texture(1)]], texture2d<float, access::sample> tint_symbol_43 [[texture(2)]], sampler tint_symbol_44 [[sampler(1)]], texture2d<float, access::sample> tint_symbol_45 [[texture(3)]], sampler tint_symbol_46 [[sampler(2)]], texture2d<float, access::sample> tint_symbol_47 [[texture(4)]], sampler tint_symbol_48 [[sampler(3)]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
   thread float2 tint_symbol_38 = 0.0f;
   thread float4 tint_symbol_49 = 0.0f;
   main_out const inner_result = tint_symbol_inner(tint_symbol_1.tUV_param, tint_symbol_1.tileID_1_param, tint_symbol_1.levelUnits_param, tint_symbol_1.stageUnits_1_param, tint_symbol_1.vPosition_param, tint_symbol_1.vUV_param, &(tint_symbol_38), tint_symbol_39, tint_symbol_40, tint_symbol_41, tint_symbol_42, tint_symbol_43, tint_symbol_44, tint_symbol_45, tint_symbol_46, tint_symbol_47, tint_symbol_48, &(tint_symbol_49));
diff --git a/test/tint/bug/tint/949.wgsl.expected.msl b/test/tint/bug/tint/949.wgsl.expected.msl
index 44f5320..779b99b 100644
--- a/test/tint/bug/tint/949.wgsl.expected.msl
+++ b/test/tint/bug/tint/949.wgsl.expected.msl
@@ -14,12 +14,7 @@
     T elements[N];
 };
 
-struct lightingInfo {
-  float3 diffuse;
-  float3 specular;
-};
-
-struct LeftOver {
+struct LeftOver_tint_packed_vec3 {
   /* 0x0000 */ float4x4 u_World;
   /* 0x0040 */ float4x4 u_ViewProjection;
   /* 0x0080 */ float u_bumpStrength;
@@ -32,7 +27,7 @@
   /* 0x00a8 */ float2 tangentSpaceParameter0;
 };
 
-struct Light0 {
+struct Light0_tint_packed_vec3 {
   /* 0x0000 */ float4 vLightData;
   /* 0x0010 */ float4 vLightDiffuse;
   /* 0x0020 */ float4 vLightSpecular;
@@ -43,6 +38,33 @@
   /* 0x0058 */ tint_array<int8_t, 8> tint_pad_1;
 };
 
+struct lightingInfo {
+  float3 diffuse;
+  float3 specular;
+};
+
+struct LeftOver {
+  float4x4 u_World;
+  float4x4 u_ViewProjection;
+  float u_bumpStrength;
+  uint padding;
+  float3 u_cameraPosition;
+  float u_parallaxScale;
+  float textureInfoName;
+  uint padding_1;
+  float2 tangentSpaceParameter0;
+};
+
+struct Light0 {
+  float4 vLightData;
+  float4 vLightDiffuse;
+  float4 vLightSpecular;
+  float3 vLightGround;
+  uint padding_2;
+  float4 shadowsInfo;
+  float2 depthValues;
+};
+
 float3x3 cotangent_frame_vf3_vf3_vf2_vf2_(thread float3* const normal_1, thread float3* const p, thread float2* const uv, thread float2* const tangentSpaceParams) {
   float3 dp1 = 0.0f;
   float3 dp2 = 0.0f;
@@ -174,7 +196,7 @@
   return x_245;
 }
 
-void main_1(thread float2* const tint_symbol_7, texture2d<float, access::sample> tint_symbol_8, sampler tint_symbol_9, const constant LeftOver* const tint_symbol_10, thread float4* const tint_symbol_11, thread bool* const tint_symbol_12, thread float2* const tint_symbol_13, thread float4* const tint_symbol_14, texture2d<float, access::sample> tint_symbol_15, sampler tint_symbol_16, const constant Light0* const tint_symbol_17, thread float4* const tint_symbol_18) {
+void main_1(thread float2* const tint_symbol_7, texture2d<float, access::sample> tint_symbol_8, sampler tint_symbol_9, const constant LeftOver_tint_packed_vec3* const tint_symbol_10, thread float4* const tint_symbol_11, thread bool* const tint_symbol_12, thread float2* const tint_symbol_13, thread float4* const tint_symbol_14, texture2d<float, access::sample> tint_symbol_15, sampler tint_symbol_16, const constant Light0_tint_packed_vec3* const tint_symbol_17, thread float4* const tint_symbol_18) {
   thread float tint_symbol_5 = 0.0f;
   thread float3 tint_symbol_6 = 0.0f;
   float4 tempTextureRead = 0.0f;
@@ -434,7 +456,7 @@
   float4 glFragColor_1 [[color(0)]];
 };
 
-main_out tint_symbol_inner(float2 vMainuv_param, float4 v_output1_param, bool gl_FrontFacing_param, float2 v_uv_param, float4 v_output2_param, thread float2* const tint_symbol_19, thread float4* const tint_symbol_20, thread bool* const tint_symbol_21, thread float2* const tint_symbol_22, thread float4* const tint_symbol_23, texture2d<float, access::sample> tint_symbol_24, sampler tint_symbol_25, const constant LeftOver* const tint_symbol_26, texture2d<float, access::sample> tint_symbol_27, sampler tint_symbol_28, const constant Light0* const tint_symbol_29, thread float4* const tint_symbol_30) {
+main_out tint_symbol_inner(float2 vMainuv_param, float4 v_output1_param, bool gl_FrontFacing_param, float2 v_uv_param, float4 v_output2_param, thread float2* const tint_symbol_19, thread float4* const tint_symbol_20, thread bool* const tint_symbol_21, thread float2* const tint_symbol_22, thread float4* const tint_symbol_23, texture2d<float, access::sample> tint_symbol_24, sampler tint_symbol_25, const constant LeftOver_tint_packed_vec3* const tint_symbol_26, texture2d<float, access::sample> tint_symbol_27, sampler tint_symbol_28, const constant Light0_tint_packed_vec3* const tint_symbol_29, thread float4* const tint_symbol_30) {
   *(tint_symbol_19) = vMainuv_param;
   *(tint_symbol_20) = v_output1_param;
   *(tint_symbol_21) = gl_FrontFacing_param;
@@ -445,7 +467,7 @@
   return tint_symbol_4;
 }
 
-fragment tint_symbol_3 tint_symbol(texture2d<float, access::sample> tint_symbol_36 [[texture(0)]], sampler tint_symbol_37 [[sampler(0)]], const constant LeftOver* tint_symbol_38 [[buffer(0)]], texture2d<float, access::sample> tint_symbol_39 [[texture(1)]], sampler tint_symbol_40 [[sampler(1)]], const constant Light0* tint_symbol_41 [[buffer(1)]], bool gl_FrontFacing_param [[front_facing]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+fragment tint_symbol_3 tint_symbol(texture2d<float, access::sample> tint_symbol_36 [[texture(0)]], sampler tint_symbol_37 [[sampler(0)]], const constant LeftOver_tint_packed_vec3* tint_symbol_38 [[buffer(0)]], texture2d<float, access::sample> tint_symbol_39 [[texture(1)]], sampler tint_symbol_40 [[sampler(1)]], const constant Light0_tint_packed_vec3* tint_symbol_41 [[buffer(1)]], bool gl_FrontFacing_param [[front_facing]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
   thread float2 tint_symbol_31 = 0.0f;
   thread float4 tint_symbol_32 = 0.0f;
   thread bool tint_symbol_33 = false;
diff --git a/test/tint/bug/tint/980.wgsl.expected.msl b/test/tint/bug/tint/980.wgsl.expected.msl
index 36cce9d..cb9fabc 100644
--- a/test/tint/bug/tint/980.wgsl.expected.msl
+++ b/test/tint/bug/tint/980.wgsl.expected.msl
@@ -1,6 +1,11 @@
 #include <metal_stdlib>
 
 using namespace metal;
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ packed_float3 v;
+  /* 0x000c */ uint i;
+};
+
 float3 Bad(uint index, float3 rd) {
   float3 normal = float3(0.0f);
   normal[index] = -(sign(rd[index]));
@@ -8,16 +13,16 @@
 }
 
 struct S {
-  /* 0x0000 */ packed_float3 v;
-  /* 0x000c */ uint i;
+  float3 v;
+  uint i;
 };
 
-void tint_symbol_inner(uint idx, device S* const tint_symbol_2) {
+void tint_symbol_inner(uint idx, device S_tint_packed_vec3* const tint_symbol_2) {
   float3 const tint_symbol_1 = Bad((*(tint_symbol_2)).i, float3((*(tint_symbol_2)).v));
-  (*(tint_symbol_2)).v = tint_symbol_1;
+  (*(tint_symbol_2)).v = packed_float3(tint_symbol_1);
 }
 
-kernel void tint_symbol(device S* tint_symbol_3 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
+kernel void tint_symbol(device S_tint_packed_vec3* tint_symbol_3 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) {
   tint_symbol_inner(idx, tint_symbol_3);
   return;
 }
diff --git a/test/tint/builtins/gen/literal/textureDimensions/cdc6c9.wgsl.expected.msl b/test/tint/builtins/gen/literal/textureDimensions/cdc6c9.wgsl.expected.msl
index ec4f006..61a10dc 100644
--- a/test/tint/builtins/gen/literal/textureDimensions/cdc6c9.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/textureDimensions/cdc6c9.wgsl.expected.msl
@@ -1,6 +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];
+};
+
+struct tint_packed_vec3_f32_array_element {
+  packed_float3 elements;
+};
+
 struct GammaTransferParams {
   float G;
   float A;
@@ -12,6 +29,16 @@
   uint padding;
 };
 
+struct ExternalTextureParams_tint_packed_vec3 {
+  uint numPlanes;
+  uint doYuvToRgbConversionOnly;
+  float3x4 yuvToRgbConversionMatrix;
+  GammaTransferParams gammaDecodeParams;
+  GammaTransferParams gammaEncodeParams;
+  tint_array<tint_packed_vec3_f32_array_element, 3> gamutConversionMatrix;
+  float3x2 coordTransformationMatrix;
+};
+
 struct ExternalTextureParams {
   uint numPlanes;
   uint doYuvToRgbConversionOnly;
diff --git a/test/tint/builtins/gen/literal/textureLoad/1bfdfb.wgsl.expected.msl b/test/tint/builtins/gen/literal/textureLoad/1bfdfb.wgsl.expected.msl
index 016c2a7..e9166ef 100644
--- a/test/tint/builtins/gen/literal/textureLoad/1bfdfb.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/textureLoad/1bfdfb.wgsl.expected.msl
@@ -14,6 +14,11 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
 struct GammaTransferParams {
   /* 0x0000 */ float G;
   /* 0x0004 */ float A;
@@ -25,18 +30,48 @@
   /* 0x001c */ uint padding;
 };
 
-struct ExternalTextureParams {
+struct ExternalTextureParams_tint_packed_vec3 {
   /* 0x0000 */ uint numPlanes;
   /* 0x0004 */ uint doYuvToRgbConversionOnly;
-  /* 0x0008 */ tint_array<int8_t, 8> tint_pad;
+  /* 0x0008 */ tint_array<int8_t, 8> tint_pad_1;
   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix;
   /* 0x0040 */ GammaTransferParams gammaDecodeParams;
   /* 0x0060 */ GammaTransferParams gammaEncodeParams;
-  /* 0x0080 */ float3x3 gamutConversionMatrix;
+  /* 0x0080 */ tint_array<tint_packed_vec3_f32_array_element, 3> gamutConversionMatrix;
   /* 0x00b0 */ float3x2 coordTransformationMatrix;
-  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_2;
 };
 
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct ExternalTextureParams {
+  uint numPlanes;
+  uint doYuvToRgbConversionOnly;
+  float3x4 yuvToRgbConversionMatrix;
+  GammaTransferParams gammaDecodeParams;
+  GammaTransferParams gammaEncodeParams;
+  float3x3 gamutConversionMatrix;
+  float3x2 coordTransformationMatrix;
+};
+
+ExternalTextureParams tint_unpack_vec3_in_composite_1(ExternalTextureParams_tint_packed_vec3 in) {
+  ExternalTextureParams result = {};
+  result.numPlanes = in.numPlanes;
+  result.doYuvToRgbConversionOnly = in.doYuvToRgbConversionOnly;
+  result.yuvToRgbConversionMatrix = in.yuvToRgbConversionMatrix;
+  result.gammaDecodeParams = in.gammaDecodeParams;
+  result.gammaEncodeParams = in.gammaEncodeParams;
+  result.gamutConversionMatrix = tint_unpack_vec3_in_composite(in.gamutConversionMatrix);
+  result.coordTransformationMatrix = in.coordTransformationMatrix;
+  return result;
+}
+
 float3 gammaCorrection(float3 v, GammaTransferParams params) {
   bool3 const cond = (fabs(v) < float3(params.D));
   float3 const t = (sign(v) * ((params.C * fabs(v)) + params.F));
@@ -48,9 +83,9 @@
   uint2 const coord1 = (coord >> uint2(1u));
   float3 color = 0.0f;
   if ((params.numPlanes == 1u)) {
-    color = float4(plane0.read(uint2(coord), 0)).rgb;
+    color = plane0.read(uint2(coord), 0).rgb;
   } else {
-    color = (float4(plane0.read(uint2(coord), 0)[0], float4(plane1.read(uint2(coord1), 0)).rg, 1.0f) * params.yuvToRgbConversionMatrix);
+    color = (float4(plane0.read(uint2(coord), 0)[0], plane1.read(uint2(coord1), 0).rg, 1.0f) * params.yuvToRgbConversionMatrix);
   }
   if ((params.doYuvToRgbConversionOnly == 0u)) {
     color = gammaCorrection(color, params.gammaDecodeParams);
@@ -60,32 +95,32 @@
   return float4(color, 1.0f);
 }
 
-void textureLoad_1bfdfb(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, const constant ExternalTextureParams* const tint_symbol_3) {
-  float4 res = textureLoadExternal(tint_symbol_1, tint_symbol_2, uint2(1u), *(tint_symbol_3));
+void textureLoad_1bfdfb(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_3) {
+  float4 res = textureLoadExternal(tint_symbol_1, tint_symbol_2, uint2(1u), tint_unpack_vec3_in_composite_1(*(tint_symbol_3)));
 }
 
 struct tint_symbol {
   float4 value [[position]];
 };
 
-float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_4, texture2d<float, access::sample> tint_symbol_5, const constant ExternalTextureParams* const tint_symbol_6) {
+float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_4, texture2d<float, access::sample> tint_symbol_5, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_6) {
   textureLoad_1bfdfb(tint_symbol_4, tint_symbol_5, tint_symbol_6);
   return float4(0.0f);
 }
 
-vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_7 [[texture(0)]], texture2d<float, access::sample> tint_symbol_8 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_9 [[buffer(2)]]) {
+vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_7 [[texture(0)]], texture2d<float, access::sample> tint_symbol_8 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_9 [[buffer(2)]]) {
   float4 const inner_result = vertex_main_inner(tint_symbol_7, tint_symbol_8, tint_symbol_9);
   tint_symbol wrapper_result = {};
   wrapper_result.value = inner_result;
   return wrapper_result;
 }
 
-fragment void fragment_main(texture2d<float, access::sample> tint_symbol_10 [[texture(0)]], texture2d<float, access::sample> tint_symbol_11 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_12 [[buffer(2)]]) {
+fragment void fragment_main(texture2d<float, access::sample> tint_symbol_10 [[texture(0)]], texture2d<float, access::sample> tint_symbol_11 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_12 [[buffer(2)]]) {
   textureLoad_1bfdfb(tint_symbol_10, tint_symbol_11, tint_symbol_12);
   return;
 }
 
-kernel void compute_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_15 [[buffer(2)]]) {
+kernel void compute_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_15 [[buffer(2)]]) {
   textureLoad_1bfdfb(tint_symbol_13, tint_symbol_14, tint_symbol_15);
   return;
 }
diff --git a/test/tint/builtins/gen/literal/textureLoad/8acf41.wgsl.expected.msl b/test/tint/builtins/gen/literal/textureLoad/8acf41.wgsl.expected.msl
index 812bf58..8ef22b0 100644
--- a/test/tint/builtins/gen/literal/textureLoad/8acf41.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/textureLoad/8acf41.wgsl.expected.msl
@@ -14,6 +14,11 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
 struct GammaTransferParams {
   /* 0x0000 */ float G;
   /* 0x0004 */ float A;
@@ -25,18 +30,48 @@
   /* 0x001c */ uint padding;
 };
 
-struct ExternalTextureParams {
+struct ExternalTextureParams_tint_packed_vec3 {
   /* 0x0000 */ uint numPlanes;
   /* 0x0004 */ uint doYuvToRgbConversionOnly;
-  /* 0x0008 */ tint_array<int8_t, 8> tint_pad;
+  /* 0x0008 */ tint_array<int8_t, 8> tint_pad_1;
   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix;
   /* 0x0040 */ GammaTransferParams gammaDecodeParams;
   /* 0x0060 */ GammaTransferParams gammaEncodeParams;
-  /* 0x0080 */ float3x3 gamutConversionMatrix;
+  /* 0x0080 */ tint_array<tint_packed_vec3_f32_array_element, 3> gamutConversionMatrix;
   /* 0x00b0 */ float3x2 coordTransformationMatrix;
-  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_2;
 };
 
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct ExternalTextureParams {
+  uint numPlanes;
+  uint doYuvToRgbConversionOnly;
+  float3x4 yuvToRgbConversionMatrix;
+  GammaTransferParams gammaDecodeParams;
+  GammaTransferParams gammaEncodeParams;
+  float3x3 gamutConversionMatrix;
+  float3x2 coordTransformationMatrix;
+};
+
+ExternalTextureParams tint_unpack_vec3_in_composite_1(ExternalTextureParams_tint_packed_vec3 in) {
+  ExternalTextureParams result = {};
+  result.numPlanes = in.numPlanes;
+  result.doYuvToRgbConversionOnly = in.doYuvToRgbConversionOnly;
+  result.yuvToRgbConversionMatrix = in.yuvToRgbConversionMatrix;
+  result.gammaDecodeParams = in.gammaDecodeParams;
+  result.gammaEncodeParams = in.gammaEncodeParams;
+  result.gamutConversionMatrix = tint_unpack_vec3_in_composite(in.gamutConversionMatrix);
+  result.coordTransformationMatrix = in.coordTransformationMatrix;
+  return result;
+}
+
 float3 gammaCorrection(float3 v, GammaTransferParams params) {
   bool3 const cond = (fabs(v) < float3(params.D));
   float3 const t = (sign(v) * ((params.C * fabs(v)) + params.F));
@@ -48,9 +83,9 @@
   int2 const coord1 = (coord >> uint2(1u));
   float3 color = 0.0f;
   if ((params.numPlanes == 1u)) {
-    color = float4(plane0.read(uint2(coord), 0)).rgb;
+    color = plane0.read(uint2(coord), 0).rgb;
   } else {
-    color = (float4(plane0.read(uint2(coord), 0)[0], float4(plane1.read(uint2(coord1), 0)).rg, 1.0f) * params.yuvToRgbConversionMatrix);
+    color = (float4(plane0.read(uint2(coord), 0)[0], plane1.read(uint2(coord1), 0).rg, 1.0f) * params.yuvToRgbConversionMatrix);
   }
   if ((params.doYuvToRgbConversionOnly == 0u)) {
     color = gammaCorrection(color, params.gammaDecodeParams);
@@ -60,32 +95,32 @@
   return float4(color, 1.0f);
 }
 
-void textureLoad_8acf41(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, const constant ExternalTextureParams* const tint_symbol_3) {
-  float4 res = textureLoadExternal(tint_symbol_1, tint_symbol_2, int2(1), *(tint_symbol_3));
+void textureLoad_8acf41(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_3) {
+  float4 res = textureLoadExternal(tint_symbol_1, tint_symbol_2, int2(1), tint_unpack_vec3_in_composite_1(*(tint_symbol_3)));
 }
 
 struct tint_symbol {
   float4 value [[position]];
 };
 
-float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_4, texture2d<float, access::sample> tint_symbol_5, const constant ExternalTextureParams* const tint_symbol_6) {
+float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_4, texture2d<float, access::sample> tint_symbol_5, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_6) {
   textureLoad_8acf41(tint_symbol_4, tint_symbol_5, tint_symbol_6);
   return float4(0.0f);
 }
 
-vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_7 [[texture(0)]], texture2d<float, access::sample> tint_symbol_8 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_9 [[buffer(2)]]) {
+vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_7 [[texture(0)]], texture2d<float, access::sample> tint_symbol_8 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_9 [[buffer(2)]]) {
   float4 const inner_result = vertex_main_inner(tint_symbol_7, tint_symbol_8, tint_symbol_9);
   tint_symbol wrapper_result = {};
   wrapper_result.value = inner_result;
   return wrapper_result;
 }
 
-fragment void fragment_main(texture2d<float, access::sample> tint_symbol_10 [[texture(0)]], texture2d<float, access::sample> tint_symbol_11 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_12 [[buffer(2)]]) {
+fragment void fragment_main(texture2d<float, access::sample> tint_symbol_10 [[texture(0)]], texture2d<float, access::sample> tint_symbol_11 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_12 [[buffer(2)]]) {
   textureLoad_8acf41(tint_symbol_10, tint_symbol_11, tint_symbol_12);
   return;
 }
 
-kernel void compute_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_15 [[buffer(2)]]) {
+kernel void compute_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_15 [[buffer(2)]]) {
   textureLoad_8acf41(tint_symbol_13, tint_symbol_14, tint_symbol_15);
   return;
 }
diff --git a/test/tint/builtins/gen/literal/textureSampleBaseClampToEdge/7c04e6.wgsl.expected.msl b/test/tint/builtins/gen/literal/textureSampleBaseClampToEdge/7c04e6.wgsl.expected.msl
index b06119d..3a204fa 100644
--- a/test/tint/builtins/gen/literal/textureSampleBaseClampToEdge/7c04e6.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/textureSampleBaseClampToEdge/7c04e6.wgsl.expected.msl
@@ -14,6 +14,11 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
 struct GammaTransferParams {
   /* 0x0000 */ float G;
   /* 0x0004 */ float A;
@@ -25,18 +30,48 @@
   /* 0x001c */ uint padding;
 };
 
-struct ExternalTextureParams {
+struct ExternalTextureParams_tint_packed_vec3 {
   /* 0x0000 */ uint numPlanes;
   /* 0x0004 */ uint doYuvToRgbConversionOnly;
-  /* 0x0008 */ tint_array<int8_t, 8> tint_pad;
+  /* 0x0008 */ tint_array<int8_t, 8> tint_pad_1;
   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix;
   /* 0x0040 */ GammaTransferParams gammaDecodeParams;
   /* 0x0060 */ GammaTransferParams gammaEncodeParams;
-  /* 0x0080 */ float3x3 gamutConversionMatrix;
+  /* 0x0080 */ tint_array<tint_packed_vec3_f32_array_element, 3> gamutConversionMatrix;
   /* 0x00b0 */ float3x2 coordTransformationMatrix;
-  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_2;
 };
 
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct ExternalTextureParams {
+  uint numPlanes;
+  uint doYuvToRgbConversionOnly;
+  float3x4 yuvToRgbConversionMatrix;
+  GammaTransferParams gammaDecodeParams;
+  GammaTransferParams gammaEncodeParams;
+  float3x3 gamutConversionMatrix;
+  float3x2 coordTransformationMatrix;
+};
+
+ExternalTextureParams tint_unpack_vec3_in_composite_1(ExternalTextureParams_tint_packed_vec3 in) {
+  ExternalTextureParams result = {};
+  result.numPlanes = in.numPlanes;
+  result.doYuvToRgbConversionOnly = in.doYuvToRgbConversionOnly;
+  result.yuvToRgbConversionMatrix = in.yuvToRgbConversionMatrix;
+  result.gammaDecodeParams = in.gammaDecodeParams;
+  result.gammaEncodeParams = in.gammaEncodeParams;
+  result.gamutConversionMatrix = tint_unpack_vec3_in_composite(in.gamutConversionMatrix);
+  result.coordTransformationMatrix = in.coordTransformationMatrix;
+  return result;
+}
+
 float3 gammaCorrection(float3 v, GammaTransferParams params) {
   bool3 const cond = (fabs(v) < float3(params.D));
   float3 const t = (sign(v) * ((params.C * fabs(v)) + params.F));
@@ -54,9 +89,9 @@
   float2 const plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1.0f - plane1_half_texel));
   float3 color = 0.0f;
   if ((params.numPlanes == 1u)) {
-    color = float4(plane0.sample(smp, plane0_clamped, level(0.0f))).rgb;
+    color = plane0.sample(smp, plane0_clamped, level(0.0f)).rgb;
   } else {
-    color = (float4(plane0.sample(smp, plane0_clamped, level(0.0f))[0], float4(plane1.sample(smp, plane1_clamped, level(0.0f))).rg, 1.0f) * params.yuvToRgbConversionMatrix);
+    color = (float4(plane0.sample(smp, plane0_clamped, level(0.0f))[0], plane1.sample(smp, plane1_clamped, level(0.0f)).rg, 1.0f) * params.yuvToRgbConversionMatrix);
   }
   if ((params.doYuvToRgbConversionOnly == 0u)) {
     color = gammaCorrection(color, params.gammaDecodeParams);
@@ -66,32 +101,32 @@
   return float4(color, 1.0f);
 }
 
-void textureSampleBaseClampToEdge_7c04e6(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, sampler tint_symbol_3, const constant ExternalTextureParams* const tint_symbol_4) {
-  float4 res = textureSampleExternal(tint_symbol_1, tint_symbol_2, tint_symbol_3, float2(1.0f), *(tint_symbol_4));
+void textureSampleBaseClampToEdge_7c04e6(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, sampler tint_symbol_3, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_4) {
+  float4 res = textureSampleExternal(tint_symbol_1, tint_symbol_2, tint_symbol_3, float2(1.0f), tint_unpack_vec3_in_composite_1(*(tint_symbol_4)));
 }
 
 struct tint_symbol {
   float4 value [[position]];
 };
 
-float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_5, texture2d<float, access::sample> tint_symbol_6, sampler tint_symbol_7, const constant ExternalTextureParams* const tint_symbol_8) {
+float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_5, texture2d<float, access::sample> tint_symbol_6, sampler tint_symbol_7, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_8) {
   textureSampleBaseClampToEdge_7c04e6(tint_symbol_5, tint_symbol_6, tint_symbol_7, tint_symbol_8);
   return float4(0.0f);
 }
 
-vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_9 [[texture(0)]], texture2d<float, access::sample> tint_symbol_10 [[texture(1)]], sampler tint_symbol_11 [[sampler(0)]], const constant ExternalTextureParams* tint_symbol_12 [[buffer(2)]]) {
+vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_9 [[texture(0)]], texture2d<float, access::sample> tint_symbol_10 [[texture(1)]], sampler tint_symbol_11 [[sampler(0)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_12 [[buffer(2)]]) {
   float4 const inner_result = vertex_main_inner(tint_symbol_9, tint_symbol_10, tint_symbol_11, tint_symbol_12);
   tint_symbol wrapper_result = {};
   wrapper_result.value = inner_result;
   return wrapper_result;
 }
 
-fragment void fragment_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], sampler tint_symbol_15 [[sampler(0)]], const constant ExternalTextureParams* tint_symbol_16 [[buffer(2)]]) {
+fragment void fragment_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], sampler tint_symbol_15 [[sampler(0)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_16 [[buffer(2)]]) {
   textureSampleBaseClampToEdge_7c04e6(tint_symbol_13, tint_symbol_14, tint_symbol_15, tint_symbol_16);
   return;
 }
 
-kernel void compute_main(texture2d<float, access::sample> tint_symbol_17 [[texture(0)]], texture2d<float, access::sample> tint_symbol_18 [[texture(1)]], sampler tint_symbol_19 [[sampler(0)]], const constant ExternalTextureParams* tint_symbol_20 [[buffer(2)]]) {
+kernel void compute_main(texture2d<float, access::sample> tint_symbol_17 [[texture(0)]], texture2d<float, access::sample> tint_symbol_18 [[texture(1)]], sampler tint_symbol_19 [[sampler(0)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_20 [[buffer(2)]]) {
   textureSampleBaseClampToEdge_7c04e6(tint_symbol_17, tint_symbol_18, tint_symbol_19, tint_symbol_20);
   return;
 }
diff --git a/test/tint/builtins/gen/var/textureDimensions/cdc6c9.wgsl.expected.msl b/test/tint/builtins/gen/var/textureDimensions/cdc6c9.wgsl.expected.msl
index ec4f006..61a10dc 100644
--- a/test/tint/builtins/gen/var/textureDimensions/cdc6c9.wgsl.expected.msl
+++ b/test/tint/builtins/gen/var/textureDimensions/cdc6c9.wgsl.expected.msl
@@ -1,6 +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];
+};
+
+struct tint_packed_vec3_f32_array_element {
+  packed_float3 elements;
+};
+
 struct GammaTransferParams {
   float G;
   float A;
@@ -12,6 +29,16 @@
   uint padding;
 };
 
+struct ExternalTextureParams_tint_packed_vec3 {
+  uint numPlanes;
+  uint doYuvToRgbConversionOnly;
+  float3x4 yuvToRgbConversionMatrix;
+  GammaTransferParams gammaDecodeParams;
+  GammaTransferParams gammaEncodeParams;
+  tint_array<tint_packed_vec3_f32_array_element, 3> gamutConversionMatrix;
+  float3x2 coordTransformationMatrix;
+};
+
 struct ExternalTextureParams {
   uint numPlanes;
   uint doYuvToRgbConversionOnly;
diff --git a/test/tint/builtins/gen/var/textureLoad/1bfdfb.wgsl.expected.msl b/test/tint/builtins/gen/var/textureLoad/1bfdfb.wgsl.expected.msl
index 64cfbf5..97af0a7 100644
--- a/test/tint/builtins/gen/var/textureLoad/1bfdfb.wgsl.expected.msl
+++ b/test/tint/builtins/gen/var/textureLoad/1bfdfb.wgsl.expected.msl
@@ -14,6 +14,11 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
 struct GammaTransferParams {
   /* 0x0000 */ float G;
   /* 0x0004 */ float A;
@@ -25,18 +30,48 @@
   /* 0x001c */ uint padding;
 };
 
-struct ExternalTextureParams {
+struct ExternalTextureParams_tint_packed_vec3 {
   /* 0x0000 */ uint numPlanes;
   /* 0x0004 */ uint doYuvToRgbConversionOnly;
-  /* 0x0008 */ tint_array<int8_t, 8> tint_pad;
+  /* 0x0008 */ tint_array<int8_t, 8> tint_pad_1;
   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix;
   /* 0x0040 */ GammaTransferParams gammaDecodeParams;
   /* 0x0060 */ GammaTransferParams gammaEncodeParams;
-  /* 0x0080 */ float3x3 gamutConversionMatrix;
+  /* 0x0080 */ tint_array<tint_packed_vec3_f32_array_element, 3> gamutConversionMatrix;
   /* 0x00b0 */ float3x2 coordTransformationMatrix;
-  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_2;
 };
 
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct ExternalTextureParams {
+  uint numPlanes;
+  uint doYuvToRgbConversionOnly;
+  float3x4 yuvToRgbConversionMatrix;
+  GammaTransferParams gammaDecodeParams;
+  GammaTransferParams gammaEncodeParams;
+  float3x3 gamutConversionMatrix;
+  float3x2 coordTransformationMatrix;
+};
+
+ExternalTextureParams tint_unpack_vec3_in_composite_1(ExternalTextureParams_tint_packed_vec3 in) {
+  ExternalTextureParams result = {};
+  result.numPlanes = in.numPlanes;
+  result.doYuvToRgbConversionOnly = in.doYuvToRgbConversionOnly;
+  result.yuvToRgbConversionMatrix = in.yuvToRgbConversionMatrix;
+  result.gammaDecodeParams = in.gammaDecodeParams;
+  result.gammaEncodeParams = in.gammaEncodeParams;
+  result.gamutConversionMatrix = tint_unpack_vec3_in_composite(in.gamutConversionMatrix);
+  result.coordTransformationMatrix = in.coordTransformationMatrix;
+  return result;
+}
+
 float3 gammaCorrection(float3 v, GammaTransferParams params) {
   bool3 const cond = (fabs(v) < float3(params.D));
   float3 const t = (sign(v) * ((params.C * fabs(v)) + params.F));
@@ -48,9 +83,9 @@
   uint2 const coord1 = (coord >> uint2(1u));
   float3 color = 0.0f;
   if ((params.numPlanes == 1u)) {
-    color = float4(plane0.read(uint2(coord), 0)).rgb;
+    color = plane0.read(uint2(coord), 0).rgb;
   } else {
-    color = (float4(plane0.read(uint2(coord), 0)[0], float4(plane1.read(uint2(coord1), 0)).rg, 1.0f) * params.yuvToRgbConversionMatrix);
+    color = (float4(plane0.read(uint2(coord), 0)[0], plane1.read(uint2(coord1), 0).rg, 1.0f) * params.yuvToRgbConversionMatrix);
   }
   if ((params.doYuvToRgbConversionOnly == 0u)) {
     color = gammaCorrection(color, params.gammaDecodeParams);
@@ -60,33 +95,33 @@
   return float4(color, 1.0f);
 }
 
-void textureLoad_1bfdfb(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, const constant ExternalTextureParams* const tint_symbol_3) {
+void textureLoad_1bfdfb(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_3) {
   uint2 arg_1 = uint2(1u);
-  float4 res = textureLoadExternal(tint_symbol_1, tint_symbol_2, arg_1, *(tint_symbol_3));
+  float4 res = textureLoadExternal(tint_symbol_1, tint_symbol_2, arg_1, tint_unpack_vec3_in_composite_1(*(tint_symbol_3)));
 }
 
 struct tint_symbol {
   float4 value [[position]];
 };
 
-float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_4, texture2d<float, access::sample> tint_symbol_5, const constant ExternalTextureParams* const tint_symbol_6) {
+float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_4, texture2d<float, access::sample> tint_symbol_5, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_6) {
   textureLoad_1bfdfb(tint_symbol_4, tint_symbol_5, tint_symbol_6);
   return float4(0.0f);
 }
 
-vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_7 [[texture(0)]], texture2d<float, access::sample> tint_symbol_8 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_9 [[buffer(2)]]) {
+vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_7 [[texture(0)]], texture2d<float, access::sample> tint_symbol_8 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_9 [[buffer(2)]]) {
   float4 const inner_result = vertex_main_inner(tint_symbol_7, tint_symbol_8, tint_symbol_9);
   tint_symbol wrapper_result = {};
   wrapper_result.value = inner_result;
   return wrapper_result;
 }
 
-fragment void fragment_main(texture2d<float, access::sample> tint_symbol_10 [[texture(0)]], texture2d<float, access::sample> tint_symbol_11 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_12 [[buffer(2)]]) {
+fragment void fragment_main(texture2d<float, access::sample> tint_symbol_10 [[texture(0)]], texture2d<float, access::sample> tint_symbol_11 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_12 [[buffer(2)]]) {
   textureLoad_1bfdfb(tint_symbol_10, tint_symbol_11, tint_symbol_12);
   return;
 }
 
-kernel void compute_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_15 [[buffer(2)]]) {
+kernel void compute_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_15 [[buffer(2)]]) {
   textureLoad_1bfdfb(tint_symbol_13, tint_symbol_14, tint_symbol_15);
   return;
 }
diff --git a/test/tint/builtins/gen/var/textureLoad/8acf41.wgsl.expected.msl b/test/tint/builtins/gen/var/textureLoad/8acf41.wgsl.expected.msl
index b3cf490..5fae152 100644
--- a/test/tint/builtins/gen/var/textureLoad/8acf41.wgsl.expected.msl
+++ b/test/tint/builtins/gen/var/textureLoad/8acf41.wgsl.expected.msl
@@ -14,6 +14,11 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
 struct GammaTransferParams {
   /* 0x0000 */ float G;
   /* 0x0004 */ float A;
@@ -25,18 +30,48 @@
   /* 0x001c */ uint padding;
 };
 
-struct ExternalTextureParams {
+struct ExternalTextureParams_tint_packed_vec3 {
   /* 0x0000 */ uint numPlanes;
   /* 0x0004 */ uint doYuvToRgbConversionOnly;
-  /* 0x0008 */ tint_array<int8_t, 8> tint_pad;
+  /* 0x0008 */ tint_array<int8_t, 8> tint_pad_1;
   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix;
   /* 0x0040 */ GammaTransferParams gammaDecodeParams;
   /* 0x0060 */ GammaTransferParams gammaEncodeParams;
-  /* 0x0080 */ float3x3 gamutConversionMatrix;
+  /* 0x0080 */ tint_array<tint_packed_vec3_f32_array_element, 3> gamutConversionMatrix;
   /* 0x00b0 */ float3x2 coordTransformationMatrix;
-  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_2;
 };
 
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct ExternalTextureParams {
+  uint numPlanes;
+  uint doYuvToRgbConversionOnly;
+  float3x4 yuvToRgbConversionMatrix;
+  GammaTransferParams gammaDecodeParams;
+  GammaTransferParams gammaEncodeParams;
+  float3x3 gamutConversionMatrix;
+  float3x2 coordTransformationMatrix;
+};
+
+ExternalTextureParams tint_unpack_vec3_in_composite_1(ExternalTextureParams_tint_packed_vec3 in) {
+  ExternalTextureParams result = {};
+  result.numPlanes = in.numPlanes;
+  result.doYuvToRgbConversionOnly = in.doYuvToRgbConversionOnly;
+  result.yuvToRgbConversionMatrix = in.yuvToRgbConversionMatrix;
+  result.gammaDecodeParams = in.gammaDecodeParams;
+  result.gammaEncodeParams = in.gammaEncodeParams;
+  result.gamutConversionMatrix = tint_unpack_vec3_in_composite(in.gamutConversionMatrix);
+  result.coordTransformationMatrix = in.coordTransformationMatrix;
+  return result;
+}
+
 float3 gammaCorrection(float3 v, GammaTransferParams params) {
   bool3 const cond = (fabs(v) < float3(params.D));
   float3 const t = (sign(v) * ((params.C * fabs(v)) + params.F));
@@ -48,9 +83,9 @@
   int2 const coord1 = (coord >> uint2(1u));
   float3 color = 0.0f;
   if ((params.numPlanes == 1u)) {
-    color = float4(plane0.read(uint2(coord), 0)).rgb;
+    color = plane0.read(uint2(coord), 0).rgb;
   } else {
-    color = (float4(plane0.read(uint2(coord), 0)[0], float4(plane1.read(uint2(coord1), 0)).rg, 1.0f) * params.yuvToRgbConversionMatrix);
+    color = (float4(plane0.read(uint2(coord), 0)[0], plane1.read(uint2(coord1), 0).rg, 1.0f) * params.yuvToRgbConversionMatrix);
   }
   if ((params.doYuvToRgbConversionOnly == 0u)) {
     color = gammaCorrection(color, params.gammaDecodeParams);
@@ -60,33 +95,33 @@
   return float4(color, 1.0f);
 }
 
-void textureLoad_8acf41(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, const constant ExternalTextureParams* const tint_symbol_3) {
+void textureLoad_8acf41(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_3) {
   int2 arg_1 = int2(1);
-  float4 res = textureLoadExternal(tint_symbol_1, tint_symbol_2, arg_1, *(tint_symbol_3));
+  float4 res = textureLoadExternal(tint_symbol_1, tint_symbol_2, arg_1, tint_unpack_vec3_in_composite_1(*(tint_symbol_3)));
 }
 
 struct tint_symbol {
   float4 value [[position]];
 };
 
-float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_4, texture2d<float, access::sample> tint_symbol_5, const constant ExternalTextureParams* const tint_symbol_6) {
+float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_4, texture2d<float, access::sample> tint_symbol_5, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_6) {
   textureLoad_8acf41(tint_symbol_4, tint_symbol_5, tint_symbol_6);
   return float4(0.0f);
 }
 
-vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_7 [[texture(0)]], texture2d<float, access::sample> tint_symbol_8 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_9 [[buffer(2)]]) {
+vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_7 [[texture(0)]], texture2d<float, access::sample> tint_symbol_8 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_9 [[buffer(2)]]) {
   float4 const inner_result = vertex_main_inner(tint_symbol_7, tint_symbol_8, tint_symbol_9);
   tint_symbol wrapper_result = {};
   wrapper_result.value = inner_result;
   return wrapper_result;
 }
 
-fragment void fragment_main(texture2d<float, access::sample> tint_symbol_10 [[texture(0)]], texture2d<float, access::sample> tint_symbol_11 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_12 [[buffer(2)]]) {
+fragment void fragment_main(texture2d<float, access::sample> tint_symbol_10 [[texture(0)]], texture2d<float, access::sample> tint_symbol_11 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_12 [[buffer(2)]]) {
   textureLoad_8acf41(tint_symbol_10, tint_symbol_11, tint_symbol_12);
   return;
 }
 
-kernel void compute_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_15 [[buffer(2)]]) {
+kernel void compute_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_15 [[buffer(2)]]) {
   textureLoad_8acf41(tint_symbol_13, tint_symbol_14, tint_symbol_15);
   return;
 }
diff --git a/test/tint/builtins/gen/var/textureSampleBaseClampToEdge/7c04e6.wgsl.expected.msl b/test/tint/builtins/gen/var/textureSampleBaseClampToEdge/7c04e6.wgsl.expected.msl
index 822c1b2..d0d9b1d 100644
--- a/test/tint/builtins/gen/var/textureSampleBaseClampToEdge/7c04e6.wgsl.expected.msl
+++ b/test/tint/builtins/gen/var/textureSampleBaseClampToEdge/7c04e6.wgsl.expected.msl
@@ -14,6 +14,11 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
 struct GammaTransferParams {
   /* 0x0000 */ float G;
   /* 0x0004 */ float A;
@@ -25,18 +30,48 @@
   /* 0x001c */ uint padding;
 };
 
-struct ExternalTextureParams {
+struct ExternalTextureParams_tint_packed_vec3 {
   /* 0x0000 */ uint numPlanes;
   /* 0x0004 */ uint doYuvToRgbConversionOnly;
-  /* 0x0008 */ tint_array<int8_t, 8> tint_pad;
+  /* 0x0008 */ tint_array<int8_t, 8> tint_pad_1;
   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix;
   /* 0x0040 */ GammaTransferParams gammaDecodeParams;
   /* 0x0060 */ GammaTransferParams gammaEncodeParams;
-  /* 0x0080 */ float3x3 gamutConversionMatrix;
+  /* 0x0080 */ tint_array<tint_packed_vec3_f32_array_element, 3> gamutConversionMatrix;
   /* 0x00b0 */ float3x2 coordTransformationMatrix;
-  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_2;
 };
 
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct ExternalTextureParams {
+  uint numPlanes;
+  uint doYuvToRgbConversionOnly;
+  float3x4 yuvToRgbConversionMatrix;
+  GammaTransferParams gammaDecodeParams;
+  GammaTransferParams gammaEncodeParams;
+  float3x3 gamutConversionMatrix;
+  float3x2 coordTransformationMatrix;
+};
+
+ExternalTextureParams tint_unpack_vec3_in_composite_1(ExternalTextureParams_tint_packed_vec3 in) {
+  ExternalTextureParams result = {};
+  result.numPlanes = in.numPlanes;
+  result.doYuvToRgbConversionOnly = in.doYuvToRgbConversionOnly;
+  result.yuvToRgbConversionMatrix = in.yuvToRgbConversionMatrix;
+  result.gammaDecodeParams = in.gammaDecodeParams;
+  result.gammaEncodeParams = in.gammaEncodeParams;
+  result.gamutConversionMatrix = tint_unpack_vec3_in_composite(in.gamutConversionMatrix);
+  result.coordTransformationMatrix = in.coordTransformationMatrix;
+  return result;
+}
+
 float3 gammaCorrection(float3 v, GammaTransferParams params) {
   bool3 const cond = (fabs(v) < float3(params.D));
   float3 const t = (sign(v) * ((params.C * fabs(v)) + params.F));
@@ -54,9 +89,9 @@
   float2 const plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1.0f - plane1_half_texel));
   float3 color = 0.0f;
   if ((params.numPlanes == 1u)) {
-    color = float4(plane0.sample(smp, plane0_clamped, level(0.0f))).rgb;
+    color = plane0.sample(smp, plane0_clamped, level(0.0f)).rgb;
   } else {
-    color = (float4(plane0.sample(smp, plane0_clamped, level(0.0f))[0], float4(plane1.sample(smp, plane1_clamped, level(0.0f))).rg, 1.0f) * params.yuvToRgbConversionMatrix);
+    color = (float4(plane0.sample(smp, plane0_clamped, level(0.0f))[0], plane1.sample(smp, plane1_clamped, level(0.0f)).rg, 1.0f) * params.yuvToRgbConversionMatrix);
   }
   if ((params.doYuvToRgbConversionOnly == 0u)) {
     color = gammaCorrection(color, params.gammaDecodeParams);
@@ -66,33 +101,33 @@
   return float4(color, 1.0f);
 }
 
-void textureSampleBaseClampToEdge_7c04e6(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, sampler tint_symbol_3, const constant ExternalTextureParams* const tint_symbol_4) {
+void textureSampleBaseClampToEdge_7c04e6(texture2d<float, access::sample> tint_symbol_1, texture2d<float, access::sample> tint_symbol_2, sampler tint_symbol_3, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_4) {
   float2 arg_2 = float2(1.0f);
-  float4 res = textureSampleExternal(tint_symbol_1, tint_symbol_2, tint_symbol_3, arg_2, *(tint_symbol_4));
+  float4 res = textureSampleExternal(tint_symbol_1, tint_symbol_2, tint_symbol_3, arg_2, tint_unpack_vec3_in_composite_1(*(tint_symbol_4)));
 }
 
 struct tint_symbol {
   float4 value [[position]];
 };
 
-float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_5, texture2d<float, access::sample> tint_symbol_6, sampler tint_symbol_7, const constant ExternalTextureParams* const tint_symbol_8) {
+float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_5, texture2d<float, access::sample> tint_symbol_6, sampler tint_symbol_7, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_8) {
   textureSampleBaseClampToEdge_7c04e6(tint_symbol_5, tint_symbol_6, tint_symbol_7, tint_symbol_8);
   return float4(0.0f);
 }
 
-vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_9 [[texture(0)]], texture2d<float, access::sample> tint_symbol_10 [[texture(1)]], sampler tint_symbol_11 [[sampler(0)]], const constant ExternalTextureParams* tint_symbol_12 [[buffer(2)]]) {
+vertex tint_symbol vertex_main(texture2d<float, access::sample> tint_symbol_9 [[texture(0)]], texture2d<float, access::sample> tint_symbol_10 [[texture(1)]], sampler tint_symbol_11 [[sampler(0)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_12 [[buffer(2)]]) {
   float4 const inner_result = vertex_main_inner(tint_symbol_9, tint_symbol_10, tint_symbol_11, tint_symbol_12);
   tint_symbol wrapper_result = {};
   wrapper_result.value = inner_result;
   return wrapper_result;
 }
 
-fragment void fragment_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], sampler tint_symbol_15 [[sampler(0)]], const constant ExternalTextureParams* tint_symbol_16 [[buffer(2)]]) {
+fragment void fragment_main(texture2d<float, access::sample> tint_symbol_13 [[texture(0)]], texture2d<float, access::sample> tint_symbol_14 [[texture(1)]], sampler tint_symbol_15 [[sampler(0)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_16 [[buffer(2)]]) {
   textureSampleBaseClampToEdge_7c04e6(tint_symbol_13, tint_symbol_14, tint_symbol_15, tint_symbol_16);
   return;
 }
 
-kernel void compute_main(texture2d<float, access::sample> tint_symbol_17 [[texture(0)]], texture2d<float, access::sample> tint_symbol_18 [[texture(1)]], sampler tint_symbol_19 [[sampler(0)]], const constant ExternalTextureParams* tint_symbol_20 [[buffer(2)]]) {
+kernel void compute_main(texture2d<float, access::sample> tint_symbol_17 [[texture(0)]], texture2d<float, access::sample> tint_symbol_18 [[texture(1)]], sampler tint_symbol_19 [[sampler(0)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_20 [[buffer(2)]]) {
   textureSampleBaseClampToEdge_7c04e6(tint_symbol_17, tint_symbol_18, tint_symbol_19, tint_symbol_20);
   return;
 }
diff --git a/test/tint/builtins/textureLoad/texture_external_param.wgsl.expected.msl b/test/tint/builtins/textureLoad/texture_external_param.wgsl.expected.msl
index 0c67e8f..08cc5d5 100644
--- a/test/tint/builtins/textureLoad/texture_external_param.wgsl.expected.msl
+++ b/test/tint/builtins/textureLoad/texture_external_param.wgsl.expected.msl
@@ -14,6 +14,11 @@
     T elements[N];
 };
 
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
 struct GammaTransferParams {
   /* 0x0000 */ float G;
   /* 0x0004 */ float A;
@@ -25,18 +30,48 @@
   /* 0x001c */ uint padding;
 };
 
-struct ExternalTextureParams {
+struct ExternalTextureParams_tint_packed_vec3 {
   /* 0x0000 */ uint numPlanes;
   /* 0x0004 */ uint doYuvToRgbConversionOnly;
-  /* 0x0008 */ tint_array<int8_t, 8> tint_pad;
+  /* 0x0008 */ tint_array<int8_t, 8> tint_pad_1;
   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix;
   /* 0x0040 */ GammaTransferParams gammaDecodeParams;
   /* 0x0060 */ GammaTransferParams gammaEncodeParams;
-  /* 0x0080 */ float3x3 gamutConversionMatrix;
+  /* 0x0080 */ tint_array<tint_packed_vec3_f32_array_element, 3> gamutConversionMatrix;
   /* 0x00b0 */ float3x2 coordTransformationMatrix;
-  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_1;
+  /* 0x00c8 */ tint_array<int8_t, 8> tint_pad_2;
 };
 
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct ExternalTextureParams {
+  uint numPlanes;
+  uint doYuvToRgbConversionOnly;
+  float3x4 yuvToRgbConversionMatrix;
+  GammaTransferParams gammaDecodeParams;
+  GammaTransferParams gammaEncodeParams;
+  float3x3 gamutConversionMatrix;
+  float3x2 coordTransformationMatrix;
+};
+
+ExternalTextureParams tint_unpack_vec3_in_composite_1(ExternalTextureParams_tint_packed_vec3 in) {
+  ExternalTextureParams result = {};
+  result.numPlanes = in.numPlanes;
+  result.doYuvToRgbConversionOnly = in.doYuvToRgbConversionOnly;
+  result.yuvToRgbConversionMatrix = in.yuvToRgbConversionMatrix;
+  result.gammaDecodeParams = in.gammaDecodeParams;
+  result.gammaEncodeParams = in.gammaEncodeParams;
+  result.gamutConversionMatrix = tint_unpack_vec3_in_composite(in.gamutConversionMatrix);
+  result.coordTransformationMatrix = in.coordTransformationMatrix;
+  return result;
+}
+
 float3 gammaCorrection(float3 v, GammaTransferParams params) {
   bool3 const cond = (fabs(v) < float3(params.D));
   float3 const t = (sign(v) * ((params.C * fabs(v)) + params.F));
@@ -48,9 +83,9 @@
   int2 const coord1 = (coord >> uint2(1u));
   float3 color = 0.0f;
   if ((params.numPlanes == 1u)) {
-    color = float4(plane0.read(uint2(coord), 0)).rgb;
+    color = plane0.read(uint2(coord), 0).rgb;
   } else {
-    color = (float4(plane0.read(uint2(coord), 0)[0], float4(plane1.read(uint2(coord1), 0)).rg, 1.0f) * params.yuvToRgbConversionMatrix);
+    color = (float4(plane0.read(uint2(coord), 0)[0], plane1.read(uint2(coord1), 0).rg, 1.0f) * params.yuvToRgbConversionMatrix);
   }
   if ((params.doYuvToRgbConversionOnly == 0u)) {
     color = gammaCorrection(color, params.gammaDecodeParams);
@@ -64,32 +99,32 @@
   return textureLoadExternal(tint_symbol, ext_tex_plane_1_1, coords, ext_tex_params_1);
 }
 
-void doTextureLoad(texture2d<float, access::sample> tint_symbol_2, texture2d<float, access::sample> tint_symbol_3, const constant ExternalTextureParams* const tint_symbol_4) {
-  float4 res = textureLoad2d(tint_symbol_2, tint_symbol_3, *(tint_symbol_4), int2(0));
+void doTextureLoad(texture2d<float, access::sample> tint_symbol_2, texture2d<float, access::sample> tint_symbol_3, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_4) {
+  float4 res = textureLoad2d(tint_symbol_2, tint_symbol_3, tint_unpack_vec3_in_composite_1(*(tint_symbol_4)), int2(0));
 }
 
 struct tint_symbol_1 {
   float4 value [[position]];
 };
 
-float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_5, texture2d<float, access::sample> tint_symbol_6, const constant ExternalTextureParams* const tint_symbol_7) {
+float4 vertex_main_inner(texture2d<float, access::sample> tint_symbol_5, texture2d<float, access::sample> tint_symbol_6, const constant ExternalTextureParams_tint_packed_vec3* const tint_symbol_7) {
   doTextureLoad(tint_symbol_5, tint_symbol_6, tint_symbol_7);
   return float4(0.0f);
 }
 
-vertex tint_symbol_1 vertex_main(texture2d<float, access::sample> tint_symbol_8 [[texture(0)]], texture2d<float, access::sample> tint_symbol_9 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_10 [[buffer(2)]]) {
+vertex tint_symbol_1 vertex_main(texture2d<float, access::sample> tint_symbol_8 [[texture(0)]], texture2d<float, access::sample> tint_symbol_9 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_10 [[buffer(2)]]) {
   float4 const inner_result = vertex_main_inner(tint_symbol_8, tint_symbol_9, tint_symbol_10);
   tint_symbol_1 wrapper_result = {};
   wrapper_result.value = inner_result;
   return wrapper_result;
 }
 
-fragment void fragment_main(texture2d<float, access::sample> tint_symbol_11 [[texture(0)]], texture2d<float, access::sample> tint_symbol_12 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_13 [[buffer(2)]]) {
+fragment void fragment_main(texture2d<float, access::sample> tint_symbol_11 [[texture(0)]], texture2d<float, access::sample> tint_symbol_12 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_13 [[buffer(2)]]) {
   doTextureLoad(tint_symbol_11, tint_symbol_12, tint_symbol_13);
   return;
 }
 
-kernel void compute_main(texture2d<float, access::sample> tint_symbol_14 [[texture(0)]], texture2d<float, access::sample> tint_symbol_15 [[texture(1)]], const constant ExternalTextureParams* tint_symbol_16 [[buffer(2)]]) {
+kernel void compute_main(texture2d<float, access::sample> tint_symbol_14 [[texture(0)]], texture2d<float, access::sample> tint_symbol_15 [[texture(1)]], const constant ExternalTextureParams_tint_packed_vec3* tint_symbol_16 [[buffer(2)]]) {
   doTextureLoad(tint_symbol_14, tint_symbol_15, tint_symbol_16);
   return;
 }
diff --git a/test/tint/expressions/binary/mul/mat3x2-vec3/f16.wgsl.expected.msl b/test/tint/expressions/binary/mul/mat3x2-vec3/f16.wgsl.expected.msl
index 779a708..2354c39 100644
--- a/test/tint/expressions/binary/mul/mat3x2-vec3/f16.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/mat3x2-vec3/f16.wgsl.expected.msl
@@ -14,14 +14,19 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ half3x2 tint_symbol;
   /* 0x000c */ tint_array<int8_t, 4> tint_pad;
   /* 0x0010 */ packed_half3 vector;
   /* 0x0016 */ tint_array<int8_t, 2> tint_pad_1;
 };
 
-fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
+struct S {
+  half3x2 tint_symbol;
+  half3 vector;
+};
+
+fragment void tint_symbol_1(const constant S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]]) {
   half2 const x = ((*(tint_symbol_2)).tint_symbol * half3((*(tint_symbol_2)).vector));
   return;
 }
diff --git a/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.msl b/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.msl
index a36de59..c6688f1 100644
--- a/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.msl
@@ -14,14 +14,19 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ float3x2 tint_symbol;
   /* 0x0018 */ tint_array<int8_t, 8> tint_pad;
   /* 0x0020 */ packed_float3 vector;
   /* 0x002c */ tint_array<int8_t, 4> tint_pad_1;
 };
 
-fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
+struct S {
+  float3x2 tint_symbol;
+  float3 vector;
+};
+
+fragment void tint_symbol_1(const constant S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]]) {
   float2 const x = ((*(tint_symbol_2)).tint_symbol * float3((*(tint_symbol_2)).vector));
   return;
 }
diff --git a/test/tint/expressions/binary/mul/mat3x3-vec3/f16.wgsl.expected.msl b/test/tint/expressions/binary/mul/mat3x3-vec3/f16.wgsl.expected.msl
index 9c67a7c..ff9f1c6 100644
--- a/test/tint/expressions/binary/mul/mat3x3-vec3/f16.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/mat3x3-vec3/f16.wgsl.expected.msl
@@ -14,14 +14,32 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ half3x3 tint_symbol;
-  /* 0x0018 */ packed_half3 vector;
-  /* 0x001e */ tint_array<int8_t, 2> tint_pad;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
-  half3 const x = ((*(tint_symbol_2)).tint_symbol * half3((*(tint_symbol_2)).vector));
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f16_array_element, 3> tint_symbol;
+  /* 0x0018 */ packed_half3 vector;
+  /* 0x001e */ tint_array<int8_t, 2> tint_pad_1;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  half3x3 tint_symbol;
+  half3 vector;
+};
+
+fragment void tint_symbol_1(const constant S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]]) {
+  half3 const x = (tint_unpack_vec3_in_composite((*(tint_symbol_2)).tint_symbol) * half3((*(tint_symbol_2)).vector));
   return;
 }
 
diff --git a/test/tint/expressions/binary/mul/mat3x3-vec3/f32.wgsl.expected.msl b/test/tint/expressions/binary/mul/mat3x3-vec3/f32.wgsl.expected.msl
index 79c3e09..539e4ab 100644
--- a/test/tint/expressions/binary/mul/mat3x3-vec3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/mat3x3-vec3/f32.wgsl.expected.msl
@@ -14,14 +14,32 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ float3x3 tint_symbol;
-  /* 0x0030 */ packed_float3 vector;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
-  float3 const x = ((*(tint_symbol_2)).tint_symbol * float3((*(tint_symbol_2)).vector));
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f32_array_element, 3> tint_symbol;
+  /* 0x0030 */ packed_float3 vector;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_1;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  float3x3 tint_symbol;
+  float3 vector;
+};
+
+fragment void tint_symbol_1(const constant S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]]) {
+  float3 const x = (tint_unpack_vec3_in_composite((*(tint_symbol_2)).tint_symbol) * float3((*(tint_symbol_2)).vector));
   return;
 }
 
diff --git a/test/tint/expressions/binary/mul/vec3-mat3x3/f16.wgsl.expected.msl b/test/tint/expressions/binary/mul/vec3-mat3x3/f16.wgsl.expected.msl
index 1d92d8d..a1a9592 100644
--- a/test/tint/expressions/binary/mul/vec3-mat3x3/f16.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/vec3-mat3x3/f16.wgsl.expected.msl
@@ -14,14 +14,32 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ half3x3 tint_symbol;
-  /* 0x0018 */ packed_half3 vector;
-  /* 0x001e */ tint_array<int8_t, 2> tint_pad;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
-  half3 const x = (half3((*(tint_symbol_2)).vector) * (*(tint_symbol_2)).tint_symbol);
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f16_array_element, 3> tint_symbol;
+  /* 0x0018 */ packed_half3 vector;
+  /* 0x001e */ tint_array<int8_t, 2> tint_pad_1;
+};
+
+half3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 3> in) {
+  half3x3 result = half3x3(0.0h);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  half3x3 tint_symbol;
+  half3 vector;
+};
+
+fragment void tint_symbol_1(const constant S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]]) {
+  half3 const x = (half3((*(tint_symbol_2)).vector) * tint_unpack_vec3_in_composite((*(tint_symbol_2)).tint_symbol));
   return;
 }
 
diff --git a/test/tint/expressions/binary/mul/vec3-mat3x3/f32.wgsl.expected.msl b/test/tint/expressions/binary/mul/vec3-mat3x3/f32.wgsl.expected.msl
index 321a379..a982edf 100644
--- a/test/tint/expressions/binary/mul/vec3-mat3x3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/vec3-mat3x3/f32.wgsl.expected.msl
@@ -14,14 +14,32 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ float3x3 tint_symbol;
-  /* 0x0030 */ packed_float3 vector;
-  /* 0x003c */ tint_array<int8_t, 4> tint_pad;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
-  float3 const x = (float3((*(tint_symbol_2)).vector) * (*(tint_symbol_2)).tint_symbol);
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f32_array_element, 3> tint_symbol;
+  /* 0x0030 */ packed_float3 vector;
+  /* 0x003c */ tint_array<int8_t, 4> tint_pad_1;
+};
+
+float3x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
+  float3x3 result = float3x3(0.0f);
+  for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  float3x3 tint_symbol;
+  float3 vector;
+};
+
+fragment void tint_symbol_1(const constant S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]]) {
+  float3 const x = (float3((*(tint_symbol_2)).vector) * tint_unpack_vec3_in_composite((*(tint_symbol_2)).tint_symbol));
   return;
 }
 
diff --git a/test/tint/expressions/binary/mul/vec3-mat4x3/f16.wgsl.expected.msl b/test/tint/expressions/binary/mul/vec3-mat4x3/f16.wgsl.expected.msl
index d311e88..571c316 100644
--- a/test/tint/expressions/binary/mul/vec3-mat4x3/f16.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/vec3-mat4x3/f16.wgsl.expected.msl
@@ -14,14 +14,32 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ half4x3 tint_symbol;
-  /* 0x0020 */ packed_half3 vector;
-  /* 0x0026 */ tint_array<int8_t, 2> tint_pad;
+struct tint_packed_vec3_f16_array_element {
+  /* 0x0000 */ packed_half3 elements;
+  /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
-  half4 const x = (half3((*(tint_symbol_2)).vector) * (*(tint_symbol_2)).tint_symbol);
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f16_array_element, 4> tint_symbol;
+  /* 0x0020 */ packed_half3 vector;
+  /* 0x0026 */ tint_array<int8_t, 2> tint_pad_1;
+};
+
+half4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f16_array_element, 4> in) {
+  half4x3 result = half4x3(0.0h);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = half3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  half4x3 tint_symbol;
+  half3 vector;
+};
+
+fragment void tint_symbol_1(const constant S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]]) {
+  half4 const x = (half3((*(tint_symbol_2)).vector) * tint_unpack_vec3_in_composite((*(tint_symbol_2)).tint_symbol));
   return;
 }
 
diff --git a/test/tint/expressions/binary/mul/vec3-mat4x3/f32.wgsl.expected.msl b/test/tint/expressions/binary/mul/vec3-mat4x3/f32.wgsl.expected.msl
index b1f6165..420b7aa 100644
--- a/test/tint/expressions/binary/mul/vec3-mat4x3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/vec3-mat4x3/f32.wgsl.expected.msl
@@ -14,14 +14,32 @@
     T elements[N];
 };
 
-struct S {
-  /* 0x0000 */ float4x3 tint_symbol;
-  /* 0x0040 */ packed_float3 vector;
-  /* 0x004c */ tint_array<int8_t, 4> tint_pad;
+struct tint_packed_vec3_f32_array_element {
+  /* 0x0000 */ packed_float3 elements;
+  /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
-  float4 const x = (float3((*(tint_symbol_2)).vector) * (*(tint_symbol_2)).tint_symbol);
+struct S_tint_packed_vec3 {
+  /* 0x0000 */ tint_array<tint_packed_vec3_f32_array_element, 4> tint_symbol;
+  /* 0x0040 */ packed_float3 vector;
+  /* 0x004c */ tint_array<int8_t, 4> tint_pad_1;
+};
+
+float4x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
+  float4x3 result = float4x3(0.0f);
+  for(uint i = 0u; (i < 4u); i = (i + 1u)) {
+    result[i] = float3(in[i].elements);
+  }
+  return result;
+}
+
+struct S {
+  float4x3 tint_symbol;
+  float3 vector;
+};
+
+fragment void tint_symbol_1(const constant S_tint_packed_vec3* tint_symbol_2 [[buffer(0)]]) {
+  float4 const x = (float3((*(tint_symbol_2)).vector) * tint_unpack_vec3_in_composite((*(tint_symbol_2)).tint_symbol));
   return;
 }
 
diff --git a/test/tint/expressions/swizzle/read/packed_vec3/f16.wgsl.expected.msl b/test/tint/expressions/swizzle/read/packed_vec3/f16.wgsl.expected.msl
index ab91c3e..7c601f0 100644
--- a/test/tint/expressions/swizzle/read/packed_vec3/f16.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/packed_vec3/f16.wgsl.expected.msl
@@ -14,12 +14,16 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ packed_half3 v;
   /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-void f(const constant S* const tint_symbol) {
+struct S {
+  half3 v;
+};
+
+void f(const constant S_tint_packed_vec3* const tint_symbol) {
   half3 v = half3((*(tint_symbol)).v);
   half x = (*(tint_symbol)).v[0];
   half y = (*(tint_symbol)).v[1];
diff --git a/test/tint/expressions/swizzle/read/packed_vec3/f32.wgsl.expected.msl b/test/tint/expressions/swizzle/read/packed_vec3/f32.wgsl.expected.msl
index 1974ac0..e9631d5 100644
--- a/test/tint/expressions/swizzle/read/packed_vec3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/packed_vec3/f32.wgsl.expected.msl
@@ -14,12 +14,16 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ packed_float3 v;
   /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-void f(const constant S* const tint_symbol) {
+struct S {
+  float3 v;
+};
+
+void f(const constant S_tint_packed_vec3* const tint_symbol) {
   float3 v = float3((*(tint_symbol)).v);
   float x = (*(tint_symbol)).v[0];
   float y = (*(tint_symbol)).v[1];
diff --git a/test/tint/expressions/swizzle/read/packed_vec3/i32.wgsl.expected.msl b/test/tint/expressions/swizzle/read/packed_vec3/i32.wgsl.expected.msl
index cfabec5..d50a90e 100644
--- a/test/tint/expressions/swizzle/read/packed_vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/packed_vec3/i32.wgsl.expected.msl
@@ -14,12 +14,16 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ packed_int3 v;
   /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-void f(const constant S* const tint_symbol) {
+struct S {
+  int3 v;
+};
+
+void f(const constant S_tint_packed_vec3* const tint_symbol) {
   int3 v = int3((*(tint_symbol)).v);
   int x = (*(tint_symbol)).v[0];
   int y = (*(tint_symbol)).v[1];
diff --git a/test/tint/expressions/swizzle/read/packed_vec3/u32.wgsl.expected.msl b/test/tint/expressions/swizzle/read/packed_vec3/u32.wgsl.expected.msl
index 3f1899c..a0a8f84 100644
--- a/test/tint/expressions/swizzle/read/packed_vec3/u32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/packed_vec3/u32.wgsl.expected.msl
@@ -14,12 +14,16 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ packed_uint3 v;
   /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-void f(const constant S* const tint_symbol) {
+struct S {
+  uint3 v;
+};
+
+void f(const constant S_tint_packed_vec3* const tint_symbol) {
   uint3 v = uint3((*(tint_symbol)).v);
   uint x = (*(tint_symbol)).v[0];
   uint y = (*(tint_symbol)).v[1];
diff --git a/test/tint/expressions/swizzle/read/vec3/f16.wgsl.expected.msl b/test/tint/expressions/swizzle/read/vec3/f16.wgsl.expected.msl
index 4ea8f92..4650bf0 100644
--- a/test/tint/expressions/swizzle/read/vec3/f16.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/vec3/f16.wgsl.expected.msl
@@ -11,122 +11,122 @@
   half x = tint_symbol.v[0];
   half y = tint_symbol.v[1];
   half z = tint_symbol.v[2];
-  half2 xx = half3(tint_symbol.v).xx;
-  half2 xy = half3(tint_symbol.v).xy;
-  half2 xz = half3(tint_symbol.v).xz;
-  half2 yx = half3(tint_symbol.v).yx;
-  half2 yy = half3(tint_symbol.v).yy;
-  half2 yz = half3(tint_symbol.v).yz;
-  half2 zx = half3(tint_symbol.v).zx;
-  half2 zy = half3(tint_symbol.v).zy;
-  half2 zz = half3(tint_symbol.v).zz;
-  half3 xxx = half3(tint_symbol.v).xxx;
-  half3 xxy = half3(tint_symbol.v).xxy;
-  half3 xxz = half3(tint_symbol.v).xxz;
-  half3 xyx = half3(tint_symbol.v).xyx;
-  half3 xyy = half3(tint_symbol.v).xyy;
-  half3 xyz = half3(tint_symbol.v).xyz;
-  half3 xzx = half3(tint_symbol.v).xzx;
-  half3 xzy = half3(tint_symbol.v).xzy;
-  half3 xzz = half3(tint_symbol.v).xzz;
-  half3 yxx = half3(tint_symbol.v).yxx;
-  half3 yxy = half3(tint_symbol.v).yxy;
-  half3 yxz = half3(tint_symbol.v).yxz;
-  half3 yyx = half3(tint_symbol.v).yyx;
-  half3 yyy = half3(tint_symbol.v).yyy;
-  half3 yyz = half3(tint_symbol.v).yyz;
-  half3 yzx = half3(tint_symbol.v).yzx;
-  half3 yzy = half3(tint_symbol.v).yzy;
-  half3 yzz = half3(tint_symbol.v).yzz;
-  half3 zxx = half3(tint_symbol.v).zxx;
-  half3 zxy = half3(tint_symbol.v).zxy;
-  half3 zxz = half3(tint_symbol.v).zxz;
-  half3 zyx = half3(tint_symbol.v).zyx;
-  half3 zyy = half3(tint_symbol.v).zyy;
-  half3 zyz = half3(tint_symbol.v).zyz;
-  half3 zzx = half3(tint_symbol.v).zzx;
-  half3 zzy = half3(tint_symbol.v).zzy;
-  half3 zzz = half3(tint_symbol.v).zzz;
-  half4 xxxx = half3(tint_symbol.v).xxxx;
-  half4 xxxy = half3(tint_symbol.v).xxxy;
-  half4 xxxz = half3(tint_symbol.v).xxxz;
-  half4 xxyx = half3(tint_symbol.v).xxyx;
-  half4 xxyy = half3(tint_symbol.v).xxyy;
-  half4 xxyz = half3(tint_symbol.v).xxyz;
-  half4 xxzx = half3(tint_symbol.v).xxzx;
-  half4 xxzy = half3(tint_symbol.v).xxzy;
-  half4 xxzz = half3(tint_symbol.v).xxzz;
-  half4 xyxx = half3(tint_symbol.v).xyxx;
-  half4 xyxy = half3(tint_symbol.v).xyxy;
-  half4 xyxz = half3(tint_symbol.v).xyxz;
-  half4 xyyx = half3(tint_symbol.v).xyyx;
-  half4 xyyy = half3(tint_symbol.v).xyyy;
-  half4 xyyz = half3(tint_symbol.v).xyyz;
-  half4 xyzx = half3(tint_symbol.v).xyzx;
-  half4 xyzy = half3(tint_symbol.v).xyzy;
-  half4 xyzz = half3(tint_symbol.v).xyzz;
-  half4 xzxx = half3(tint_symbol.v).xzxx;
-  half4 xzxy = half3(tint_symbol.v).xzxy;
-  half4 xzxz = half3(tint_symbol.v).xzxz;
-  half4 xzyx = half3(tint_symbol.v).xzyx;
-  half4 xzyy = half3(tint_symbol.v).xzyy;
-  half4 xzyz = half3(tint_symbol.v).xzyz;
-  half4 xzzx = half3(tint_symbol.v).xzzx;
-  half4 xzzy = half3(tint_symbol.v).xzzy;
-  half4 xzzz = half3(tint_symbol.v).xzzz;
-  half4 yxxx = half3(tint_symbol.v).yxxx;
-  half4 yxxy = half3(tint_symbol.v).yxxy;
-  half4 yxxz = half3(tint_symbol.v).yxxz;
-  half4 yxyx = half3(tint_symbol.v).yxyx;
-  half4 yxyy = half3(tint_symbol.v).yxyy;
-  half4 yxyz = half3(tint_symbol.v).yxyz;
-  half4 yxzx = half3(tint_symbol.v).yxzx;
-  half4 yxzy = half3(tint_symbol.v).yxzy;
-  half4 yxzz = half3(tint_symbol.v).yxzz;
-  half4 yyxx = half3(tint_symbol.v).yyxx;
-  half4 yyxy = half3(tint_symbol.v).yyxy;
-  half4 yyxz = half3(tint_symbol.v).yyxz;
-  half4 yyyx = half3(tint_symbol.v).yyyx;
-  half4 yyyy = half3(tint_symbol.v).yyyy;
-  half4 yyyz = half3(tint_symbol.v).yyyz;
-  half4 yyzx = half3(tint_symbol.v).yyzx;
-  half4 yyzy = half3(tint_symbol.v).yyzy;
-  half4 yyzz = half3(tint_symbol.v).yyzz;
-  half4 yzxx = half3(tint_symbol.v).yzxx;
-  half4 yzxy = half3(tint_symbol.v).yzxy;
-  half4 yzxz = half3(tint_symbol.v).yzxz;
-  half4 yzyx = half3(tint_symbol.v).yzyx;
-  half4 yzyy = half3(tint_symbol.v).yzyy;
-  half4 yzyz = half3(tint_symbol.v).yzyz;
-  half4 yzzx = half3(tint_symbol.v).yzzx;
-  half4 yzzy = half3(tint_symbol.v).yzzy;
-  half4 yzzz = half3(tint_symbol.v).yzzz;
-  half4 zxxx = half3(tint_symbol.v).zxxx;
-  half4 zxxy = half3(tint_symbol.v).zxxy;
-  half4 zxxz = half3(tint_symbol.v).zxxz;
-  half4 zxyx = half3(tint_symbol.v).zxyx;
-  half4 zxyy = half3(tint_symbol.v).zxyy;
-  half4 zxyz = half3(tint_symbol.v).zxyz;
-  half4 zxzx = half3(tint_symbol.v).zxzx;
-  half4 zxzy = half3(tint_symbol.v).zxzy;
-  half4 zxzz = half3(tint_symbol.v).zxzz;
-  half4 zyxx = half3(tint_symbol.v).zyxx;
-  half4 zyxy = half3(tint_symbol.v).zyxy;
-  half4 zyxz = half3(tint_symbol.v).zyxz;
-  half4 zyyx = half3(tint_symbol.v).zyyx;
-  half4 zyyy = half3(tint_symbol.v).zyyy;
-  half4 zyyz = half3(tint_symbol.v).zyyz;
-  half4 zyzx = half3(tint_symbol.v).zyzx;
-  half4 zyzy = half3(tint_symbol.v).zyzy;
-  half4 zyzz = half3(tint_symbol.v).zyzz;
-  half4 zzxx = half3(tint_symbol.v).zzxx;
-  half4 zzxy = half3(tint_symbol.v).zzxy;
-  half4 zzxz = half3(tint_symbol.v).zzxz;
-  half4 zzyx = half3(tint_symbol.v).zzyx;
-  half4 zzyy = half3(tint_symbol.v).zzyy;
-  half4 zzyz = half3(tint_symbol.v).zzyz;
-  half4 zzzx = half3(tint_symbol.v).zzzx;
-  half4 zzzy = half3(tint_symbol.v).zzzy;
-  half4 zzzz = half3(tint_symbol.v).zzzz;
+  half2 xx = tint_symbol.v.xx;
+  half2 xy = tint_symbol.v.xy;
+  half2 xz = tint_symbol.v.xz;
+  half2 yx = tint_symbol.v.yx;
+  half2 yy = tint_symbol.v.yy;
+  half2 yz = tint_symbol.v.yz;
+  half2 zx = tint_symbol.v.zx;
+  half2 zy = tint_symbol.v.zy;
+  half2 zz = tint_symbol.v.zz;
+  half3 xxx = tint_symbol.v.xxx;
+  half3 xxy = tint_symbol.v.xxy;
+  half3 xxz = tint_symbol.v.xxz;
+  half3 xyx = tint_symbol.v.xyx;
+  half3 xyy = tint_symbol.v.xyy;
+  half3 xyz = tint_symbol.v.xyz;
+  half3 xzx = tint_symbol.v.xzx;
+  half3 xzy = tint_symbol.v.xzy;
+  half3 xzz = tint_symbol.v.xzz;
+  half3 yxx = tint_symbol.v.yxx;
+  half3 yxy = tint_symbol.v.yxy;
+  half3 yxz = tint_symbol.v.yxz;
+  half3 yyx = tint_symbol.v.yyx;
+  half3 yyy = tint_symbol.v.yyy;
+  half3 yyz = tint_symbol.v.yyz;
+  half3 yzx = tint_symbol.v.yzx;
+  half3 yzy = tint_symbol.v.yzy;
+  half3 yzz = tint_symbol.v.yzz;
+  half3 zxx = tint_symbol.v.zxx;
+  half3 zxy = tint_symbol.v.zxy;
+  half3 zxz = tint_symbol.v.zxz;
+  half3 zyx = tint_symbol.v.zyx;
+  half3 zyy = tint_symbol.v.zyy;
+  half3 zyz = tint_symbol.v.zyz;
+  half3 zzx = tint_symbol.v.zzx;
+  half3 zzy = tint_symbol.v.zzy;
+  half3 zzz = tint_symbol.v.zzz;
+  half4 xxxx = tint_symbol.v.xxxx;
+  half4 xxxy = tint_symbol.v.xxxy;
+  half4 xxxz = tint_symbol.v.xxxz;
+  half4 xxyx = tint_symbol.v.xxyx;
+  half4 xxyy = tint_symbol.v.xxyy;
+  half4 xxyz = tint_symbol.v.xxyz;
+  half4 xxzx = tint_symbol.v.xxzx;
+  half4 xxzy = tint_symbol.v.xxzy;
+  half4 xxzz = tint_symbol.v.xxzz;
+  half4 xyxx = tint_symbol.v.xyxx;
+  half4 xyxy = tint_symbol.v.xyxy;
+  half4 xyxz = tint_symbol.v.xyxz;
+  half4 xyyx = tint_symbol.v.xyyx;
+  half4 xyyy = tint_symbol.v.xyyy;
+  half4 xyyz = tint_symbol.v.xyyz;
+  half4 xyzx = tint_symbol.v.xyzx;
+  half4 xyzy = tint_symbol.v.xyzy;
+  half4 xyzz = tint_symbol.v.xyzz;
+  half4 xzxx = tint_symbol.v.xzxx;
+  half4 xzxy = tint_symbol.v.xzxy;
+  half4 xzxz = tint_symbol.v.xzxz;
+  half4 xzyx = tint_symbol.v.xzyx;
+  half4 xzyy = tint_symbol.v.xzyy;
+  half4 xzyz = tint_symbol.v.xzyz;
+  half4 xzzx = tint_symbol.v.xzzx;
+  half4 xzzy = tint_symbol.v.xzzy;
+  half4 xzzz = tint_symbol.v.xzzz;
+  half4 yxxx = tint_symbol.v.yxxx;
+  half4 yxxy = tint_symbol.v.yxxy;
+  half4 yxxz = tint_symbol.v.yxxz;
+  half4 yxyx = tint_symbol.v.yxyx;
+  half4 yxyy = tint_symbol.v.yxyy;
+  half4 yxyz = tint_symbol.v.yxyz;
+  half4 yxzx = tint_symbol.v.yxzx;
+  half4 yxzy = tint_symbol.v.yxzy;
+  half4 yxzz = tint_symbol.v.yxzz;
+  half4 yyxx = tint_symbol.v.yyxx;
+  half4 yyxy = tint_symbol.v.yyxy;
+  half4 yyxz = tint_symbol.v.yyxz;
+  half4 yyyx = tint_symbol.v.yyyx;
+  half4 yyyy = tint_symbol.v.yyyy;
+  half4 yyyz = tint_symbol.v.yyyz;
+  half4 yyzx = tint_symbol.v.yyzx;
+  half4 yyzy = tint_symbol.v.yyzy;
+  half4 yyzz = tint_symbol.v.yyzz;
+  half4 yzxx = tint_symbol.v.yzxx;
+  half4 yzxy = tint_symbol.v.yzxy;
+  half4 yzxz = tint_symbol.v.yzxz;
+  half4 yzyx = tint_symbol.v.yzyx;
+  half4 yzyy = tint_symbol.v.yzyy;
+  half4 yzyz = tint_symbol.v.yzyz;
+  half4 yzzx = tint_symbol.v.yzzx;
+  half4 yzzy = tint_symbol.v.yzzy;
+  half4 yzzz = tint_symbol.v.yzzz;
+  half4 zxxx = tint_symbol.v.zxxx;
+  half4 zxxy = tint_symbol.v.zxxy;
+  half4 zxxz = tint_symbol.v.zxxz;
+  half4 zxyx = tint_symbol.v.zxyx;
+  half4 zxyy = tint_symbol.v.zxyy;
+  half4 zxyz = tint_symbol.v.zxyz;
+  half4 zxzx = tint_symbol.v.zxzx;
+  half4 zxzy = tint_symbol.v.zxzy;
+  half4 zxzz = tint_symbol.v.zxzz;
+  half4 zyxx = tint_symbol.v.zyxx;
+  half4 zyxy = tint_symbol.v.zyxy;
+  half4 zyxz = tint_symbol.v.zyxz;
+  half4 zyyx = tint_symbol.v.zyyx;
+  half4 zyyy = tint_symbol.v.zyyy;
+  half4 zyyz = tint_symbol.v.zyyz;
+  half4 zyzx = tint_symbol.v.zyzx;
+  half4 zyzy = tint_symbol.v.zyzy;
+  half4 zyzz = tint_symbol.v.zyzz;
+  half4 zzxx = tint_symbol.v.zzxx;
+  half4 zzxy = tint_symbol.v.zzxy;
+  half4 zzxz = tint_symbol.v.zzxz;
+  half4 zzyx = tint_symbol.v.zzyx;
+  half4 zzyy = tint_symbol.v.zzyy;
+  half4 zzyz = tint_symbol.v.zzyz;
+  half4 zzzx = tint_symbol.v.zzzx;
+  half4 zzzy = tint_symbol.v.zzzy;
+  half4 zzzz = tint_symbol.v.zzzz;
 }
 
diff --git a/test/tint/expressions/swizzle/read/vec3/f32.wgsl.expected.msl b/test/tint/expressions/swizzle/read/vec3/f32.wgsl.expected.msl
index a682cd4..eda312d 100644
--- a/test/tint/expressions/swizzle/read/vec3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/vec3/f32.wgsl.expected.msl
@@ -11,122 +11,122 @@
   float x = tint_symbol.v[0];
   float y = tint_symbol.v[1];
   float z = tint_symbol.v[2];
-  float2 xx = float3(tint_symbol.v).xx;
-  float2 xy = float3(tint_symbol.v).xy;
-  float2 xz = float3(tint_symbol.v).xz;
-  float2 yx = float3(tint_symbol.v).yx;
-  float2 yy = float3(tint_symbol.v).yy;
-  float2 yz = float3(tint_symbol.v).yz;
-  float2 zx = float3(tint_symbol.v).zx;
-  float2 zy = float3(tint_symbol.v).zy;
-  float2 zz = float3(tint_symbol.v).zz;
-  float3 xxx = float3(tint_symbol.v).xxx;
-  float3 xxy = float3(tint_symbol.v).xxy;
-  float3 xxz = float3(tint_symbol.v).xxz;
-  float3 xyx = float3(tint_symbol.v).xyx;
-  float3 xyy = float3(tint_symbol.v).xyy;
-  float3 xyz = float3(tint_symbol.v).xyz;
-  float3 xzx = float3(tint_symbol.v).xzx;
-  float3 xzy = float3(tint_symbol.v).xzy;
-  float3 xzz = float3(tint_symbol.v).xzz;
-  float3 yxx = float3(tint_symbol.v).yxx;
-  float3 yxy = float3(tint_symbol.v).yxy;
-  float3 yxz = float3(tint_symbol.v).yxz;
-  float3 yyx = float3(tint_symbol.v).yyx;
-  float3 yyy = float3(tint_symbol.v).yyy;
-  float3 yyz = float3(tint_symbol.v).yyz;
-  float3 yzx = float3(tint_symbol.v).yzx;
-  float3 yzy = float3(tint_symbol.v).yzy;
-  float3 yzz = float3(tint_symbol.v).yzz;
-  float3 zxx = float3(tint_symbol.v).zxx;
-  float3 zxy = float3(tint_symbol.v).zxy;
-  float3 zxz = float3(tint_symbol.v).zxz;
-  float3 zyx = float3(tint_symbol.v).zyx;
-  float3 zyy = float3(tint_symbol.v).zyy;
-  float3 zyz = float3(tint_symbol.v).zyz;
-  float3 zzx = float3(tint_symbol.v).zzx;
-  float3 zzy = float3(tint_symbol.v).zzy;
-  float3 zzz = float3(tint_symbol.v).zzz;
-  float4 xxxx = float3(tint_symbol.v).xxxx;
-  float4 xxxy = float3(tint_symbol.v).xxxy;
-  float4 xxxz = float3(tint_symbol.v).xxxz;
-  float4 xxyx = float3(tint_symbol.v).xxyx;
-  float4 xxyy = float3(tint_symbol.v).xxyy;
-  float4 xxyz = float3(tint_symbol.v).xxyz;
-  float4 xxzx = float3(tint_symbol.v).xxzx;
-  float4 xxzy = float3(tint_symbol.v).xxzy;
-  float4 xxzz = float3(tint_symbol.v).xxzz;
-  float4 xyxx = float3(tint_symbol.v).xyxx;
-  float4 xyxy = float3(tint_symbol.v).xyxy;
-  float4 xyxz = float3(tint_symbol.v).xyxz;
-  float4 xyyx = float3(tint_symbol.v).xyyx;
-  float4 xyyy = float3(tint_symbol.v).xyyy;
-  float4 xyyz = float3(tint_symbol.v).xyyz;
-  float4 xyzx = float3(tint_symbol.v).xyzx;
-  float4 xyzy = float3(tint_symbol.v).xyzy;
-  float4 xyzz = float3(tint_symbol.v).xyzz;
-  float4 xzxx = float3(tint_symbol.v).xzxx;
-  float4 xzxy = float3(tint_symbol.v).xzxy;
-  float4 xzxz = float3(tint_symbol.v).xzxz;
-  float4 xzyx = float3(tint_symbol.v).xzyx;
-  float4 xzyy = float3(tint_symbol.v).xzyy;
-  float4 xzyz = float3(tint_symbol.v).xzyz;
-  float4 xzzx = float3(tint_symbol.v).xzzx;
-  float4 xzzy = float3(tint_symbol.v).xzzy;
-  float4 xzzz = float3(tint_symbol.v).xzzz;
-  float4 yxxx = float3(tint_symbol.v).yxxx;
-  float4 yxxy = float3(tint_symbol.v).yxxy;
-  float4 yxxz = float3(tint_symbol.v).yxxz;
-  float4 yxyx = float3(tint_symbol.v).yxyx;
-  float4 yxyy = float3(tint_symbol.v).yxyy;
-  float4 yxyz = float3(tint_symbol.v).yxyz;
-  float4 yxzx = float3(tint_symbol.v).yxzx;
-  float4 yxzy = float3(tint_symbol.v).yxzy;
-  float4 yxzz = float3(tint_symbol.v).yxzz;
-  float4 yyxx = float3(tint_symbol.v).yyxx;
-  float4 yyxy = float3(tint_symbol.v).yyxy;
-  float4 yyxz = float3(tint_symbol.v).yyxz;
-  float4 yyyx = float3(tint_symbol.v).yyyx;
-  float4 yyyy = float3(tint_symbol.v).yyyy;
-  float4 yyyz = float3(tint_symbol.v).yyyz;
-  float4 yyzx = float3(tint_symbol.v).yyzx;
-  float4 yyzy = float3(tint_symbol.v).yyzy;
-  float4 yyzz = float3(tint_symbol.v).yyzz;
-  float4 yzxx = float3(tint_symbol.v).yzxx;
-  float4 yzxy = float3(tint_symbol.v).yzxy;
-  float4 yzxz = float3(tint_symbol.v).yzxz;
-  float4 yzyx = float3(tint_symbol.v).yzyx;
-  float4 yzyy = float3(tint_symbol.v).yzyy;
-  float4 yzyz = float3(tint_symbol.v).yzyz;
-  float4 yzzx = float3(tint_symbol.v).yzzx;
-  float4 yzzy = float3(tint_symbol.v).yzzy;
-  float4 yzzz = float3(tint_symbol.v).yzzz;
-  float4 zxxx = float3(tint_symbol.v).zxxx;
-  float4 zxxy = float3(tint_symbol.v).zxxy;
-  float4 zxxz = float3(tint_symbol.v).zxxz;
-  float4 zxyx = float3(tint_symbol.v).zxyx;
-  float4 zxyy = float3(tint_symbol.v).zxyy;
-  float4 zxyz = float3(tint_symbol.v).zxyz;
-  float4 zxzx = float3(tint_symbol.v).zxzx;
-  float4 zxzy = float3(tint_symbol.v).zxzy;
-  float4 zxzz = float3(tint_symbol.v).zxzz;
-  float4 zyxx = float3(tint_symbol.v).zyxx;
-  float4 zyxy = float3(tint_symbol.v).zyxy;
-  float4 zyxz = float3(tint_symbol.v).zyxz;
-  float4 zyyx = float3(tint_symbol.v).zyyx;
-  float4 zyyy = float3(tint_symbol.v).zyyy;
-  float4 zyyz = float3(tint_symbol.v).zyyz;
-  float4 zyzx = float3(tint_symbol.v).zyzx;
-  float4 zyzy = float3(tint_symbol.v).zyzy;
-  float4 zyzz = float3(tint_symbol.v).zyzz;
-  float4 zzxx = float3(tint_symbol.v).zzxx;
-  float4 zzxy = float3(tint_symbol.v).zzxy;
-  float4 zzxz = float3(tint_symbol.v).zzxz;
-  float4 zzyx = float3(tint_symbol.v).zzyx;
-  float4 zzyy = float3(tint_symbol.v).zzyy;
-  float4 zzyz = float3(tint_symbol.v).zzyz;
-  float4 zzzx = float3(tint_symbol.v).zzzx;
-  float4 zzzy = float3(tint_symbol.v).zzzy;
-  float4 zzzz = float3(tint_symbol.v).zzzz;
+  float2 xx = tint_symbol.v.xx;
+  float2 xy = tint_symbol.v.xy;
+  float2 xz = tint_symbol.v.xz;
+  float2 yx = tint_symbol.v.yx;
+  float2 yy = tint_symbol.v.yy;
+  float2 yz = tint_symbol.v.yz;
+  float2 zx = tint_symbol.v.zx;
+  float2 zy = tint_symbol.v.zy;
+  float2 zz = tint_symbol.v.zz;
+  float3 xxx = tint_symbol.v.xxx;
+  float3 xxy = tint_symbol.v.xxy;
+  float3 xxz = tint_symbol.v.xxz;
+  float3 xyx = tint_symbol.v.xyx;
+  float3 xyy = tint_symbol.v.xyy;
+  float3 xyz = tint_symbol.v.xyz;
+  float3 xzx = tint_symbol.v.xzx;
+  float3 xzy = tint_symbol.v.xzy;
+  float3 xzz = tint_symbol.v.xzz;
+  float3 yxx = tint_symbol.v.yxx;
+  float3 yxy = tint_symbol.v.yxy;
+  float3 yxz = tint_symbol.v.yxz;
+  float3 yyx = tint_symbol.v.yyx;
+  float3 yyy = tint_symbol.v.yyy;
+  float3 yyz = tint_symbol.v.yyz;
+  float3 yzx = tint_symbol.v.yzx;
+  float3 yzy = tint_symbol.v.yzy;
+  float3 yzz = tint_symbol.v.yzz;
+  float3 zxx = tint_symbol.v.zxx;
+  float3 zxy = tint_symbol.v.zxy;
+  float3 zxz = tint_symbol.v.zxz;
+  float3 zyx = tint_symbol.v.zyx;
+  float3 zyy = tint_symbol.v.zyy;
+  float3 zyz = tint_symbol.v.zyz;
+  float3 zzx = tint_symbol.v.zzx;
+  float3 zzy = tint_symbol.v.zzy;
+  float3 zzz = tint_symbol.v.zzz;
+  float4 xxxx = tint_symbol.v.xxxx;
+  float4 xxxy = tint_symbol.v.xxxy;
+  float4 xxxz = tint_symbol.v.xxxz;
+  float4 xxyx = tint_symbol.v.xxyx;
+  float4 xxyy = tint_symbol.v.xxyy;
+  float4 xxyz = tint_symbol.v.xxyz;
+  float4 xxzx = tint_symbol.v.xxzx;
+  float4 xxzy = tint_symbol.v.xxzy;
+  float4 xxzz = tint_symbol.v.xxzz;
+  float4 xyxx = tint_symbol.v.xyxx;
+  float4 xyxy = tint_symbol.v.xyxy;
+  float4 xyxz = tint_symbol.v.xyxz;
+  float4 xyyx = tint_symbol.v.xyyx;
+  float4 xyyy = tint_symbol.v.xyyy;
+  float4 xyyz = tint_symbol.v.xyyz;
+  float4 xyzx = tint_symbol.v.xyzx;
+  float4 xyzy = tint_symbol.v.xyzy;
+  float4 xyzz = tint_symbol.v.xyzz;
+  float4 xzxx = tint_symbol.v.xzxx;
+  float4 xzxy = tint_symbol.v.xzxy;
+  float4 xzxz = tint_symbol.v.xzxz;
+  float4 xzyx = tint_symbol.v.xzyx;
+  float4 xzyy = tint_symbol.v.xzyy;
+  float4 xzyz = tint_symbol.v.xzyz;
+  float4 xzzx = tint_symbol.v.xzzx;
+  float4 xzzy = tint_symbol.v.xzzy;
+  float4 xzzz = tint_symbol.v.xzzz;
+  float4 yxxx = tint_symbol.v.yxxx;
+  float4 yxxy = tint_symbol.v.yxxy;
+  float4 yxxz = tint_symbol.v.yxxz;
+  float4 yxyx = tint_symbol.v.yxyx;
+  float4 yxyy = tint_symbol.v.yxyy;
+  float4 yxyz = tint_symbol.v.yxyz;
+  float4 yxzx = tint_symbol.v.yxzx;
+  float4 yxzy = tint_symbol.v.yxzy;
+  float4 yxzz = tint_symbol.v.yxzz;
+  float4 yyxx = tint_symbol.v.yyxx;
+  float4 yyxy = tint_symbol.v.yyxy;
+  float4 yyxz = tint_symbol.v.yyxz;
+  float4 yyyx = tint_symbol.v.yyyx;
+  float4 yyyy = tint_symbol.v.yyyy;
+  float4 yyyz = tint_symbol.v.yyyz;
+  float4 yyzx = tint_symbol.v.yyzx;
+  float4 yyzy = tint_symbol.v.yyzy;
+  float4 yyzz = tint_symbol.v.yyzz;
+  float4 yzxx = tint_symbol.v.yzxx;
+  float4 yzxy = tint_symbol.v.yzxy;
+  float4 yzxz = tint_symbol.v.yzxz;
+  float4 yzyx = tint_symbol.v.yzyx;
+  float4 yzyy = tint_symbol.v.yzyy;
+  float4 yzyz = tint_symbol.v.yzyz;
+  float4 yzzx = tint_symbol.v.yzzx;
+  float4 yzzy = tint_symbol.v.yzzy;
+  float4 yzzz = tint_symbol.v.yzzz;
+  float4 zxxx = tint_symbol.v.zxxx;
+  float4 zxxy = tint_symbol.v.zxxy;
+  float4 zxxz = tint_symbol.v.zxxz;
+  float4 zxyx = tint_symbol.v.zxyx;
+  float4 zxyy = tint_symbol.v.zxyy;
+  float4 zxyz = tint_symbol.v.zxyz;
+  float4 zxzx = tint_symbol.v.zxzx;
+  float4 zxzy = tint_symbol.v.zxzy;
+  float4 zxzz = tint_symbol.v.zxzz;
+  float4 zyxx = tint_symbol.v.zyxx;
+  float4 zyxy = tint_symbol.v.zyxy;
+  float4 zyxz = tint_symbol.v.zyxz;
+  float4 zyyx = tint_symbol.v.zyyx;
+  float4 zyyy = tint_symbol.v.zyyy;
+  float4 zyyz = tint_symbol.v.zyyz;
+  float4 zyzx = tint_symbol.v.zyzx;
+  float4 zyzy = tint_symbol.v.zyzy;
+  float4 zyzz = tint_symbol.v.zyzz;
+  float4 zzxx = tint_symbol.v.zzxx;
+  float4 zzxy = tint_symbol.v.zzxy;
+  float4 zzxz = tint_symbol.v.zzxz;
+  float4 zzyx = tint_symbol.v.zzyx;
+  float4 zzyy = tint_symbol.v.zzyy;
+  float4 zzyz = tint_symbol.v.zzyz;
+  float4 zzzx = tint_symbol.v.zzzx;
+  float4 zzzy = tint_symbol.v.zzzy;
+  float4 zzzz = tint_symbol.v.zzzz;
 }
 
diff --git a/test/tint/expressions/swizzle/read/vec3/i32.wgsl.expected.msl b/test/tint/expressions/swizzle/read/vec3/i32.wgsl.expected.msl
index 63e124b..9fd3e2f 100644
--- a/test/tint/expressions/swizzle/read/vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/vec3/i32.wgsl.expected.msl
@@ -11,122 +11,122 @@
   int x = tint_symbol.v[0];
   int y = tint_symbol.v[1];
   int z = tint_symbol.v[2];
-  int2 xx = int3(tint_symbol.v).xx;
-  int2 xy = int3(tint_symbol.v).xy;
-  int2 xz = int3(tint_symbol.v).xz;
-  int2 yx = int3(tint_symbol.v).yx;
-  int2 yy = int3(tint_symbol.v).yy;
-  int2 yz = int3(tint_symbol.v).yz;
-  int2 zx = int3(tint_symbol.v).zx;
-  int2 zy = int3(tint_symbol.v).zy;
-  int2 zz = int3(tint_symbol.v).zz;
-  int3 xxx = int3(tint_symbol.v).xxx;
-  int3 xxy = int3(tint_symbol.v).xxy;
-  int3 xxz = int3(tint_symbol.v).xxz;
-  int3 xyx = int3(tint_symbol.v).xyx;
-  int3 xyy = int3(tint_symbol.v).xyy;
-  int3 xyz = int3(tint_symbol.v).xyz;
-  int3 xzx = int3(tint_symbol.v).xzx;
-  int3 xzy = int3(tint_symbol.v).xzy;
-  int3 xzz = int3(tint_symbol.v).xzz;
-  int3 yxx = int3(tint_symbol.v).yxx;
-  int3 yxy = int3(tint_symbol.v).yxy;
-  int3 yxz = int3(tint_symbol.v).yxz;
-  int3 yyx = int3(tint_symbol.v).yyx;
-  int3 yyy = int3(tint_symbol.v).yyy;
-  int3 yyz = int3(tint_symbol.v).yyz;
-  int3 yzx = int3(tint_symbol.v).yzx;
-  int3 yzy = int3(tint_symbol.v).yzy;
-  int3 yzz = int3(tint_symbol.v).yzz;
-  int3 zxx = int3(tint_symbol.v).zxx;
-  int3 zxy = int3(tint_symbol.v).zxy;
-  int3 zxz = int3(tint_symbol.v).zxz;
-  int3 zyx = int3(tint_symbol.v).zyx;
-  int3 zyy = int3(tint_symbol.v).zyy;
-  int3 zyz = int3(tint_symbol.v).zyz;
-  int3 zzx = int3(tint_symbol.v).zzx;
-  int3 zzy = int3(tint_symbol.v).zzy;
-  int3 zzz = int3(tint_symbol.v).zzz;
-  int4 xxxx = int3(tint_symbol.v).xxxx;
-  int4 xxxy = int3(tint_symbol.v).xxxy;
-  int4 xxxz = int3(tint_symbol.v).xxxz;
-  int4 xxyx = int3(tint_symbol.v).xxyx;
-  int4 xxyy = int3(tint_symbol.v).xxyy;
-  int4 xxyz = int3(tint_symbol.v).xxyz;
-  int4 xxzx = int3(tint_symbol.v).xxzx;
-  int4 xxzy = int3(tint_symbol.v).xxzy;
-  int4 xxzz = int3(tint_symbol.v).xxzz;
-  int4 xyxx = int3(tint_symbol.v).xyxx;
-  int4 xyxy = int3(tint_symbol.v).xyxy;
-  int4 xyxz = int3(tint_symbol.v).xyxz;
-  int4 xyyx = int3(tint_symbol.v).xyyx;
-  int4 xyyy = int3(tint_symbol.v).xyyy;
-  int4 xyyz = int3(tint_symbol.v).xyyz;
-  int4 xyzx = int3(tint_symbol.v).xyzx;
-  int4 xyzy = int3(tint_symbol.v).xyzy;
-  int4 xyzz = int3(tint_symbol.v).xyzz;
-  int4 xzxx = int3(tint_symbol.v).xzxx;
-  int4 xzxy = int3(tint_symbol.v).xzxy;
-  int4 xzxz = int3(tint_symbol.v).xzxz;
-  int4 xzyx = int3(tint_symbol.v).xzyx;
-  int4 xzyy = int3(tint_symbol.v).xzyy;
-  int4 xzyz = int3(tint_symbol.v).xzyz;
-  int4 xzzx = int3(tint_symbol.v).xzzx;
-  int4 xzzy = int3(tint_symbol.v).xzzy;
-  int4 xzzz = int3(tint_symbol.v).xzzz;
-  int4 yxxx = int3(tint_symbol.v).yxxx;
-  int4 yxxy = int3(tint_symbol.v).yxxy;
-  int4 yxxz = int3(tint_symbol.v).yxxz;
-  int4 yxyx = int3(tint_symbol.v).yxyx;
-  int4 yxyy = int3(tint_symbol.v).yxyy;
-  int4 yxyz = int3(tint_symbol.v).yxyz;
-  int4 yxzx = int3(tint_symbol.v).yxzx;
-  int4 yxzy = int3(tint_symbol.v).yxzy;
-  int4 yxzz = int3(tint_symbol.v).yxzz;
-  int4 yyxx = int3(tint_symbol.v).yyxx;
-  int4 yyxy = int3(tint_symbol.v).yyxy;
-  int4 yyxz = int3(tint_symbol.v).yyxz;
-  int4 yyyx = int3(tint_symbol.v).yyyx;
-  int4 yyyy = int3(tint_symbol.v).yyyy;
-  int4 yyyz = int3(tint_symbol.v).yyyz;
-  int4 yyzx = int3(tint_symbol.v).yyzx;
-  int4 yyzy = int3(tint_symbol.v).yyzy;
-  int4 yyzz = int3(tint_symbol.v).yyzz;
-  int4 yzxx = int3(tint_symbol.v).yzxx;
-  int4 yzxy = int3(tint_symbol.v).yzxy;
-  int4 yzxz = int3(tint_symbol.v).yzxz;
-  int4 yzyx = int3(tint_symbol.v).yzyx;
-  int4 yzyy = int3(tint_symbol.v).yzyy;
-  int4 yzyz = int3(tint_symbol.v).yzyz;
-  int4 yzzx = int3(tint_symbol.v).yzzx;
-  int4 yzzy = int3(tint_symbol.v).yzzy;
-  int4 yzzz = int3(tint_symbol.v).yzzz;
-  int4 zxxx = int3(tint_symbol.v).zxxx;
-  int4 zxxy = int3(tint_symbol.v).zxxy;
-  int4 zxxz = int3(tint_symbol.v).zxxz;
-  int4 zxyx = int3(tint_symbol.v).zxyx;
-  int4 zxyy = int3(tint_symbol.v).zxyy;
-  int4 zxyz = int3(tint_symbol.v).zxyz;
-  int4 zxzx = int3(tint_symbol.v).zxzx;
-  int4 zxzy = int3(tint_symbol.v).zxzy;
-  int4 zxzz = int3(tint_symbol.v).zxzz;
-  int4 zyxx = int3(tint_symbol.v).zyxx;
-  int4 zyxy = int3(tint_symbol.v).zyxy;
-  int4 zyxz = int3(tint_symbol.v).zyxz;
-  int4 zyyx = int3(tint_symbol.v).zyyx;
-  int4 zyyy = int3(tint_symbol.v).zyyy;
-  int4 zyyz = int3(tint_symbol.v).zyyz;
-  int4 zyzx = int3(tint_symbol.v).zyzx;
-  int4 zyzy = int3(tint_symbol.v).zyzy;
-  int4 zyzz = int3(tint_symbol.v).zyzz;
-  int4 zzxx = int3(tint_symbol.v).zzxx;
-  int4 zzxy = int3(tint_symbol.v).zzxy;
-  int4 zzxz = int3(tint_symbol.v).zzxz;
-  int4 zzyx = int3(tint_symbol.v).zzyx;
-  int4 zzyy = int3(tint_symbol.v).zzyy;
-  int4 zzyz = int3(tint_symbol.v).zzyz;
-  int4 zzzx = int3(tint_symbol.v).zzzx;
-  int4 zzzy = int3(tint_symbol.v).zzzy;
-  int4 zzzz = int3(tint_symbol.v).zzzz;
+  int2 xx = tint_symbol.v.xx;
+  int2 xy = tint_symbol.v.xy;
+  int2 xz = tint_symbol.v.xz;
+  int2 yx = tint_symbol.v.yx;
+  int2 yy = tint_symbol.v.yy;
+  int2 yz = tint_symbol.v.yz;
+  int2 zx = tint_symbol.v.zx;
+  int2 zy = tint_symbol.v.zy;
+  int2 zz = tint_symbol.v.zz;
+  int3 xxx = tint_symbol.v.xxx;
+  int3 xxy = tint_symbol.v.xxy;
+  int3 xxz = tint_symbol.v.xxz;
+  int3 xyx = tint_symbol.v.xyx;
+  int3 xyy = tint_symbol.v.xyy;
+  int3 xyz = tint_symbol.v.xyz;
+  int3 xzx = tint_symbol.v.xzx;
+  int3 xzy = tint_symbol.v.xzy;
+  int3 xzz = tint_symbol.v.xzz;
+  int3 yxx = tint_symbol.v.yxx;
+  int3 yxy = tint_symbol.v.yxy;
+  int3 yxz = tint_symbol.v.yxz;
+  int3 yyx = tint_symbol.v.yyx;
+  int3 yyy = tint_symbol.v.yyy;
+  int3 yyz = tint_symbol.v.yyz;
+  int3 yzx = tint_symbol.v.yzx;
+  int3 yzy = tint_symbol.v.yzy;
+  int3 yzz = tint_symbol.v.yzz;
+  int3 zxx = tint_symbol.v.zxx;
+  int3 zxy = tint_symbol.v.zxy;
+  int3 zxz = tint_symbol.v.zxz;
+  int3 zyx = tint_symbol.v.zyx;
+  int3 zyy = tint_symbol.v.zyy;
+  int3 zyz = tint_symbol.v.zyz;
+  int3 zzx = tint_symbol.v.zzx;
+  int3 zzy = tint_symbol.v.zzy;
+  int3 zzz = tint_symbol.v.zzz;
+  int4 xxxx = tint_symbol.v.xxxx;
+  int4 xxxy = tint_symbol.v.xxxy;
+  int4 xxxz = tint_symbol.v.xxxz;
+  int4 xxyx = tint_symbol.v.xxyx;
+  int4 xxyy = tint_symbol.v.xxyy;
+  int4 xxyz = tint_symbol.v.xxyz;
+  int4 xxzx = tint_symbol.v.xxzx;
+  int4 xxzy = tint_symbol.v.xxzy;
+  int4 xxzz = tint_symbol.v.xxzz;
+  int4 xyxx = tint_symbol.v.xyxx;
+  int4 xyxy = tint_symbol.v.xyxy;
+  int4 xyxz = tint_symbol.v.xyxz;
+  int4 xyyx = tint_symbol.v.xyyx;
+  int4 xyyy = tint_symbol.v.xyyy;
+  int4 xyyz = tint_symbol.v.xyyz;
+  int4 xyzx = tint_symbol.v.xyzx;
+  int4 xyzy = tint_symbol.v.xyzy;
+  int4 xyzz = tint_symbol.v.xyzz;
+  int4 xzxx = tint_symbol.v.xzxx;
+  int4 xzxy = tint_symbol.v.xzxy;
+  int4 xzxz = tint_symbol.v.xzxz;
+  int4 xzyx = tint_symbol.v.xzyx;
+  int4 xzyy = tint_symbol.v.xzyy;
+  int4 xzyz = tint_symbol.v.xzyz;
+  int4 xzzx = tint_symbol.v.xzzx;
+  int4 xzzy = tint_symbol.v.xzzy;
+  int4 xzzz = tint_symbol.v.xzzz;
+  int4 yxxx = tint_symbol.v.yxxx;
+  int4 yxxy = tint_symbol.v.yxxy;
+  int4 yxxz = tint_symbol.v.yxxz;
+  int4 yxyx = tint_symbol.v.yxyx;
+  int4 yxyy = tint_symbol.v.yxyy;
+  int4 yxyz = tint_symbol.v.yxyz;
+  int4 yxzx = tint_symbol.v.yxzx;
+  int4 yxzy = tint_symbol.v.yxzy;
+  int4 yxzz = tint_symbol.v.yxzz;
+  int4 yyxx = tint_symbol.v.yyxx;
+  int4 yyxy = tint_symbol.v.yyxy;
+  int4 yyxz = tint_symbol.v.yyxz;
+  int4 yyyx = tint_symbol.v.yyyx;
+  int4 yyyy = tint_symbol.v.yyyy;
+  int4 yyyz = tint_symbol.v.yyyz;
+  int4 yyzx = tint_symbol.v.yyzx;
+  int4 yyzy = tint_symbol.v.yyzy;
+  int4 yyzz = tint_symbol.v.yyzz;
+  int4 yzxx = tint_symbol.v.yzxx;
+  int4 yzxy = tint_symbol.v.yzxy;
+  int4 yzxz = tint_symbol.v.yzxz;
+  int4 yzyx = tint_symbol.v.yzyx;
+  int4 yzyy = tint_symbol.v.yzyy;
+  int4 yzyz = tint_symbol.v.yzyz;
+  int4 yzzx = tint_symbol.v.yzzx;
+  int4 yzzy = tint_symbol.v.yzzy;
+  int4 yzzz = tint_symbol.v.yzzz;
+  int4 zxxx = tint_symbol.v.zxxx;
+  int4 zxxy = tint_symbol.v.zxxy;
+  int4 zxxz = tint_symbol.v.zxxz;
+  int4 zxyx = tint_symbol.v.zxyx;
+  int4 zxyy = tint_symbol.v.zxyy;
+  int4 zxyz = tint_symbol.v.zxyz;
+  int4 zxzx = tint_symbol.v.zxzx;
+  int4 zxzy = tint_symbol.v.zxzy;
+  int4 zxzz = tint_symbol.v.zxzz;
+  int4 zyxx = tint_symbol.v.zyxx;
+  int4 zyxy = tint_symbol.v.zyxy;
+  int4 zyxz = tint_symbol.v.zyxz;
+  int4 zyyx = tint_symbol.v.zyyx;
+  int4 zyyy = tint_symbol.v.zyyy;
+  int4 zyyz = tint_symbol.v.zyyz;
+  int4 zyzx = tint_symbol.v.zyzx;
+  int4 zyzy = tint_symbol.v.zyzy;
+  int4 zyzz = tint_symbol.v.zyzz;
+  int4 zzxx = tint_symbol.v.zzxx;
+  int4 zzxy = tint_symbol.v.zzxy;
+  int4 zzxz = tint_symbol.v.zzxz;
+  int4 zzyx = tint_symbol.v.zzyx;
+  int4 zzyy = tint_symbol.v.zzyy;
+  int4 zzyz = tint_symbol.v.zzyz;
+  int4 zzzx = tint_symbol.v.zzzx;
+  int4 zzzy = tint_symbol.v.zzzy;
+  int4 zzzz = tint_symbol.v.zzzz;
 }
 
diff --git a/test/tint/expressions/swizzle/read/vec3/u32.wgsl.expected.msl b/test/tint/expressions/swizzle/read/vec3/u32.wgsl.expected.msl
index 62ca0b3..e926493 100644
--- a/test/tint/expressions/swizzle/read/vec3/u32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/vec3/u32.wgsl.expected.msl
@@ -11,122 +11,122 @@
   uint x = tint_symbol.v[0];
   uint y = tint_symbol.v[1];
   uint z = tint_symbol.v[2];
-  uint2 xx = uint3(tint_symbol.v).xx;
-  uint2 xy = uint3(tint_symbol.v).xy;
-  uint2 xz = uint3(tint_symbol.v).xz;
-  uint2 yx = uint3(tint_symbol.v).yx;
-  uint2 yy = uint3(tint_symbol.v).yy;
-  uint2 yz = uint3(tint_symbol.v).yz;
-  uint2 zx = uint3(tint_symbol.v).zx;
-  uint2 zy = uint3(tint_symbol.v).zy;
-  uint2 zz = uint3(tint_symbol.v).zz;
-  uint3 xxx = uint3(tint_symbol.v).xxx;
-  uint3 xxy = uint3(tint_symbol.v).xxy;
-  uint3 xxz = uint3(tint_symbol.v).xxz;
-  uint3 xyx = uint3(tint_symbol.v).xyx;
-  uint3 xyy = uint3(tint_symbol.v).xyy;
-  uint3 xyz = uint3(tint_symbol.v).xyz;
-  uint3 xzx = uint3(tint_symbol.v).xzx;
-  uint3 xzy = uint3(tint_symbol.v).xzy;
-  uint3 xzz = uint3(tint_symbol.v).xzz;
-  uint3 yxx = uint3(tint_symbol.v).yxx;
-  uint3 yxy = uint3(tint_symbol.v).yxy;
-  uint3 yxz = uint3(tint_symbol.v).yxz;
-  uint3 yyx = uint3(tint_symbol.v).yyx;
-  uint3 yyy = uint3(tint_symbol.v).yyy;
-  uint3 yyz = uint3(tint_symbol.v).yyz;
-  uint3 yzx = uint3(tint_symbol.v).yzx;
-  uint3 yzy = uint3(tint_symbol.v).yzy;
-  uint3 yzz = uint3(tint_symbol.v).yzz;
-  uint3 zxx = uint3(tint_symbol.v).zxx;
-  uint3 zxy = uint3(tint_symbol.v).zxy;
-  uint3 zxz = uint3(tint_symbol.v).zxz;
-  uint3 zyx = uint3(tint_symbol.v).zyx;
-  uint3 zyy = uint3(tint_symbol.v).zyy;
-  uint3 zyz = uint3(tint_symbol.v).zyz;
-  uint3 zzx = uint3(tint_symbol.v).zzx;
-  uint3 zzy = uint3(tint_symbol.v).zzy;
-  uint3 zzz = uint3(tint_symbol.v).zzz;
-  uint4 xxxx = uint3(tint_symbol.v).xxxx;
-  uint4 xxxy = uint3(tint_symbol.v).xxxy;
-  uint4 xxxz = uint3(tint_symbol.v).xxxz;
-  uint4 xxyx = uint3(tint_symbol.v).xxyx;
-  uint4 xxyy = uint3(tint_symbol.v).xxyy;
-  uint4 xxyz = uint3(tint_symbol.v).xxyz;
-  uint4 xxzx = uint3(tint_symbol.v).xxzx;
-  uint4 xxzy = uint3(tint_symbol.v).xxzy;
-  uint4 xxzz = uint3(tint_symbol.v).xxzz;
-  uint4 xyxx = uint3(tint_symbol.v).xyxx;
-  uint4 xyxy = uint3(tint_symbol.v).xyxy;
-  uint4 xyxz = uint3(tint_symbol.v).xyxz;
-  uint4 xyyx = uint3(tint_symbol.v).xyyx;
-  uint4 xyyy = uint3(tint_symbol.v).xyyy;
-  uint4 xyyz = uint3(tint_symbol.v).xyyz;
-  uint4 xyzx = uint3(tint_symbol.v).xyzx;
-  uint4 xyzy = uint3(tint_symbol.v).xyzy;
-  uint4 xyzz = uint3(tint_symbol.v).xyzz;
-  uint4 xzxx = uint3(tint_symbol.v).xzxx;
-  uint4 xzxy = uint3(tint_symbol.v).xzxy;
-  uint4 xzxz = uint3(tint_symbol.v).xzxz;
-  uint4 xzyx = uint3(tint_symbol.v).xzyx;
-  uint4 xzyy = uint3(tint_symbol.v).xzyy;
-  uint4 xzyz = uint3(tint_symbol.v).xzyz;
-  uint4 xzzx = uint3(tint_symbol.v).xzzx;
-  uint4 xzzy = uint3(tint_symbol.v).xzzy;
-  uint4 xzzz = uint3(tint_symbol.v).xzzz;
-  uint4 yxxx = uint3(tint_symbol.v).yxxx;
-  uint4 yxxy = uint3(tint_symbol.v).yxxy;
-  uint4 yxxz = uint3(tint_symbol.v).yxxz;
-  uint4 yxyx = uint3(tint_symbol.v).yxyx;
-  uint4 yxyy = uint3(tint_symbol.v).yxyy;
-  uint4 yxyz = uint3(tint_symbol.v).yxyz;
-  uint4 yxzx = uint3(tint_symbol.v).yxzx;
-  uint4 yxzy = uint3(tint_symbol.v).yxzy;
-  uint4 yxzz = uint3(tint_symbol.v).yxzz;
-  uint4 yyxx = uint3(tint_symbol.v).yyxx;
-  uint4 yyxy = uint3(tint_symbol.v).yyxy;
-  uint4 yyxz = uint3(tint_symbol.v).yyxz;
-  uint4 yyyx = uint3(tint_symbol.v).yyyx;
-  uint4 yyyy = uint3(tint_symbol.v).yyyy;
-  uint4 yyyz = uint3(tint_symbol.v).yyyz;
-  uint4 yyzx = uint3(tint_symbol.v).yyzx;
-  uint4 yyzy = uint3(tint_symbol.v).yyzy;
-  uint4 yyzz = uint3(tint_symbol.v).yyzz;
-  uint4 yzxx = uint3(tint_symbol.v).yzxx;
-  uint4 yzxy = uint3(tint_symbol.v).yzxy;
-  uint4 yzxz = uint3(tint_symbol.v).yzxz;
-  uint4 yzyx = uint3(tint_symbol.v).yzyx;
-  uint4 yzyy = uint3(tint_symbol.v).yzyy;
-  uint4 yzyz = uint3(tint_symbol.v).yzyz;
-  uint4 yzzx = uint3(tint_symbol.v).yzzx;
-  uint4 yzzy = uint3(tint_symbol.v).yzzy;
-  uint4 yzzz = uint3(tint_symbol.v).yzzz;
-  uint4 zxxx = uint3(tint_symbol.v).zxxx;
-  uint4 zxxy = uint3(tint_symbol.v).zxxy;
-  uint4 zxxz = uint3(tint_symbol.v).zxxz;
-  uint4 zxyx = uint3(tint_symbol.v).zxyx;
-  uint4 zxyy = uint3(tint_symbol.v).zxyy;
-  uint4 zxyz = uint3(tint_symbol.v).zxyz;
-  uint4 zxzx = uint3(tint_symbol.v).zxzx;
-  uint4 zxzy = uint3(tint_symbol.v).zxzy;
-  uint4 zxzz = uint3(tint_symbol.v).zxzz;
-  uint4 zyxx = uint3(tint_symbol.v).zyxx;
-  uint4 zyxy = uint3(tint_symbol.v).zyxy;
-  uint4 zyxz = uint3(tint_symbol.v).zyxz;
-  uint4 zyyx = uint3(tint_symbol.v).zyyx;
-  uint4 zyyy = uint3(tint_symbol.v).zyyy;
-  uint4 zyyz = uint3(tint_symbol.v).zyyz;
-  uint4 zyzx = uint3(tint_symbol.v).zyzx;
-  uint4 zyzy = uint3(tint_symbol.v).zyzy;
-  uint4 zyzz = uint3(tint_symbol.v).zyzz;
-  uint4 zzxx = uint3(tint_symbol.v).zzxx;
-  uint4 zzxy = uint3(tint_symbol.v).zzxy;
-  uint4 zzxz = uint3(tint_symbol.v).zzxz;
-  uint4 zzyx = uint3(tint_symbol.v).zzyx;
-  uint4 zzyy = uint3(tint_symbol.v).zzyy;
-  uint4 zzyz = uint3(tint_symbol.v).zzyz;
-  uint4 zzzx = uint3(tint_symbol.v).zzzx;
-  uint4 zzzy = uint3(tint_symbol.v).zzzy;
-  uint4 zzzz = uint3(tint_symbol.v).zzzz;
+  uint2 xx = tint_symbol.v.xx;
+  uint2 xy = tint_symbol.v.xy;
+  uint2 xz = tint_symbol.v.xz;
+  uint2 yx = tint_symbol.v.yx;
+  uint2 yy = tint_symbol.v.yy;
+  uint2 yz = tint_symbol.v.yz;
+  uint2 zx = tint_symbol.v.zx;
+  uint2 zy = tint_symbol.v.zy;
+  uint2 zz = tint_symbol.v.zz;
+  uint3 xxx = tint_symbol.v.xxx;
+  uint3 xxy = tint_symbol.v.xxy;
+  uint3 xxz = tint_symbol.v.xxz;
+  uint3 xyx = tint_symbol.v.xyx;
+  uint3 xyy = tint_symbol.v.xyy;
+  uint3 xyz = tint_symbol.v.xyz;
+  uint3 xzx = tint_symbol.v.xzx;
+  uint3 xzy = tint_symbol.v.xzy;
+  uint3 xzz = tint_symbol.v.xzz;
+  uint3 yxx = tint_symbol.v.yxx;
+  uint3 yxy = tint_symbol.v.yxy;
+  uint3 yxz = tint_symbol.v.yxz;
+  uint3 yyx = tint_symbol.v.yyx;
+  uint3 yyy = tint_symbol.v.yyy;
+  uint3 yyz = tint_symbol.v.yyz;
+  uint3 yzx = tint_symbol.v.yzx;
+  uint3 yzy = tint_symbol.v.yzy;
+  uint3 yzz = tint_symbol.v.yzz;
+  uint3 zxx = tint_symbol.v.zxx;
+  uint3 zxy = tint_symbol.v.zxy;
+  uint3 zxz = tint_symbol.v.zxz;
+  uint3 zyx = tint_symbol.v.zyx;
+  uint3 zyy = tint_symbol.v.zyy;
+  uint3 zyz = tint_symbol.v.zyz;
+  uint3 zzx = tint_symbol.v.zzx;
+  uint3 zzy = tint_symbol.v.zzy;
+  uint3 zzz = tint_symbol.v.zzz;
+  uint4 xxxx = tint_symbol.v.xxxx;
+  uint4 xxxy = tint_symbol.v.xxxy;
+  uint4 xxxz = tint_symbol.v.xxxz;
+  uint4 xxyx = tint_symbol.v.xxyx;
+  uint4 xxyy = tint_symbol.v.xxyy;
+  uint4 xxyz = tint_symbol.v.xxyz;
+  uint4 xxzx = tint_symbol.v.xxzx;
+  uint4 xxzy = tint_symbol.v.xxzy;
+  uint4 xxzz = tint_symbol.v.xxzz;
+  uint4 xyxx = tint_symbol.v.xyxx;
+  uint4 xyxy = tint_symbol.v.xyxy;
+  uint4 xyxz = tint_symbol.v.xyxz;
+  uint4 xyyx = tint_symbol.v.xyyx;
+  uint4 xyyy = tint_symbol.v.xyyy;
+  uint4 xyyz = tint_symbol.v.xyyz;
+  uint4 xyzx = tint_symbol.v.xyzx;
+  uint4 xyzy = tint_symbol.v.xyzy;
+  uint4 xyzz = tint_symbol.v.xyzz;
+  uint4 xzxx = tint_symbol.v.xzxx;
+  uint4 xzxy = tint_symbol.v.xzxy;
+  uint4 xzxz = tint_symbol.v.xzxz;
+  uint4 xzyx = tint_symbol.v.xzyx;
+  uint4 xzyy = tint_symbol.v.xzyy;
+  uint4 xzyz = tint_symbol.v.xzyz;
+  uint4 xzzx = tint_symbol.v.xzzx;
+  uint4 xzzy = tint_symbol.v.xzzy;
+  uint4 xzzz = tint_symbol.v.xzzz;
+  uint4 yxxx = tint_symbol.v.yxxx;
+  uint4 yxxy = tint_symbol.v.yxxy;
+  uint4 yxxz = tint_symbol.v.yxxz;
+  uint4 yxyx = tint_symbol.v.yxyx;
+  uint4 yxyy = tint_symbol.v.yxyy;
+  uint4 yxyz = tint_symbol.v.yxyz;
+  uint4 yxzx = tint_symbol.v.yxzx;
+  uint4 yxzy = tint_symbol.v.yxzy;
+  uint4 yxzz = tint_symbol.v.yxzz;
+  uint4 yyxx = tint_symbol.v.yyxx;
+  uint4 yyxy = tint_symbol.v.yyxy;
+  uint4 yyxz = tint_symbol.v.yyxz;
+  uint4 yyyx = tint_symbol.v.yyyx;
+  uint4 yyyy = tint_symbol.v.yyyy;
+  uint4 yyyz = tint_symbol.v.yyyz;
+  uint4 yyzx = tint_symbol.v.yyzx;
+  uint4 yyzy = tint_symbol.v.yyzy;
+  uint4 yyzz = tint_symbol.v.yyzz;
+  uint4 yzxx = tint_symbol.v.yzxx;
+  uint4 yzxy = tint_symbol.v.yzxy;
+  uint4 yzxz = tint_symbol.v.yzxz;
+  uint4 yzyx = tint_symbol.v.yzyx;
+  uint4 yzyy = tint_symbol.v.yzyy;
+  uint4 yzyz = tint_symbol.v.yzyz;
+  uint4 yzzx = tint_symbol.v.yzzx;
+  uint4 yzzy = tint_symbol.v.yzzy;
+  uint4 yzzz = tint_symbol.v.yzzz;
+  uint4 zxxx = tint_symbol.v.zxxx;
+  uint4 zxxy = tint_symbol.v.zxxy;
+  uint4 zxxz = tint_symbol.v.zxxz;
+  uint4 zxyx = tint_symbol.v.zxyx;
+  uint4 zxyy = tint_symbol.v.zxyy;
+  uint4 zxyz = tint_symbol.v.zxyz;
+  uint4 zxzx = tint_symbol.v.zxzx;
+  uint4 zxzy = tint_symbol.v.zxzy;
+  uint4 zxzz = tint_symbol.v.zxzz;
+  uint4 zyxx = tint_symbol.v.zyxx;
+  uint4 zyxy = tint_symbol.v.zyxy;
+  uint4 zyxz = tint_symbol.v.zyxz;
+  uint4 zyyx = tint_symbol.v.zyyx;
+  uint4 zyyy = tint_symbol.v.zyyy;
+  uint4 zyyz = tint_symbol.v.zyyz;
+  uint4 zyzx = tint_symbol.v.zyzx;
+  uint4 zyzy = tint_symbol.v.zyzy;
+  uint4 zyzz = tint_symbol.v.zyzz;
+  uint4 zzxx = tint_symbol.v.zzxx;
+  uint4 zzxy = tint_symbol.v.zzxy;
+  uint4 zzxz = tint_symbol.v.zzxz;
+  uint4 zzyx = tint_symbol.v.zzyx;
+  uint4 zzyy = tint_symbol.v.zzyy;
+  uint4 zzyz = tint_symbol.v.zzyz;
+  uint4 zzzx = tint_symbol.v.zzzx;
+  uint4 zzzy = tint_symbol.v.zzzy;
+  uint4 zzzz = tint_symbol.v.zzzz;
 }
 
diff --git a/test/tint/expressions/swizzle/write/packed_vec3/f16.wgsl.expected.msl b/test/tint/expressions/swizzle/write/packed_vec3/f16.wgsl.expected.msl
index 92500cc..2512a63 100644
--- a/test/tint/expressions/swizzle/write/packed_vec3/f16.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/write/packed_vec3/f16.wgsl.expected.msl
@@ -14,13 +14,17 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ packed_half3 v;
   /* 0x0006 */ tint_array<int8_t, 2> tint_pad;
 };
 
-void f(device S* const tint_symbol) {
-  (*(tint_symbol)).v = half3(1.0h, 2.0h, 3.0h);
+struct S {
+  half3 v;
+};
+
+void f(device S_tint_packed_vec3* const tint_symbol) {
+  (*(tint_symbol)).v = packed_half3(1.0h, 2.0h, 3.0h);
   (*(tint_symbol)).v[0] = 1.0h;
   (*(tint_symbol)).v[1] = 2.0h;
   (*(tint_symbol)).v[2] = 3.0h;
diff --git a/test/tint/expressions/swizzle/write/packed_vec3/f32.wgsl.expected.msl b/test/tint/expressions/swizzle/write/packed_vec3/f32.wgsl.expected.msl
index 8640cf6..0c7b6a3 100644
--- a/test/tint/expressions/swizzle/write/packed_vec3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/write/packed_vec3/f32.wgsl.expected.msl
@@ -14,13 +14,17 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ packed_float3 v;
   /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-void f(device S* const tint_symbol) {
-  (*(tint_symbol)).v = float3(1.0f, 2.0f, 3.0f);
+struct S {
+  float3 v;
+};
+
+void f(device S_tint_packed_vec3* const tint_symbol) {
+  (*(tint_symbol)).v = packed_float3(1.0f, 2.0f, 3.0f);
   (*(tint_symbol)).v[0] = 1.0f;
   (*(tint_symbol)).v[1] = 2.0f;
   (*(tint_symbol)).v[2] = 3.0f;
diff --git a/test/tint/expressions/swizzle/write/packed_vec3/i32.wgsl.expected.msl b/test/tint/expressions/swizzle/write/packed_vec3/i32.wgsl.expected.msl
index 06cb457..f630193 100644
--- a/test/tint/expressions/swizzle/write/packed_vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/write/packed_vec3/i32.wgsl.expected.msl
@@ -14,13 +14,17 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ packed_int3 v;
   /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-void f(device S* const tint_symbol) {
-  (*(tint_symbol)).v = int3(1, 2, 3);
+struct S {
+  int3 v;
+};
+
+void f(device S_tint_packed_vec3* const tint_symbol) {
+  (*(tint_symbol)).v = packed_int3(1, 2, 3);
   (*(tint_symbol)).v[0] = 1;
   (*(tint_symbol)).v[1] = 2;
   (*(tint_symbol)).v[2] = 3;
diff --git a/test/tint/expressions/swizzle/write/packed_vec3/u32.wgsl.expected.msl b/test/tint/expressions/swizzle/write/packed_vec3/u32.wgsl.expected.msl
index e8e4904..75f99e4 100644
--- a/test/tint/expressions/swizzle/write/packed_vec3/u32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/write/packed_vec3/u32.wgsl.expected.msl
@@ -14,13 +14,17 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ packed_uint3 v;
   /* 0x000c */ tint_array<int8_t, 4> tint_pad;
 };
 
-void f(device S* const tint_symbol) {
-  (*(tint_symbol)).v = uint3(1u, 2u, 3u);
+struct S {
+  uint3 v;
+};
+
+void f(device S_tint_packed_vec3* const tint_symbol) {
+  (*(tint_symbol)).v = packed_uint3(1u, 2u, 3u);
   (*(tint_symbol)).v[0] = 1u;
   (*(tint_symbol)).v[1] = 2u;
   (*(tint_symbol)).v[2] = 3u;
diff --git a/test/tint/samples/compute_boids.wgsl.expected.msl b/test/tint/samples/compute_boids.wgsl.expected.msl
index a3cb32a..3a8d9cc 100644
--- a/test/tint/samples/compute_boids.wgsl.expected.msl
+++ b/test/tint/samples/compute_boids.wgsl.expected.msl
@@ -89,8 +89,8 @@
     if ((i == index)) {
       continue;
     }
-    pos = float2((*(tint_symbol_4)).particles[i].pos).xy;
-    vel = float2((*(tint_symbol_4)).particles[i].vel).xy;
+    pos = (*(tint_symbol_4)).particles[i].pos.xy;
+    vel = (*(tint_symbol_4)).particles[i].vel.xy;
     if ((distance(pos, vPos) < (*(tint_symbol_5)).rule1Distance)) {
       cMass = (cMass + pos);
       cMassCount = as_type<int>((as_type<uint>(cMassCount) + as_type<uint>(1)));
diff --git a/test/tint/shader_io/shared_struct_storage_buffer_f16.wgsl.expected.msl b/test/tint/shader_io/shared_struct_storage_buffer_f16.wgsl.expected.msl
index c442b8f..f5c35d5 100644
--- a/test/tint/shader_io/shared_struct_storage_buffer_f16.wgsl.expected.msl
+++ b/test/tint/shader_io/shared_struct_storage_buffer_f16.wgsl.expected.msl
@@ -14,7 +14,7 @@
     T elements[N];
 };
 
-struct S {
+struct S_tint_packed_vec3 {
   /* 0x0000 */ float f;
   /* 0x0004 */ uint u;
   /* 0x0008 */ tint_array<int8_t, 120> tint_pad;
@@ -26,12 +26,20 @@
   /* 0x00c6 */ tint_array<int8_t, 58> tint_pad_3;
 };
 
-void assign_and_preserve_padding(device S* const dest, S value) {
+struct S {
+  float f;
+  uint u;
+  float4 v;
+  half x;
+  half3 y;
+};
+
+void assign_and_preserve_padding(device S_tint_packed_vec3* const dest, S value) {
   (*(dest)).f = value.f;
   (*(dest)).u = value.u;
   (*(dest)).v = value.v;
   (*(dest)).x = value.x;
-  (*(dest)).y = half3(value.y);
+  (*(dest)).y = packed_half3(value.y);
 }
 
 struct tint_symbol_1 {
@@ -41,16 +49,16 @@
   half3 y [[user(locn3)]];
 };
 
-void frag_main_inner(S input, device S* const tint_symbol_3) {
+void frag_main_inner(S input, device S_tint_packed_vec3* const tint_symbol_3) {
   float const f = input.f;
   uint const u = input.u;
   float4 const v = input.v;
   half const x = input.x;
-  half3 const y = half3(input.y);
+  half3 const y = input.y;
   assign_and_preserve_padding(tint_symbol_3, input);
 }
 
-fragment void frag_main(device S* tint_symbol_4 [[buffer(0)]], float4 v [[position]], tint_symbol_1 tint_symbol [[stage_in]]) {
+fragment void frag_main(device S_tint_packed_vec3* tint_symbol_4 [[buffer(0)]], float4 v [[position]], tint_symbol_1 tint_symbol [[stage_in]]) {
   S const tint_symbol_2 = {.f=tint_symbol.f, .u=tint_symbol.u, .v=v, .x=tint_symbol.x, .y=tint_symbol.y};
   frag_main_inner(tint_symbol_2, tint_symbol_4);
   return;