[msl] Add polyfill for Dot4x8Packed

Use the new 8-bit integer types to polyfill these functions by casting
to vec4<{i,u}8> and performing the calculations manually.

Bug: 42251016
Change-Id: I2b8eb226a2f1aeadfefca3d6adc980d89debb5e3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/201156
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/lang/core/ir/transform/remove_terminator_args.cc b/src/tint/lang/core/ir/transform/remove_terminator_args.cc
index 22f801a..330fe61 100644
--- a/src/tint/lang/core/ir/transform/remove_terminator_args.cc
+++ b/src/tint/lang/core/ir/transform/remove_terminator_args.cc
@@ -166,6 +166,7 @@
 Result<SuccessType> RemoveTerminatorArgs(Module& ir) {
     auto result = ValidateAndDumpIfNeeded(ir, "RemoveTerminatorArgs transform",
                                           core::ir::Capabilities{
+                                              core::ir::Capability::kAllow8BitIntegers,
                                               core::ir::Capability::kAllowPointersInStructures,
                                               core::ir::Capability::kAllowVectorElementPointer,
                                           });
diff --git a/src/tint/lang/core/ir/transform/rename_conflicts.cc b/src/tint/lang/core/ir/transform/rename_conflicts.cc
index 90de8a1..17733e7 100644
--- a/src/tint/lang/core/ir/transform/rename_conflicts.cc
+++ b/src/tint/lang/core/ir/transform/rename_conflicts.cc
@@ -295,6 +295,7 @@
 Result<SuccessType> RenameConflicts(core::ir::Module& ir) {
     auto result = ValidateAndDumpIfNeeded(ir, "RenameConflicts transform",
                                           core::ir::Capabilities{
+                                              core::ir::Capability::kAllow8BitIntegers,
                                               core::ir::Capability::kAllowPointersInStructures,
                                               core::ir::Capability::kAllowVectorElementPointer,
                                           });
diff --git a/src/tint/lang/core/ir/transform/value_to_let.cc b/src/tint/lang/core/ir/transform/value_to_let.cc
index 120e0d9..630dd32 100644
--- a/src/tint/lang/core/ir/transform/value_to_let.cc
+++ b/src/tint/lang/core/ir/transform/value_to_let.cc
@@ -176,6 +176,7 @@
 Result<SuccessType> ValueToLet(Module& ir) {
     auto result = ValidateAndDumpIfNeeded(ir, "ValueToLet transform",
                                           core::ir::Capabilities{
+                                              core::ir::Capability::kAllow8BitIntegers,
                                               core::ir::Capability::kAllowPointersInStructures,
                                               core::ir::Capability::kAllowVectorElementPointer,
                                           });
diff --git a/src/tint/lang/msl/writer/printer/printer.cc b/src/tint/lang/msl/writer/printer/printer.cc
index c1919f6..2d6d849 100644
--- a/src/tint/lang/msl/writer/printer/printer.cc
+++ b/src/tint/lang/msl/writer/printer/printer.cc
@@ -77,6 +77,7 @@
 #include "src/tint/lang/core/type/f16.h"
 #include "src/tint/lang/core/type/f32.h"
 #include "src/tint/lang/core/type/i32.h"
+#include "src/tint/lang/core/type/i8.h"
 #include "src/tint/lang/core/type/matrix.h"
 #include "src/tint/lang/core/type/multisampled_texture.h"
 #include "src/tint/lang/core/type/pointer.h"
@@ -84,6 +85,7 @@
 #include "src/tint/lang/core/type/storage_texture.h"
 #include "src/tint/lang/core/type/texture.h"
 #include "src/tint/lang/core/type/u32.h"
+#include "src/tint/lang/core/type/u8.h"
 #include "src/tint/lang/core/type/vector.h"
 #include "src/tint/lang/core/type/void.h"
 #include "src/tint/lang/msl/barrier_type.h"
@@ -119,6 +121,7 @@
         auto valid =
             core::ir::ValidateAndDumpIfNeeded(ir_, "MSL writer",
                                               core::ir::Capabilities{
+                                                  core::ir::Capability::kAllow8BitIntegers,
                                                   core::ir::Capability::kAllowPointersInStructures,
                                               });
         if (valid != Success) {
@@ -403,7 +406,7 @@
                 [&](const core::ir::LoadVectorElement*) { /* inlined */ },  //
                 [&](const core::ir::Swizzle*) { /* inlined */ },            //
                 [&](const core::ir::Bitcast*) { /* inlined */ },            //
-                [&](const core::ir::CoreBinary*) { /* inlined */ },         //
+                [&](const core::ir::Binary*) { /* inlined */ },             //
                 [&](const core::ir::CoreUnary*) { /* inlined */ },          //
                 [&](const core::ir::Load*) { /* inlined */ },               //
                 [&](const core::ir::Construct*) { /* inlined */ },          //
@@ -419,7 +422,7 @@
             [&](const core::ir::InstructionResult* r) {
                 Switch(
                     r->Instruction(),                                                    //
-                    [&](const core::ir::CoreBinary* b) { EmitBinary(out, b); },          //
+                    [&](const core::ir::Binary* b) { EmitBinary(out, b); },              //
                     [&](const core::ir::CoreUnary* u) { EmitUnary(out, u); },            //
                     [&](const core::ir::Convert* b) { EmitConvert(out, b); },            //
                     [&](const core::ir::Let* l) { out << NameOf(l->Result(0)); },        //
@@ -465,7 +468,7 @@
 
     /// Emit a binary instruction
     /// @param b the binary instruction
-    void EmitBinary(StringStream& out, const core::ir::CoreBinary* b) {
+    void EmitBinary(StringStream& out, const core::ir::Binary* b) {
         auto kind = [&] {
             switch (b->Op()) {
                 case core::BinaryOp::kAdd:
@@ -1100,6 +1103,8 @@
             [&](const core::type::F16*) { out << "half"; },   //
             [&](const core::type::I32*) { out << "int"; },    //
             [&](const core::type::U32*) { out << "uint"; },   //
+            [&](const core::type::I8*) { out << "char"; },    //
+            [&](const core::type::U8*) { out << "uchar"; },   //
             [&](const core::type::Array* arr) { EmitArrayType(out, arr); },
             [&](const core::type::Vector* vec) { EmitVectorType(out, vec); },
             [&](const core::type::Matrix* mat) { EmitMatrixType(out, mat); },
diff --git a/src/tint/lang/msl/writer/raise/builtin_polyfill.cc b/src/tint/lang/msl/writer/raise/builtin_polyfill.cc
index 41eb46d..4c183f4 100644
--- a/src/tint/lang/msl/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/msl/writer/raise/builtin_polyfill.cc
@@ -46,6 +46,7 @@
 #include "src/tint/lang/core/type/vector.h"
 #include "src/tint/lang/msl/barrier_type.h"
 #include "src/tint/lang/msl/builtin_fn.h"
+#include "src/tint/lang/msl/ir/binary.h"
 #include "src/tint/lang/msl/ir/builtin_call.h"
 #include "src/tint/lang/msl/ir/component.h"
 #include "src/tint/lang/msl/ir/member_builtin_call.h"
@@ -78,6 +79,9 @@
     /// A map from an integer vector type to a dot polyfill.
     Hashmap<const core::type::Vector*, core::ir::Function*, 4> integer_dot_polyfills{};
 
+    /// A map from an integer type to a packed 8-bit dot polyfill.
+    Hashmap<const core::type::Type*, core::ir::Function*, 2> packed_8bit_integer_dot_polyfills{};
+
     /// Process the module.
     void Process() {
         // Find the builtins that need replacing.
@@ -98,6 +102,8 @@
                     case core::BuiltinFn::kAtomicXor:
                     case core::BuiltinFn::kDistance:
                     case core::BuiltinFn::kDot:
+                    case core::BuiltinFn::kDot4I8Packed:
+                    case core::BuiltinFn::kDot4U8Packed:
                     case core::BuiltinFn::kFrexp:
                     case core::BuiltinFn::kLength:
                     case core::BuiltinFn::kModf:
@@ -175,6 +181,10 @@
                 case core::BuiltinFn::kDot:
                     Dot(builtin);
                     break;
+                case core::BuiltinFn::kDot4I8Packed:
+                case core::BuiltinFn::kDot4U8Packed:
+                    Dot4x8Packed(builtin);
+                    break;
                 case core::BuiltinFn::kFrexp:
                     Frexp(builtin);
                     break;
@@ -371,6 +381,51 @@
         builtin->Destroy();
     }
 
+    /// Polyfill a packed 8-bit dot product call.
+    /// @param builtin the builtin call instruction
+    void Dot4x8Packed(core::ir::CoreBuiltinCall* builtin) {
+        b.InsertBefore(builtin, [&] {
+            auto* arg0 = builtin->Args()[0];
+            auto* arg1 = builtin->Args()[1];
+            auto* int32 = builtin->Result(0)->Type();
+            auto* int8 = int32->Is<core::type::I32>()
+                             ? static_cast<const core::type::Type*>(ty.i8())
+                             : static_cast<const core::type::Type*>(ty.u8());
+            // Calls to packed 8-bit dot products are polyfilled by casting to [u]char4, performing
+            // the dot product, and converting the result to a {i,u}32:
+            //   uchar4 vec1 = as_type<uchar4>(param_0);
+            //   uchar4 vec2 = as_type<uchar4>(param_1);
+            //   result = uint(vec1[0] * vec2[0] + vec1[1] * vec2[1]
+            //               + vec1[2] * vec2[2] + vec1[3] * vec2[3]);
+            auto* polyfill = packed_8bit_integer_dot_polyfills.GetOrAdd(int32, [&] {
+                auto* lhs_32 = b.FunctionParam("lhs", ty.u32());
+                auto* rhs_32 = b.FunctionParam("rhs", ty.u32());
+                auto* func = b.Function("tint_packed_8bit_dot", int32);
+                func->SetParams({lhs_32, rhs_32});
+                b.Append(func->Block(), [&] {
+                    auto* lhs = b.Bitcast(ty.vec4(int8), lhs_32);
+                    auto* rhs = b.Bitcast(ty.vec4(int8), rhs_32);
+                    core::ir::Value* sum = nullptr;
+                    for (uint32_t i = 0; i < 4; i++) {
+                        auto* l = b.Access(int8, lhs, u32(i));
+                        auto* r = b.Access(int8, rhs, u32(i));
+                        auto* mul = b.Binary<ir::Binary>(core::BinaryOp::kMultiply, int8, l, r);
+                        if (sum) {
+                            auto* add = b.Binary<ir::Binary>(core::BinaryOp::kAdd, int8, sum, mul);
+                            sum = add->Result(0);
+                        } else {
+                            sum = mul->Result(0);
+                        }
+                    }
+                    b.Return(func, b.Convert(int32, sum));
+                });
+                return func;
+            });
+            b.CallWithResult(builtin->DetachResult(), polyfill, arg0, arg1);
+        });
+        builtin->Destroy();
+    }
+
     /// Polyfill a frexp call.
     /// @param builtin the builtin call instruction
     void Frexp(core::ir::CoreBuiltinCall* builtin) {
diff --git a/src/tint/lang/msl/writer/raise/builtin_polyfill_test.cc b/src/tint/lang/msl/writer/raise/builtin_polyfill_test.cc
index 5c1a409..d7c7dfe 100644
--- a/src/tint/lang/msl/writer/raise/builtin_polyfill_test.cc
+++ b/src/tint/lang/msl/writer/raise/builtin_polyfill_test.cc
@@ -1022,6 +1022,211 @@
     EXPECT_EQ(expect, str());
 }
 
+TEST_F(MslWriter_BuiltinPolyfillTest, Dot4I8Packed) {
+    auto* value0 = b.FunctionParam<u32>("value0");
+    auto* value1 = b.FunctionParam<u32>("value1");
+    auto* func = b.Function("foo", ty.i32());
+    func->SetParams({value0, value1});
+    b.Append(func->Block(), [&] {
+        auto* result = b.Call<i32>(core::BuiltinFn::kDot4I8Packed, value0, value1);
+        b.Return(func, result);
+    });
+
+    auto* src = R"(
+%foo = func(%value0:u32, %value1:u32):i32 {
+  $B1: {
+    %4:i32 = dot4I8Packed %value0, %value1
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = func(%value0:u32, %value1:u32):i32 {
+  $B1: {
+    %4:i32 = call %tint_packed_8bit_dot, %value0, %value1
+    ret %4
+  }
+}
+%tint_packed_8bit_dot = func(%lhs:u32, %rhs:u32):i32 {
+  $B2: {
+    %8:vec4<i8> = bitcast %lhs
+    %9:vec4<i8> = bitcast %rhs
+    %10:i8 = access %8, 0u
+    %11:i8 = access %9, 0u
+    %12:i8 = mul %10, %11
+    %13:i8 = access %8, 1u
+    %14:i8 = access %9, 1u
+    %15:i8 = mul %13, %14
+    %16:i8 = add %12, %15
+    %17:i8 = access %8, 2u
+    %18:i8 = access %9, 2u
+    %19:i8 = mul %17, %18
+    %20:i8 = add %16, %19
+    %21:i8 = access %8, 3u
+    %22:i8 = access %9, 3u
+    %23:i8 = mul %21, %22
+    %24:i8 = add %20, %23
+    %25:i32 = convert %24
+    ret %25
+  }
+}
+)";
+
+    capabilities.Add(core::ir::Capability::kAllow8BitIntegers);
+    Run(BuiltinPolyfill);
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(MslWriter_BuiltinPolyfillTest, Dot4U8Packed) {
+    auto* value0 = b.FunctionParam<u32>("value0");
+    auto* value1 = b.FunctionParam<u32>("value1");
+    auto* func = b.Function("foo", ty.u32());
+    func->SetParams({value0, value1});
+    b.Append(func->Block(), [&] {
+        auto* result = b.Call<u32>(core::BuiltinFn::kDot4U8Packed, value0, value1);
+        b.Return(func, result);
+    });
+
+    auto* src = R"(
+%foo = func(%value0:u32, %value1:u32):u32 {
+  $B1: {
+    %4:u32 = dot4U8Packed %value0, %value1
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = func(%value0:u32, %value1:u32):u32 {
+  $B1: {
+    %4:u32 = call %tint_packed_8bit_dot, %value0, %value1
+    ret %4
+  }
+}
+%tint_packed_8bit_dot = func(%lhs:u32, %rhs:u32):u32 {
+  $B2: {
+    %8:vec4<u8> = bitcast %lhs
+    %9:vec4<u8> = bitcast %rhs
+    %10:u8 = access %8, 0u
+    %11:u8 = access %9, 0u
+    %12:u8 = mul %10, %11
+    %13:u8 = access %8, 1u
+    %14:u8 = access %9, 1u
+    %15:u8 = mul %13, %14
+    %16:u8 = add %12, %15
+    %17:u8 = access %8, 2u
+    %18:u8 = access %9, 2u
+    %19:u8 = mul %17, %18
+    %20:u8 = add %16, %19
+    %21:u8 = access %8, 3u
+    %22:u8 = access %9, 3u
+    %23:u8 = mul %21, %22
+    %24:u8 = add %20, %23
+    %25:u32 = convert %24
+    ret %25
+  }
+}
+)";
+
+    capabilities.Add(core::ir::Capability::kAllow8BitIntegers);
+    Run(BuiltinPolyfill);
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(MslWriter_BuiltinPolyfillTest, Dot4x8Packed_MultipleCalls) {
+    auto* v = b.FunctionParam<u32>("v");
+    auto* func = b.Function("foo", ty.void_());
+    func->SetParams({v, v});
+    b.Append(func->Block(), [&] {
+        b.Call<i32>(core::BuiltinFn::kDot4I8Packed, v, v);
+        b.Call<i32>(core::BuiltinFn::kDot4I8Packed, v, v);
+        b.Call<u32>(core::BuiltinFn::kDot4U8Packed, v, v);
+        b.Call<u32>(core::BuiltinFn::kDot4U8Packed, v, v);
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = func(%v:u32%v:u32):void {
+  $B1: {
+    %3:i32 = dot4I8Packed %v, %v
+    %4:i32 = dot4I8Packed %v, %v
+    %5:u32 = dot4U8Packed %v, %v
+    %6:u32 = dot4U8Packed %v, %v
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = func(%v:u32%v:u32):void {
+  $B1: {
+    %3:i32 = call %tint_packed_8bit_dot, %v, %v
+    %5:i32 = call %tint_packed_8bit_dot, %v, %v
+    %6:u32 = call %tint_packed_8bit_dot_1, %v, %v
+    %8:u32 = call %tint_packed_8bit_dot_1, %v, %v
+    ret
+  }
+}
+%tint_packed_8bit_dot = func(%lhs:u32, %rhs:u32):i32 {
+  $B2: {
+    %11:vec4<i8> = bitcast %lhs
+    %12:vec4<i8> = bitcast %rhs
+    %13:i8 = access %11, 0u
+    %14:i8 = access %12, 0u
+    %15:i8 = mul %13, %14
+    %16:i8 = access %11, 1u
+    %17:i8 = access %12, 1u
+    %18:i8 = mul %16, %17
+    %19:i8 = add %15, %18
+    %20:i8 = access %11, 2u
+    %21:i8 = access %12, 2u
+    %22:i8 = mul %20, %21
+    %23:i8 = add %19, %22
+    %24:i8 = access %11, 3u
+    %25:i8 = access %12, 3u
+    %26:i8 = mul %24, %25
+    %27:i8 = add %23, %26
+    %28:i32 = convert %27
+    ret %28
+  }
+}
+%tint_packed_8bit_dot_1 = func(%lhs_1:u32, %rhs_1:u32):u32 {  # %tint_packed_8bit_dot_1: 'tint_packed_8bit_dot', %lhs_1: 'lhs', %rhs_1: 'rhs'
+  $B3: {
+    %31:vec4<u8> = bitcast %lhs_1
+    %32:vec4<u8> = bitcast %rhs_1
+    %33:u8 = access %31, 0u
+    %34:u8 = access %32, 0u
+    %35:u8 = mul %33, %34
+    %36:u8 = access %31, 1u
+    %37:u8 = access %32, 1u
+    %38:u8 = mul %36, %37
+    %39:u8 = add %35, %38
+    %40:u8 = access %31, 2u
+    %41:u8 = access %32, 2u
+    %42:u8 = mul %40, %41
+    %43:u8 = add %39, %42
+    %44:u8 = access %31, 3u
+    %45:u8 = access %32, 3u
+    %46:u8 = mul %44, %45
+    %47:u8 = add %43, %46
+    %48:u32 = convert %47
+    ret %48
+  }
+}
+)";
+
+    capabilities.Add(core::ir::Capability::kAllow8BitIntegers);
+    Run(BuiltinPolyfill);
+
+    EXPECT_EQ(expect, str());
+}
+
 TEST_F(MslWriter_BuiltinPolyfillTest, Frexp_Scalar) {
     auto* value = b.FunctionParam<f32>("value");
     auto* func = b.Function("foo", ty.f32());
diff --git a/test/tint/builtins/gen/var/dot4I8Packed/881e62.wgsl.expected.ir.msl b/test/tint/builtins/gen/var/dot4I8Packed/881e62.wgsl.expected.ir.msl
index 00ec0fe..c6f910a 100644
--- a/test/tint/builtins/gen/var/dot4I8Packed/881e62.wgsl.expected.ir.msl
+++ b/test/tint/builtins/gen/var/dot4I8Packed/881e62.wgsl.expected.ir.msl
@@ -1,9 +1,51 @@
-SKIP: FAILED
+#include <metal_stdlib>
+using namespace metal;
 
-../../src/tint/lang/msl/writer/printer/printer.cc:989 internal compiler error: TINT_UNREACHABLE unhandled: dot4I8Packed
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
+struct tint_module_vars_struct {
+  device int* prevent_dce;
+};
+
+struct VertexOutput {
+  float4 pos;
+  int prevent_dce;
+};
+
+struct vertex_main_outputs {
+  float4 VertexOutput_pos [[position]];
+  int VertexOutput_prevent_dce [[user(locn0)]] [[flat]];
+};
+
+int tint_packed_8bit_dot(int lhs, int rhs) {
+  char4 const v = as_type<char4>(lhs);
+  char4 const v_1 = as_type<char4>(rhs);
+  return int(((((v[0u] * v_1[0u]) + (v[1u] * v_1[1u])) + (v[2u] * v_1[2u])) + (v[3u] * v_1[3u])));
+}
+
+int dot4I8Packed_881e62() {
+  uint arg_0 = 1u;
+  uint arg_1 = 1u;
+  int res = tint_packed_8bit_dot(arg_0, arg_1);
+  return res;
+}
+
+fragment void fragment_main(device int* prevent_dce [[buffer(0)]]) {
+  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.prevent_dce=prevent_dce};
+  (*tint_module_vars.prevent_dce) = dot4I8Packed_881e62();
+}
+
+kernel void compute_main(device int* prevent_dce [[buffer(0)]]) {
+  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.prevent_dce=prevent_dce};
+  (*tint_module_vars.prevent_dce) = dot4I8Packed_881e62();
+}
+
+VertexOutput vertex_main_inner() {
+  VertexOutput out = {};
+  out.pos = float4(0.0f);
+  out.prevent_dce = dot4I8Packed_881e62();
+  return out;
+}
+
+vertex vertex_main_outputs vertex_main() {
+  VertexOutput const v_2 = vertex_main_inner();
+  return vertex_main_outputs{.VertexOutput_pos=v_2.pos, .VertexOutput_prevent_dce=v_2.prevent_dce};
+}
diff --git a/test/tint/builtins/gen/var/dot4U8Packed/fbed7b.wgsl.expected.ir.msl b/test/tint/builtins/gen/var/dot4U8Packed/fbed7b.wgsl.expected.ir.msl
index e0f4a9e..0b0c145 100644
--- a/test/tint/builtins/gen/var/dot4U8Packed/fbed7b.wgsl.expected.ir.msl
+++ b/test/tint/builtins/gen/var/dot4U8Packed/fbed7b.wgsl.expected.ir.msl
@@ -1,9 +1,51 @@
-SKIP: FAILED
+#include <metal_stdlib>
+using namespace metal;
 
-../../src/tint/lang/msl/writer/printer/printer.cc:989 internal compiler error: TINT_UNREACHABLE unhandled: dot4U8Packed
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
+struct tint_module_vars_struct {
+  device uint* prevent_dce;
+};
+
+struct VertexOutput {
+  float4 pos;
+  uint prevent_dce;
+};
+
+struct vertex_main_outputs {
+  float4 VertexOutput_pos [[position]];
+  uint VertexOutput_prevent_dce [[user(locn0)]] [[flat]];
+};
+
+uint tint_packed_8bit_dot(uint lhs, uint rhs) {
+  uchar4 const v = as_type<uchar4>(lhs);
+  uchar4 const v_1 = as_type<uchar4>(rhs);
+  return uint(((((v[0u] * v_1[0u]) + (v[1u] * v_1[1u])) + (v[2u] * v_1[2u])) + (v[3u] * v_1[3u])));
+}
+
+uint dot4U8Packed_fbed7b() {
+  uint arg_0 = 1u;
+  uint arg_1 = 1u;
+  uint res = tint_packed_8bit_dot(arg_0, arg_1);
+  return res;
+}
+
+fragment void fragment_main(device uint* prevent_dce [[buffer(0)]]) {
+  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.prevent_dce=prevent_dce};
+  (*tint_module_vars.prevent_dce) = dot4U8Packed_fbed7b();
+}
+
+kernel void compute_main(device uint* prevent_dce [[buffer(0)]]) {
+  tint_module_vars_struct const tint_module_vars = tint_module_vars_struct{.prevent_dce=prevent_dce};
+  (*tint_module_vars.prevent_dce) = dot4U8Packed_fbed7b();
+}
+
+VertexOutput vertex_main_inner() {
+  VertexOutput out = {};
+  out.pos = float4(0.0f);
+  out.prevent_dce = dot4U8Packed_fbed7b();
+  return out;
+}
+
+vertex vertex_main_outputs vertex_main() {
+  VertexOutput const v_2 = vertex_main_inner();
+  return vertex_main_outputs{.VertexOutput_pos=v_2.pos, .VertexOutput_prevent_dce=v_2.prevent_dce};
+}