[msl] Fix lve/sve for packed vec3<bool> inside struct

The type will still be a pointer when extracted from the struct via
`access`, so we need to unwrap the pointer before we check for
vec3<bool>.

Fixed: 436823153
Change-Id: Ifb8fa0a50d607384cd0ef874e4e1a6075dd7c119
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/256294
Auto-Submit: James Price <jrprice@google.com>
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/msl/writer/raise/packed_vec3.cc b/src/tint/lang/msl/writer/raise/packed_vec3.cc
index 136bed2..7e19ec0 100644
--- a/src/tint/lang/msl/writer/raise/packed_vec3.cc
+++ b/src/tint/lang/msl/writer/raise/packed_vec3.cc
@@ -315,7 +315,7 @@
                 // Packed vectors support component access so there is usually nothing to do.
                 // For vectors that were originally booleans we need to convert the u32 that we load
                 // to a bool.
-                if (unpacked_type->IsBoolVector()) {
+                if (unpacked_type->UnwrapPtr()->IsBoolVector()) {
                     auto* u32_load = b.InstructionResult<u32>();
                     auto* converted_to_bool = b.ConvertWithResult(lve->DetachResult(), u32_load);
                     converted_to_bool->InsertAfter(lve);
@@ -330,7 +330,7 @@
                 // Packed vectors support component access so there is usually nothing to do.
                 // For vectors that were originally booleans we need to convert the bool to a u32
                 // before we store it.
-                if (unpacked_type->IsBoolVector()) {
+                if (unpacked_type->UnwrapPtr()->IsBoolVector()) {
                     auto* converted_to_u32 = b.Convert<u32>(sve->Value());
                     converted_to_u32->InsertBefore(sve);
                     sve->SetOperand(core::ir::StoreVectorElement::kValueOperandOffset,
diff --git a/src/tint/lang/msl/writer/raise/packed_vec3_test.cc b/src/tint/lang/msl/writer/raise/packed_vec3_test.cc
index 7a41054..8a0d470 100644
--- a/src/tint/lang/msl/writer/raise/packed_vec3_test.cc
+++ b/src/tint/lang/msl/writer/raise/packed_vec3_test.cc
@@ -3860,5 +3860,70 @@
     EXPECT_EQ(expect, str());
 }
 
+TEST_F(MslWriter_PackedVec3Test, WorkgroupVar_Struct_Vec3_Bool_VectorElementLoadAndStore) {
+    auto* s = ty.Struct(mod.symbols.New("S"), {
+                                                  {mod.symbols.Register("data"), ty.vec3<bool>()},
+                                              });
+    auto* var = b.Var("v", ty.ptr<workgroup>(s));
+    mod.root_block->Append(var);
+
+    auto* func = b.Function("foo", ty.void_());
+    b.Append(func->Block(), [&] {  //
+        auto* ptr = b.Access(ty.ptr<workgroup, vec3<bool>>(), var, 0_u);
+        auto* el = b.LoadVectorElement(ptr, 0_u);
+        b.StoreVectorElement(ptr, 1_u, el);
+        b.Return(func);
+    });
+
+    auto* src = R"(
+S = struct @align(16) {
+  data:vec3<bool> @offset(0)
+}
+
+$B1: {  # root
+  %v:ptr<workgroup, S, read_write> = var undef
+}
+
+%foo = func():void {
+  $B2: {
+    %3:ptr<workgroup, vec3<bool>, read_write> = access %v, 0u
+    %4:bool = load_vector_element %3, 0u
+    store_vector_element %3, 1u, %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+S = struct @align(16) {
+  data:vec3<bool> @offset(0)
+}
+
+S_packed_vec3 = struct @align(16) {
+  data:__packed_vec3<u32> @offset(0)
+}
+
+$B1: {  # root
+  %v:ptr<workgroup, S_packed_vec3, read_write> = var undef
+}
+
+%foo = func():void {
+  $B2: {
+    %3:ptr<workgroup, __packed_vec3<u32>, read_write> = access %v, 0u
+    %4:u32 = load_vector_element %3, 0u
+    %5:bool = convert %4
+    %6:u32 = convert %5
+    store_vector_element %3, 1u, %6
+    ret
+  }
+}
+)";
+
+    Run(PackedVec3);
+
+    EXPECT_EQ(expect, str());
+}
+
 }  // namespace
 }  // namespace tint::msl::writer::raise