[ir] Do not wrap structs with @block attribute

Push constant structures already have a block attribute and do not
need to be wrapped, so skip them in the BlockDecoratedStructs
transform.

Change-Id: I1d564b9155cd3a2b7d6d38158b9475d7fed60583
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/209834
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/core/ir/transform/block_decorated_structs.cc b/src/tint/lang/core/ir/transform/block_decorated_structs.cc
index bc8fe39..e026fad 100644
--- a/src/tint/lang/core/ir/transform/block_decorated_structs.cc
+++ b/src/tint/lang/core/ir/transform/block_decorated_structs.cc
@@ -68,12 +68,18 @@
         auto* ptr = var->Result(0)->Type()->As<core::type::Pointer>();
         auto* store_ty = ptr->StoreType();
 
-        if (auto* str = store_ty->As<core::type::Struct>(); str && !str->HasFixedFootprint()) {
-            // We know the original struct will only ever be used as the store type of a buffer, so
-            // just mark it as a block-decorated struct.
-            // TODO(crbug.com/tint/745): Remove the const_cast.
-            const_cast<type::Struct*>(str)->SetStructFlag(type::kBlock);
-            continue;
+        if (auto* str = store_ty->As<core::type::Struct>()) {
+            if (str->StructFlags().Contains(type::kBlock)) {
+                // The struct already has a block attribute, so we don't need to do anything here.
+                continue;
+            }
+            if (!str->HasFixedFootprint()) {
+                // We know the original struct will only ever be used as the store type of a buffer,
+                // so just mark it as a block-decorated struct.
+                // TODO(crbug.com/tint/745): Remove the const_cast.
+                const_cast<type::Struct*>(str)->SetStructFlag(type::kBlock);
+                continue;
+            }
         }
 
         // The original struct might be used in other places, so create a new block-decorated
diff --git a/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc b/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
index f85e4dd..6f7ad60 100644
--- a/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
+++ b/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
@@ -394,5 +394,47 @@
     EXPECT_EQ(expect, str());
 }
 
+TEST_F(IR_BlockDecoratedStructsTest, PushConstantAlreadyHasBlockAttribute) {
+    auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+                                                                 {mod.symbols.New("i"), ty.i32()},
+                                                             });
+    structure->SetStructFlag(type::kBlock);
+
+    auto* buffer = b.Var(ty.ptr(push_constant, structure));
+    mod.root_block->Append(buffer);
+
+    auto* func = b.Function("foo", ty.i32());
+    b.Append(func->Block(), [&] {
+        auto* val_ptr = b.Access<ptr<push_constant, i32>>(buffer, 0_u);
+        b.Return(func, b.Load(val_ptr));
+    });
+
+    auto* src = R"(
+MyStruct = struct @align(4), @block {
+  i:i32 @offset(0)
+}
+
+$B1: {  # root
+  %1:ptr<push_constant, MyStruct, read> = var
+}
+
+%foo = func():i32 {
+  $B2: {
+    %3:ptr<push_constant, i32, read> = access %1, 0u
+    %4:i32 = load %3
+    ret %4
+  }
+}
+)";
+
+    EXPECT_EQ(src, str());
+
+    auto* expect = src;
+
+    Run(BlockDecoratedStructs);
+
+    EXPECT_EQ(expect, str());
+}
+
 }  // namespace
 }  // namespace tint::core::ir::transform