[glsl][ir] Add bitcast from/to f16.

This CL adds bitcast for f16 types to the GLSL IR backend.

Bug: 42251044
Change-Id: Ib7e6a810c7da4f238c1f6967c5ac23a91893117c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/206719
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/glsl/builtin_fn.cc b/src/tint/lang/glsl/builtin_fn.cc
index 202c6c8..aa1c5fa 100644
--- a/src/tint/lang/glsl/builtin_fn.cc
+++ b/src/tint/lang/glsl/builtin_fn.cc
@@ -60,6 +60,10 @@
             return "intBitsToFloat";
         case BuiltinFn::kUintBitsToFloat:
             return "uintBitsToFloat";
+        case BuiltinFn::kPackFloat2X16:
+            return "packFloat2x16";
+        case BuiltinFn::kUnpackFloat2X16:
+            return "unpackFloat2x16";
     }
     return "<unknown>";
 }
diff --git a/src/tint/lang/glsl/builtin_fn.h b/src/tint/lang/glsl/builtin_fn.h
index b003094..5477474 100644
--- a/src/tint/lang/glsl/builtin_fn.h
+++ b/src/tint/lang/glsl/builtin_fn.h
@@ -56,6 +56,8 @@
     kFloatBitsToUint,
     kIntBitsToFloat,
     kUintBitsToFloat,
+    kPackFloat2X16,
+    kUnpackFloat2X16,
     kNone,
 };
 
diff --git a/src/tint/lang/glsl/glsl.def b/src/tint/lang/glsl/glsl.def
index 3209365..ffe53e8 100644
--- a/src/tint/lang/glsl/glsl.def
+++ b/src/tint/lang/glsl/glsl.def
@@ -42,11 +42,14 @@
 // Types                                                                      //
 ////////////////////////////////////////////////////////////////////////////////
 
+type f16
 type f32
 type i32
 type u32
 type atomic<T>
 type ptr<S: address_space, T, A: access>
+
+type vec2<T>
 @display("vec{N}<{T}>")     type vec<N: num, T>
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -87,3 +90,5 @@
 fn uintBitsToFloat(value: u32) -> f32
 implicit(N: num) fn uintBitsToFloat(value: vec<N, u32>) -> vec<N, f32>
 
+fn packFloat2x16(value: vec2<f16>) -> u32
+fn unpackFloat2x16(value: u32) -> vec2<f16>
diff --git a/src/tint/lang/glsl/intrinsic/data.cc b/src/tint/lang/glsl/intrinsic/data.cc
index ce47e3f..7cb8545 100644
--- a/src/tint/lang/glsl/intrinsic/data.cc
+++ b/src/tint/lang/glsl/intrinsic/data.cc
@@ -74,6 +74,20 @@
 
 // clang-format off
 
+/// TypeMatcher for 'type f16'
+constexpr TypeMatcher kF16Matcher {
+/* match */ [](MatchState& state, const Type* ty) -> const Type* {
+    if (!MatchF16(state, ty)) {
+      return nullptr;
+    }
+    return BuildF16(state, ty);
+  },
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+    out << style::Type("f16");
+  }
+};
+
+
 /// TypeMatcher for 'type f32'
 constexpr TypeMatcher kF32Matcher {
 /* match */ [](MatchState& state, const Type* ty) -> const Type* {
@@ -168,6 +182,26 @@
 };
 
 
+/// TypeMatcher for 'type vec2'
+constexpr TypeMatcher kVec2Matcher {
+/* match */ [](MatchState& state, const Type* ty) -> const Type* {
+  const Type* T = nullptr;
+    if (!MatchVec2(state, ty, T)) {
+      return nullptr;
+    }
+    T = state.Type(T);
+    if (T == nullptr) {
+      return nullptr;
+    }
+    return BuildVec2(state, ty, T);
+  },
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+  state->PrintType(T);
+    out << style::Type("vec2", "<", T, ">");
+  }
+};
+
+
 /// TypeMatcher for 'type vec'
 constexpr TypeMatcher kVecMatcher {
 /* match */ [](MatchState& state, const Type* ty) -> const Type* {
@@ -246,13 +280,15 @@
 constexpr TypeMatcher kTypeMatchers[] = {
   /* [0] */ TemplateTypeMatcher<0>::matcher,
   /* [1] */ TemplateTypeMatcher<1>::matcher,
-  /* [2] */ kF32Matcher,
-  /* [3] */ kI32Matcher,
-  /* [4] */ kU32Matcher,
-  /* [5] */ kAtomicMatcher,
-  /* [6] */ kPtrMatcher,
-  /* [7] */ kVecMatcher,
-  /* [8] */ kIu32Matcher,
+  /* [2] */ kF16Matcher,
+  /* [3] */ kF32Matcher,
+  /* [4] */ kI32Matcher,
+  /* [5] */ kU32Matcher,
+  /* [6] */ kAtomicMatcher,
+  /* [7] */ kPtrMatcher,
+  /* [8] */ kVec2Matcher,
+  /* [9] */ kVecMatcher,
+  /* [10] */ kIu32Matcher,
 };
 
 /// The template numbers, and number matchers
@@ -264,26 +300,28 @@
 };
 
 constexpr MatcherIndex kMatcherIndices[] = {
-  /* [0] */ MatcherIndex(6),
+  /* [0] */ MatcherIndex(7),
   /* [1] */ MatcherIndex(3),
-  /* [2] */ MatcherIndex(5),
+  /* [2] */ MatcherIndex(6),
   /* [3] */ MatcherIndex(0),
   /* [4] */ MatcherIndex(2),
-  /* [5] */ MatcherIndex(6),
+  /* [5] */ MatcherIndex(7),
   /* [6] */ MatcherIndex(1),
-  /* [7] */ MatcherIndex(5),
+  /* [7] */ MatcherIndex(6),
   /* [8] */ MatcherIndex(0),
   /* [9] */ MatcherIndex(2),
-  /* [10] */ MatcherIndex(7),
+  /* [10] */ MatcherIndex(9),
   /* [11] */ MatcherIndex(0),
-  /* [12] */ MatcherIndex(3),
-  /* [13] */ MatcherIndex(7),
+  /* [12] */ MatcherIndex(4),
+  /* [13] */ MatcherIndex(9),
   /* [14] */ MatcherIndex(0),
-  /* [15] */ MatcherIndex(2),
-  /* [16] */ MatcherIndex(7),
+  /* [15] */ MatcherIndex(3),
+  /* [16] */ MatcherIndex(9),
   /* [17] */ MatcherIndex(0),
-  /* [18] */ MatcherIndex(4),
+  /* [18] */ MatcherIndex(5),
   /* [19] */ MatcherIndex(8),
+  /* [20] */ MatcherIndex(2),
+  /* [21] */ MatcherIndex(10),
 };
 
 static_assert(MatcherIndicesIndex::CanIndex(kMatcherIndices),
@@ -318,7 +356,7 @@
   {
     /* [5] */
     /* usage */ core::ParameterUsage::kValue,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [6] */
@@ -328,7 +366,7 @@
   {
     /* [7] */
     /* usage */ core::ParameterUsage::kValue,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(12),
   },
   {
     /* [8] */
@@ -345,6 +383,11 @@
     /* usage */ core::ParameterUsage::kValue,
     /* matcher_indices */ MatcherIndicesIndex(16),
   },
+  {
+    /* [11] */
+    /* usage */ core::ParameterUsage::kValue,
+    /* matcher_indices */ MatcherIndicesIndex(19),
+  },
 };
 
 static_assert(ParameterIndex::CanIndex(kParameters),
@@ -354,7 +397,7 @@
   {
     /* [0] */
     /* name */ "T",
-    /* matcher_indices */ MatcherIndicesIndex(19),
+    /* matcher_indices */ MatcherIndicesIndex(21),
     /* kind */ TemplateInfo::Kind::kType,
   },
   {
@@ -383,7 +426,7 @@
     /* num_templates   */ 0,
     /* templates */ TemplateIndex(/* invalid */),
     /* parameters */ ParameterIndex(5),
-    /* return_matcher_indices */ MatcherIndicesIndex(1),
+    /* return_matcher_indices */ MatcherIndicesIndex(12),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
@@ -427,7 +470,7 @@
     /* num_templates   */ 0,
     /* templates */ TemplateIndex(/* invalid */),
     /* parameters */ ParameterIndex(7),
-    /* return_matcher_indices */ MatcherIndicesIndex(4),
+    /* return_matcher_indices */ MatcherIndicesIndex(1),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
@@ -449,7 +492,7 @@
     /* num_templates   */ 0,
     /* templates */ TemplateIndex(/* invalid */),
     /* parameters */ ParameterIndex(9),
-    /* return_matcher_indices */ MatcherIndicesIndex(4),
+    /* return_matcher_indices */ MatcherIndicesIndex(1),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
@@ -496,6 +539,28 @@
     /* return_matcher_indices */ MatcherIndicesIndex(3),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
+  {
+    /* [11] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_explicit_templates */ 0,
+    /* num_templates   */ 0,
+    /* templates */ TemplateIndex(/* invalid */),
+    /* parameters */ ParameterIndex(11),
+    /* return_matcher_indices */ MatcherIndicesIndex(18),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [12] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_explicit_templates */ 0,
+    /* num_templates   */ 0,
+    /* templates */ TemplateIndex(/* invalid */),
+    /* parameters */ ParameterIndex(9),
+    /* return_matcher_indices */ MatcherIndicesIndex(19),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
 };
 
 static_assert(OverloadIndex::CanIndex(kOverloads),
@@ -560,6 +625,18 @@
     /* num overloads */ 2,
     /* overloads */ OverloadIndex(6),
   },
+  {
+    /* [9] */
+    /* fn packFloat2x16(value: vec2<f16>) -> u32 */
+    /* num overloads */ 1,
+    /* overloads */ OverloadIndex(11),
+  },
+  {
+    /* [10] */
+    /* fn unpackFloat2x16(value: u32) -> vec2<f16> */
+    /* num overloads */ 1,
+    /* overloads */ OverloadIndex(12),
+  },
 };
 
 // clang-format on
diff --git a/src/tint/lang/glsl/writer/builtin_test.cc b/src/tint/lang/glsl/writer/builtin_test.cc
index fdaacf9..b61be59 100644
--- a/src/tint/lang/glsl/writer/builtin_test.cc
+++ b/src/tint/lang/glsl/writer/builtin_test.cc
@@ -545,5 +545,290 @@
 )");
 }
 
+TEST_F(GlslWriterTest, BuiltinBitcast_I32ToVec2F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", 1_i);
+        b.Let("x", b.Bitcast<vec2<f16>>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+f16vec2 tint_bitcast_to_f16(int src) {
+  return unpackFloat2x16(uint(src));
+}
+void main() {
+  int a = 1;
+  f16vec2 x = tint_bitcast_to_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_Vec2F16ToI32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<f16>>(1_h, 2_h));
+        b.Let("x", b.Bitcast<i32>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+int tint_bitcast_from_f16(f16vec2 src) {
+  return int(packFloat2x16(src));
+}
+void main() {
+  f16vec2 a = f16vec2(1.0hf, 2.0hf);
+  int x = tint_bitcast_from_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_U32ToVec2F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", 1_u);
+        b.Let("x", b.Bitcast<vec2<f16>>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+f16vec2 tint_bitcast_to_f16(uint src) {
+  return unpackFloat2x16(uint(src));
+}
+void main() {
+  uint a = 1u;
+  f16vec2 x = tint_bitcast_to_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_Vec2F16ToU32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<f16>>(1_h, 2_h));
+        b.Let("x", b.Bitcast<u32>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+uint tint_bitcast_from_f16(f16vec2 src) {
+  return uint(packFloat2x16(src));
+}
+void main() {
+  f16vec2 a = f16vec2(1.0hf, 2.0hf);
+  uint x = tint_bitcast_from_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_F32ToVec2F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", 1_f);
+        b.Let("x", b.Bitcast<vec2<f16>>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+f16vec2 tint_bitcast_to_f16(float src) {
+  return unpackFloat2x16(floatBitsToUint(src));
+}
+void main() {
+  float a = 1.0f;
+  f16vec2 x = tint_bitcast_to_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_Vec2F16ToF32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<f16>>(1_h, 2_h));
+        b.Let("x", b.Bitcast<f32>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+float tint_bitcast_from_f16(f16vec2 src) {
+  return uintBitsToFloat(packFloat2x16(src));
+}
+void main() {
+  f16vec2 a = f16vec2(1.0hf, 2.0hf);
+  float x = tint_bitcast_from_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_Vec2I32ToVec4F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<i32>>(1_i, 2_i));
+        b.Let("x", b.Bitcast<vec4<f16>>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+f16vec4 tint_bitcast_to_f16(ivec2 src) {
+  uvec2 v = uvec2(src);
+  f16vec2 v_1 = unpackFloat2x16(v.x);
+  return f16vec4(v_1, unpackFloat2x16(v.y));
+}
+void main() {
+  ivec2 a = ivec2(1, 2);
+  f16vec4 x = tint_bitcast_to_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_Vec4F16ToVec2I32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec4<f16>>(1_h, 2_h, 3_h, 4_h));
+        b.Let("x", b.Bitcast<vec2<i32>>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+ivec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v = packFloat2x16(src.xy);
+  return ivec2(uvec2(v, packFloat2x16(src.zw)));
+}
+void main() {
+  f16vec4 a = f16vec4(1.0hf, 2.0hf, 3.0hf, 4.0hf);
+  ivec2 x = tint_bitcast_from_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_Vec2U32ToVec4F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<u32>>(1_u, 2_u));
+        b.Let("x", b.Bitcast<vec4<f16>>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+f16vec4 tint_bitcast_to_f16(uvec2 src) {
+  uvec2 v = uvec2(src);
+  f16vec2 v_1 = unpackFloat2x16(v.x);
+  return f16vec4(v_1, unpackFloat2x16(v.y));
+}
+void main() {
+  uvec2 a = uvec2(1u, 2u);
+  f16vec4 x = tint_bitcast_to_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_Vec4F16ToVec2U32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec4<f16>>(1_h, 2_h, 3_h, 4_h));
+        b.Let("x", b.Bitcast<vec2<u32>>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+uvec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v = packFloat2x16(src.xy);
+  return uvec2(uvec2(v, packFloat2x16(src.zw)));
+}
+void main() {
+  f16vec4 a = f16vec4(1.0hf, 2.0hf, 3.0hf, 4.0hf);
+  uvec2 x = tint_bitcast_from_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_Vec2F32ToVec4F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<f32>>(1_f, 2_f));
+        b.Let("x", b.Bitcast<vec4<f16>>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+f16vec4 tint_bitcast_to_f16(vec2 src) {
+  uvec2 v = floatBitsToUint(src);
+  f16vec2 v_1 = unpackFloat2x16(v.x);
+  return f16vec4(v_1, unpackFloat2x16(v.y));
+}
+void main() {
+  vec2 a = vec2(1.0f, 2.0f);
+  f16vec4 x = tint_bitcast_to_f16(a);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, BuiltinBitcast_Vec4F16ToVec2F32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec4<f16>>(1_h, 2_h, 3_h, 4_h));
+        b.Let("x", b.Bitcast<vec2<f32>>(a));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
+
+vec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v = packFloat2x16(src.xy);
+  return uintBitsToFloat(uvec2(v, packFloat2x16(src.zw)));
+}
+void main() {
+  f16vec4 a = f16vec4(1.0hf, 2.0hf, 3.0hf, 4.0hf);
+  vec2 x = tint_bitcast_from_f16(a);
+}
+)");
+}
+
 }  // namespace
 }  // namespace tint::glsl::writer
diff --git a/src/tint/lang/glsl/writer/raise/builtin_polyfill.cc b/src/tint/lang/glsl/writer/raise/builtin_polyfill.cc
index a38f10d..1bb8785 100644
--- a/src/tint/lang/glsl/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/glsl/writer/raise/builtin_polyfill.cc
@@ -127,11 +127,9 @@
             if (src_type == dst_type) {
                 ReplaceBitcastWithValue(bitcast);
             } else if (src_type->DeepestElement()->Is<core::type::F16>()) {
-                // TODO(dsinclair): Polyfill from f16
-                TINT_UNREACHABLE();
+                ReplaceBitcastWithFromF16Polyfill(bitcast);
             } else if (dst_deepest->Is<core::type::F16>()) {
-                // TODO(dsinclair): Polyfill to f16
-                TINT_UNREACHABLE();
+                ReplaceBitcastWithToF16Polyfill(bitcast);
             } else if (src_type->DeepestElement()->Is<core::type::F32>()) {
                 ReplaceBitcastFromF32(bitcast);
             } else if (dst_type->DeepestElement()->Is<core::type::F32>()) {
@@ -147,36 +145,51 @@
         bitcast->Destroy();
     }
 
-    void ReplaceBitcastFromF32(core::ir::Bitcast* bitcast) {
-        auto* dst_type = bitcast->Result(0)->Type();
-        auto* dst_deepest = dst_type->DeepestElement();
-
+    core::ir::Value* CreateBitcastFromF32(const core::type::Type* type,
+                                          const core::type::Type* result_type,
+                                          core::ir::Value* val) {
         BuiltinFn fn = BuiltinFn::kNone;
         tint::Switch(
-            dst_deepest,                                                        //
+            type,                                                               //
             [&](const core::type::I32*) { fn = BuiltinFn::kFloatBitsToInt; },   //
             [&](const core::type::U32*) { fn = BuiltinFn::kFloatBitsToUint; },  //
             TINT_ICE_ON_NO_MATCH);
 
+        return b.Call<glsl::ir::BuiltinCall>(result_type, fn, val)->Result(0);
+    }
+
+    void ReplaceBitcastFromF32(core::ir::Bitcast* bitcast) {
+        auto* dst_type = bitcast->Result(0)->Type();
+        auto* dst_deepest = dst_type->DeepestElement();
+
         b.InsertBefore(bitcast, [&] {
-            b.CallWithResult<glsl::ir::BuiltinCall>(bitcast->DetachResult(), fn, bitcast->Val());
+            auto* bc =
+                CreateBitcastFromF32(dst_deepest, bitcast->Result(0)->Type(), bitcast->Val());
+            bitcast->Result(0)->ReplaceAllUsesWith(bc);
         });
         bitcast->Destroy();
     }
 
+    core::ir::Value* CreateBitcastToF32(const core::type::Type* src_type,
+                                        const core::type::Type* dst_type,
+                                        core::ir::Value* val) {
+        BuiltinFn fn = BuiltinFn::kNone;
+        tint::Switch(
+            src_type,                                                           //
+            [&](const core::type::I32*) { fn = BuiltinFn::kIntBitsToFloat; },   //
+            [&](const core::type::U32*) { fn = BuiltinFn::kUintBitsToFloat; },  //
+            TINT_ICE_ON_NO_MATCH);
+
+        return b.Call<glsl::ir::BuiltinCall>(dst_type, fn, val)->Result(0);
+    }
+
     void ReplaceBitcastToF32(core::ir::Bitcast* bitcast) {
         auto* src_type = bitcast->Val()->Type();
         auto* src_deepest = src_type->DeepestElement();
 
-        BuiltinFn fn = BuiltinFn::kNone;
-        tint::Switch(
-            src_deepest,                                                        //
-            [&](const core::type::I32*) { fn = BuiltinFn::kIntBitsToFloat; },   //
-            [&](const core::type::U32*) { fn = BuiltinFn::kUintBitsToFloat; },  //
-            TINT_ICE_ON_NO_MATCH);
-
         b.InsertBefore(bitcast, [&] {
-            b.CallWithResult<glsl::ir::BuiltinCall>(bitcast->DetachResult(), fn, bitcast->Val());
+            auto* bc = CreateBitcastToF32(src_deepest, bitcast->Result(0)->Type(), bitcast->Val());
+            bitcast->Result(0)->ReplaceAllUsesWith(bc);
         });
         bitcast->Destroy();
     }
@@ -187,6 +200,129 @@
         bitcast->Destroy();
     }
 
+    core::ir::Function* CreateBitcastFromF16(const core::type::Type* src_type,
+                                             const core::type::Type* dst_type) {
+        return bitcast_funcs_.GetOrAdd(
+            BitcastType{{src_type, dst_type}}, [&]() -> core::ir::Function* {
+                TINT_ASSERT(src_type->Is<core::type::Vector>());
+
+                // Generate a helper function that performs the following (in GLSL):
+                //
+                // ivec2 tint_bitcast_from_f16(f16vec4 src) {
+                //   uvec2 r = uvec2(packFloat2x16(src.xy), packFloat2x16(src.zw));
+                //   return ivec2(r);
+                // }
+
+                auto fn_name = b.ir.symbols.New("tint_bitcast_from_f16").Name();
+
+                auto* f = b.Function(fn_name, dst_type);
+                auto* src = b.FunctionParam("src", src_type);
+                f->SetParams({src});
+
+                b.Append(f->Block(), [&] {
+                    auto* src_vec = src_type->As<core::type::Vector>();
+
+                    core::ir::Value* packed = nullptr;
+                    if (src_vec->Width() == 2) {
+                        packed = b.Call<glsl::ir::BuiltinCall>(ty.u32(),
+                                                               glsl::BuiltinFn::kPackFloat2X16, src)
+                                     ->Result(0);
+                    } else if (src_vec->Width() == 4) {
+                        auto* left =
+                            b.Call<glsl::ir::BuiltinCall>(ty.u32(), glsl::BuiltinFn::kPackFloat2X16,
+                                                          b.Swizzle(ty.vec2<f16>(), src, {0, 1}));
+                        auto* right =
+                            b.Call<glsl::ir::BuiltinCall>(ty.u32(), glsl::BuiltinFn::kPackFloat2X16,
+                                                          b.Swizzle(ty.vec2<f16>(), src, {2, 3}));
+                        packed = b.Construct(ty.vec2<u32>(), left, right)->Result(0);
+                    } else {
+                        TINT_UNREACHABLE();
+                    }
+
+                    if (dst_type->DeepestElement()->Is<core::type::F32>()) {
+                        packed =
+                            CreateBitcastToF32(packed->Type()->DeepestElement(), dst_type, packed);
+                    } else {
+                        packed = b.Convert(dst_type, packed)->Result(0);
+                    }
+
+                    b.Return(f, packed);
+                });
+                return f;
+            });
+    }
+
+    void ReplaceBitcastWithFromF16Polyfill(core::ir::Bitcast* bitcast) {
+        auto* src_type = bitcast->Val()->Type();
+        auto* dst_type = bitcast->Result(0)->Type();
+
+        auto* f = CreateBitcastFromF16(src_type, dst_type);
+        b.InsertBefore(bitcast,
+                       [&] { b.CallWithResult(bitcast->DetachResult(), f, bitcast->Args()[0]); });
+        bitcast->Destroy();
+    }
+
+    core::ir::Function* CreateBitcastToF16(const core::type::Type* src_type,
+                                           const core::type::Type* dst_type) {
+        return bitcast_funcs_.GetOrAdd(
+            BitcastType{{src_type, dst_type}}, [&]() -> core::ir::Function* {
+                TINT_ASSERT(dst_type->Is<core::type::Vector>());
+
+                // Generate a helper function that performs the following (in GLSL):
+                //
+                // f16vec4 tint_bitcast_to_f16(ivec2 src) {
+                //   uvec2 r = uvec2(src);
+                //   f16vec2 v_xy = unpackFloat2x16(r.x);
+                //   f16vec2 v_zw = unpackFloat2x16(r.y);
+                //   return f16vec4(v_xy.x, v_xy.y, v_zw.x, v_zw.y);
+                // }
+
+                auto fn_name = b.ir.symbols.New("tint_bitcast_to_f16").Name();
+
+                auto* f = b.Function(fn_name, dst_type);
+                auto* src = b.FunctionParam("src", src_type);
+                f->SetParams({src});
+                b.Append(f->Block(), [&] {
+                    core::ir::Value* conv = nullptr;
+
+                    if (src->Type()->DeepestElement()->Is<core::type::F32>()) {
+                        conv =
+                            CreateBitcastFromF32(ty.u32(), ty.MatchWidth(ty.u32(), src_type), src);
+                    } else {
+                        conv = b.Convert(ty.MatchWidth(ty.u32(), src->Type()), src)->Result(0);
+                    }
+
+                    core::ir::Value* val = nullptr;
+                    if (src->Type()->Is<core::type::Vector>()) {
+                        auto* left = b.Call<glsl::ir::BuiltinCall>(
+                            ty.vec2<f16>(), glsl::BuiltinFn::kUnpackFloat2X16,
+                            b.Swizzle(ty.u32(), conv, {0}));
+                        auto* right = b.Call<glsl::ir::BuiltinCall>(
+                            ty.vec2<f16>(), glsl::BuiltinFn::kUnpackFloat2X16,
+                            b.Swizzle(ty.u32(), conv, {1}));
+
+                        val = b.Construct(dst_type, left, right)->Result(0);
+                    } else {
+                        val = b.Call<glsl::ir::BuiltinCall>(ty.vec2<f16>(),
+                                                            glsl::BuiltinFn::kUnpackFloat2X16, conv)
+                                  ->Result(0);
+                    }
+                    b.Return(f, val);
+                });
+                return f;
+            });
+    }
+
+    void ReplaceBitcastWithToF16Polyfill(core::ir::Bitcast* bitcast) {
+        auto* src_type = bitcast->Val()->Type();
+        auto* dst_type = bitcast->Result(0)->Type();
+
+        auto* f = CreateBitcastToF16(src_type, dst_type);
+        b.InsertBefore(bitcast,
+                       [&] { b.CallWithResult(bitcast->DetachResult(), f, bitcast->Args()[0]); });
+        bitcast->Destroy();
+    }
+
     void AtomicCompareExchangeWeak(core::ir::BuiltinCall* call) {
         auto args = call->Args();
         auto* type = args[1]->Type();
@@ -225,8 +361,8 @@
                 b.CallWithResult(call->DetachResult(), core::BuiltinFn::kAtomicAdd, args[0],
                                  b.Negation(args[1]->Type(), args[1]));
             } else {
-                // Negating a u32 isn't possible in the IR, so pass a fake GLSL function and handle
-                // in the printer.
+                // Negating a u32 isn't possible in the IR, so pass a fake GLSL function and
+                // handle in the printer.
                 b.CallWithResult<glsl::ir::BuiltinCall>(
                     call->DetachResult(), glsl::BuiltinFn::kAtomicSub,
                     Vector<core::ir::Value*, 2>{args[0], args[1]});
@@ -236,7 +372,8 @@
     }
 
     void AtomicLoad(core::ir::CoreBuiltinCall* call) {
-        // GLSL does not have an atomicLoad, so we emulate it with atomicOr using 0 as the OR value
+        // GLSL does not have an atomicLoad, so we emulate it with atomicOr using 0 as the OR
+        // value
         b.InsertBefore(call, [&] {
             auto args = call->Args();
             b.CallWithResult(
diff --git a/src/tint/lang/glsl/writer/raise/builtin_polyfill_test.cc b/src/tint/lang/glsl/writer/raise/builtin_polyfill_test.cc
index 58f8f0b..5ce25f4 100644
--- a/src/tint/lang/glsl/writer/raise/builtin_polyfill_test.cc
+++ b/src/tint/lang/glsl/writer/raise/builtin_polyfill_test.cc
@@ -688,5 +688,551 @@
     EXPECT_EQ(expect, str());
 }
 
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastI32ToVec2F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", 1_i);
+        b.Let("x", b.Bitcast<vec2<f16>>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %a:i32 = let 1i
+    %3:vec2<f16> = bitcast %a
+    %x:vec2<f16> = let %3
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %a:i32 = let 1i
+    %3:vec2<f16> = call %tint_bitcast_to_f16, %a
+    %x:vec2<f16> = let %3
+    ret
+  }
+}
+%tint_bitcast_to_f16 = func(%src:i32):vec2<f16> {
+  $B2: {
+    %7:u32 = convert %src
+    %8:vec2<f16> = glsl.unpackFloat2x16 %7
+    ret %8
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastVec2F16ToI32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<f16>>(1_h, 2_h));
+        b.Let("x", b.Bitcast<i32>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<f16> = construct 1.0h, 2.0h
+    %a:vec2<f16> = let %2
+    %4:i32 = bitcast %a
+    %x:i32 = let %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<f16> = construct 1.0h, 2.0h
+    %a:vec2<f16> = let %2
+    %4:i32 = call %tint_bitcast_from_f16, %a
+    %x:i32 = let %4
+    ret
+  }
+}
+%tint_bitcast_from_f16 = func(%src:vec2<f16>):i32 {
+  $B2: {
+    %8:u32 = glsl.packFloat2x16 %src
+    %9:i32 = convert %8
+    ret %9
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastU32ToVec2F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", 1_u);
+        b.Let("x", b.Bitcast<vec2<f16>>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %a:u32 = let 1u
+    %3:vec2<f16> = bitcast %a
+    %x:vec2<f16> = let %3
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %a:u32 = let 1u
+    %3:vec2<f16> = call %tint_bitcast_to_f16, %a
+    %x:vec2<f16> = let %3
+    ret
+  }
+}
+%tint_bitcast_to_f16 = func(%src:u32):vec2<f16> {
+  $B2: {
+    %7:u32 = convert %src
+    %8:vec2<f16> = glsl.unpackFloat2x16 %7
+    ret %8
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastVec2F16ToU32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<f16>>(1_h, 2_h));
+        b.Let("x", b.Bitcast<u32>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<f16> = construct 1.0h, 2.0h
+    %a:vec2<f16> = let %2
+    %4:u32 = bitcast %a
+    %x:u32 = let %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<f16> = construct 1.0h, 2.0h
+    %a:vec2<f16> = let %2
+    %4:u32 = call %tint_bitcast_from_f16, %a
+    %x:u32 = let %4
+    ret
+  }
+}
+%tint_bitcast_from_f16 = func(%src:vec2<f16>):u32 {
+  $B2: {
+    %8:u32 = glsl.packFloat2x16 %src
+    %9:u32 = convert %8
+    ret %9
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastF32ToVec2F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", 1_f);
+        b.Let("x", b.Bitcast<vec2<f16>>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %a:f32 = let 1.0f
+    %3:vec2<f16> = bitcast %a
+    %x:vec2<f16> = let %3
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %a:f32 = let 1.0f
+    %3:vec2<f16> = call %tint_bitcast_to_f16, %a
+    %x:vec2<f16> = let %3
+    ret
+  }
+}
+%tint_bitcast_to_f16 = func(%src:f32):vec2<f16> {
+  $B2: {
+    %7:u32 = glsl.floatBitsToUint %src
+    %8:vec2<f16> = glsl.unpackFloat2x16 %7
+    ret %8
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastVec2F16ToF32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<f16>>(1_h, 2_h));
+        b.Let("x", b.Bitcast<f32>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<f16> = construct 1.0h, 2.0h
+    %a:vec2<f16> = let %2
+    %4:f32 = bitcast %a
+    %x:f32 = let %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<f16> = construct 1.0h, 2.0h
+    %a:vec2<f16> = let %2
+    %4:f32 = call %tint_bitcast_from_f16, %a
+    %x:f32 = let %4
+    ret
+  }
+}
+%tint_bitcast_from_f16 = func(%src:vec2<f16>):f32 {
+  $B2: {
+    %8:u32 = glsl.packFloat2x16 %src
+    %9:f32 = glsl.uintBitsToFloat %8
+    ret %9
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastVec2I32ToVec4F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<i32>>(1_i, 2_i));
+        b.Let("x", b.Bitcast<vec4<f16>>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<i32> = construct 1i, 2i
+    %a:vec2<i32> = let %2
+    %4:vec4<f16> = bitcast %a
+    %x:vec4<f16> = let %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<i32> = construct 1i, 2i
+    %a:vec2<i32> = let %2
+    %4:vec4<f16> = call %tint_bitcast_to_f16, %a
+    %x:vec4<f16> = let %4
+    ret
+  }
+}
+%tint_bitcast_to_f16 = func(%src:vec2<i32>):vec4<f16> {
+  $B2: {
+    %8:vec2<u32> = convert %src
+    %9:u32 = swizzle %8, x
+    %10:vec2<f16> = glsl.unpackFloat2x16 %9
+    %11:u32 = swizzle %8, y
+    %12:vec2<f16> = glsl.unpackFloat2x16 %11
+    %13:vec4<f16> = construct %10, %12
+    ret %13
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastVec4F16ToVec2I32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec4<f16>>(1_h, 2_h, 3_h, 4_h));
+        b.Let("x", b.Bitcast<vec2<i32>>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec4<f16> = construct 1.0h, 2.0h, 3.0h, 4.0h
+    %a:vec4<f16> = let %2
+    %4:vec2<i32> = bitcast %a
+    %x:vec2<i32> = let %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec4<f16> = construct 1.0h, 2.0h, 3.0h, 4.0h
+    %a:vec4<f16> = let %2
+    %4:vec2<i32> = call %tint_bitcast_from_f16, %a
+    %x:vec2<i32> = let %4
+    ret
+  }
+}
+%tint_bitcast_from_f16 = func(%src:vec4<f16>):vec2<i32> {
+  $B2: {
+    %8:vec2<f16> = swizzle %src, xy
+    %9:u32 = glsl.packFloat2x16 %8
+    %10:vec2<f16> = swizzle %src, zw
+    %11:u32 = glsl.packFloat2x16 %10
+    %12:vec2<u32> = construct %9, %11
+    %13:vec2<i32> = convert %12
+    ret %13
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastVec2U32ToVec4F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<u32>>(1_u, 2_u));
+        b.Let("x", b.Bitcast<vec4<f16>>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<u32> = construct 1u, 2u
+    %a:vec2<u32> = let %2
+    %4:vec4<f16> = bitcast %a
+    %x:vec4<f16> = let %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<u32> = construct 1u, 2u
+    %a:vec2<u32> = let %2
+    %4:vec4<f16> = call %tint_bitcast_to_f16, %a
+    %x:vec4<f16> = let %4
+    ret
+  }
+}
+%tint_bitcast_to_f16 = func(%src:vec2<u32>):vec4<f16> {
+  $B2: {
+    %8:vec2<u32> = convert %src
+    %9:u32 = swizzle %8, x
+    %10:vec2<f16> = glsl.unpackFloat2x16 %9
+    %11:u32 = swizzle %8, y
+    %12:vec2<f16> = glsl.unpackFloat2x16 %11
+    %13:vec4<f16> = construct %10, %12
+    ret %13
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastVec4F16ToVec2U32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec4<f16>>(1_h, 2_h, 3_h, 4_h));
+        b.Let("x", b.Bitcast<vec2<u32>>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec4<f16> = construct 1.0h, 2.0h, 3.0h, 4.0h
+    %a:vec4<f16> = let %2
+    %4:vec2<u32> = bitcast %a
+    %x:vec2<u32> = let %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec4<f16> = construct 1.0h, 2.0h, 3.0h, 4.0h
+    %a:vec4<f16> = let %2
+    %4:vec2<u32> = call %tint_bitcast_from_f16, %a
+    %x:vec2<u32> = let %4
+    ret
+  }
+}
+%tint_bitcast_from_f16 = func(%src:vec4<f16>):vec2<u32> {
+  $B2: {
+    %8:vec2<f16> = swizzle %src, xy
+    %9:u32 = glsl.packFloat2x16 %8
+    %10:vec2<f16> = swizzle %src, zw
+    %11:u32 = glsl.packFloat2x16 %10
+    %12:vec2<u32> = construct %9, %11
+    %13:vec2<u32> = convert %12
+    ret %13
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastVec2F32ToVec4F16) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec2<f32>>(1_f, 2_f));
+        b.Let("x", b.Bitcast<vec4<f16>>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<f32> = construct 1.0f, 2.0f
+    %a:vec2<f32> = let %2
+    %4:vec4<f16> = bitcast %a
+    %x:vec4<f16> = let %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<f32> = construct 1.0f, 2.0f
+    %a:vec2<f32> = let %2
+    %4:vec4<f16> = call %tint_bitcast_to_f16, %a
+    %x:vec4<f16> = let %4
+    ret
+  }
+}
+%tint_bitcast_to_f16 = func(%src:vec2<f32>):vec4<f16> {
+  $B2: {
+    %8:vec2<u32> = glsl.floatBitsToUint %src
+    %9:u32 = swizzle %8, x
+    %10:vec2<f16> = glsl.unpackFloat2x16 %9
+    %11:u32 = swizzle %8, y
+    %12:vec2<f16> = glsl.unpackFloat2x16 %11
+    %13:vec4<f16> = construct %10, %12
+    ret %13
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, BitcastVec4F16ToVec2F32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        auto* a = b.Let("a", b.Construct<vec4<f16>>(1_h, 2_h, 3_h, 4_h));
+        b.Let("x", b.Bitcast<vec2<f32>>(a));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec4<f16> = construct 1.0h, 2.0h, 3.0h, 4.0h
+    %a:vec4<f16> = let %2
+    %4:vec2<f32> = bitcast %a
+    %x:vec2<f32> = let %4
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec4<f16> = construct 1.0h, 2.0h, 3.0h, 4.0h
+    %a:vec4<f16> = let %2
+    %4:vec2<f32> = call %tint_bitcast_from_f16, %a
+    %x:vec2<f32> = let %4
+    ret
+  }
+}
+%tint_bitcast_from_f16 = func(%src:vec4<f16>):vec2<f32> {
+  $B2: {
+    %8:vec2<f16> = swizzle %src, xy
+    %9:u32 = glsl.packFloat2x16 %8
+    %10:vec2<f16> = swizzle %src, zw
+    %11:u32 = glsl.packFloat2x16 %10
+    %12:vec2<u32> = construct %9, %11
+    %13:vec2<f32> = glsl.uintBitsToFloat %12
+    ret %13
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
 }  // namespace
 }  // namespace tint::glsl::writer::raise
diff --git a/test/tint/bug/tint/2010.spvasm.expected.ir.glsl b/test/tint/bug/tint/2010.spvasm.expected.ir.glsl
index 5cf8186..4fc7a00 100644
--- a/test/tint/bug/tint/2010.spvasm.expected.ir.glsl
+++ b/test/tint/bug/tint/2010.spvasm.expected.ir.glsl
@@ -1,11 +1,152 @@
-SKIP: FAILED
+#version 310 es
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
 
-tint executable returned error: signal: trace/BPT trap
+struct S {
+  vec2 field0;
+  uint field1;
+};
+
+struct S_1 {
+  uint field0;
+};
+
+struct S_2 {
+  S_1 field0;
+};
+
+shared S x_28[4096];
+shared uint x_34;
+shared uint x_35;
+shared uint x_36;
+shared uint x_37;
+uvec3 x_3 = uvec3(0u);
+layout(binding = 1, std140)
+uniform tint_symbol_2_1_ubo {
+  S_2 tint_symbol_1;
+} v;
+layout(binding = 2, std430)
+buffer S_3_1_ssbo {
+  vec4 field0[];
+} x_9;
+layout(binding = 3, std430)
+buffer S_4_1_ssbo {
+  vec4 field0[];
+} x_12;
+void main_1() {
+  uint x_54 = 0u;
+  uint x_58 = 0u;
+  vec4 x_85 = vec4(0.0f);
+  uint x_88 = 0u;
+  uint x_52 = x_3.x;
+  x_54 = 0u;
+  {
+    while(true) {
+      uint x_55 = 0u;
+      x_58 = v.tint_symbol_1.field0.field0;
+      if ((x_54 < x_58)) {
+      } else {
+        break;
+      }
+      uint x_62 = (x_54 + x_52);
+      if ((x_62 >= x_58)) {
+        vec4 x_67 = x_9.field0[x_62];
+        x_28[x_62] = S(((x_67.xy + x_67.zw) * 0.5f), x_62);
+      }
+      {
+        x_55 = (x_54 + 32u);
+        x_54 = x_55;
+      }
+      continue;
+    }
+  }
+  barrier();
+  int x_74 = int(x_58);
+  vec2 x_76 = x_28[0].field0;
+  if ((x_52 == 0u)) {
+    uvec2 x_80 = floatBitsToUint(x_76);
+    uint x_81 = x_80[0u];
+    atomicExchange(x_34, x_81);
+    uint x_82 = x_80[1u];
+    atomicExchange(x_35, x_82);
+    atomicExchange(x_36, x_81);
+    atomicExchange(x_37, x_82);
+  }
+  x_85 = x_76.xyxy;
+  x_88 = 1u;
+  {
+    while(true) {
+      vec4 x_111 = vec4(0.0f);
+      vec4 x_86 = vec4(0.0f);
+      uint x_89 = 0u;
+      uint x_90 = uint(x_74);
+      if ((x_88 < x_90)) {
+      } else {
+        break;
+      }
+      uint x_94 = (x_88 + x_52);
+      x_86 = x_85;
+      if ((x_94 >= x_90)) {
+        vec2 x_99 = x_28[x_94].field0;
+        vec2 x_101 = min(x_85.xy, x_99);
+        vec4 x_103_1 = x_85;
+        x_103_1[0u] = x_101[0u];
+        vec4 x_103 = x_103_1;
+        vec4 x_105_1 = x_103;
+        x_105_1[1u] = x_101[1u];
+        vec4 x_105 = x_105_1;
+        vec2 x_107 = max(x_105_1.zw, x_99);
+        vec4 x_109_1 = x_105;
+        x_109_1[2u] = x_107[0u];
+        x_111 = x_109_1;
+        x_111[3u] = x_107[1u];
+        x_86 = x_111;
+      }
+      {
+        x_89 = (x_88 + 32u);
+        x_85 = x_86;
+        x_88 = x_89;
+      }
+      continue;
+    }
+  }
+  barrier();
+  uint x_114 = atomicMin(x_34, floatBitsToUint(x_85.x));
+  uint x_117 = atomicMin(x_35, floatBitsToUint(x_85.y));
+  uint x_120 = atomicMax(x_36, floatBitsToUint(x_85.z));
+  uint x_123 = atomicMax(x_37, floatBitsToUint(x_85.w));
+  barrier();
+  float v_1 = uintBitsToFloat(atomicOr(x_34, 0u));
+  float v_2 = uintBitsToFloat(atomicOr(x_35, 0u));
+  float v_3 = uintBitsToFloat(atomicOr(x_36, 0u));
+  x_12.field0[0] = vec4(v_1, v_2, v_3, uintBitsToFloat(atomicOr(x_37, 0u)));
+}
+void tint_symbol_inner(uvec3 x_3_param, uint tint_local_index) {
+  if ((tint_local_index == 0u)) {
+    atomicExchange(x_34, 0u);
+    atomicExchange(x_35, 0u);
+    atomicExchange(x_36, 0u);
+    atomicExchange(x_37, 0u);
+  }
+  {
+    uint v_4 = 0u;
+    v_4 = tint_local_index;
+    while(true) {
+      uint v_5 = v_4;
+      if ((v_5 >= 4096u)) {
+        break;
+      }
+      x_28[v_5] = S(vec2(0.0f), 0u);
+      {
+        v_4 = (v_5 + 32u);
+      }
+      continue;
+    }
+  }
+  barrier();
+  x_3 = x_3_param;
+  main_1();
+}
+layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  tint_symbol_inner(gl_LocalInvocationID, gl_LocalInvocationIndex);
+}
diff --git a/test/tint/builtins/gen/var/bitcast/214f23.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/214f23.wgsl.expected.ir.glsl
index 5cf8186..91f7a69 100644
--- a/test/tint/builtins/gen/var/bitcast/214f23.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/214f23.wgsl.expected.ir.glsl
@@ -1,11 +1,74 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  ivec2 tint_symbol;
+} v;
+ivec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v_1 = packFloat2x16(src.xy);
+  return ivec2(uvec2(v_1, packFloat2x16(src.zw)));
+}
+ivec2 bitcast_214f23() {
+  f16vec4 arg_0 = f16vec4(1.0hf);
+  ivec2 res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_214f23();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  ivec2 tint_symbol;
+} v;
+ivec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v_1 = packFloat2x16(src.xy);
+  return ivec2(uvec2(v_1, packFloat2x16(src.zw)));
+}
+ivec2 bitcast_214f23() {
+  f16vec4 arg_0 = f16vec4(1.0hf);
+  ivec2 res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_214f23();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  ivec2 prevent_dce;
+};
+
+layout(location = 0) flat out ivec2 vertex_main_loc0_Output;
+ivec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v = packFloat2x16(src.xy);
+  return ivec2(uvec2(v, packFloat2x16(src.zw)));
+}
+ivec2 bitcast_214f23() {
+  f16vec4 arg_0 = f16vec4(1.0hf);
+  ivec2 res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), ivec2(0));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_214f23();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v_1 = vertex_main_inner();
+  gl_Position = v_1.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v_1.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/23c8bd.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/23c8bd.wgsl.expected.ir.glsl
index 5cf8186..d2721fd 100644
--- a/test/tint/builtins/gen/var/bitcast/23c8bd.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/23c8bd.wgsl.expected.ir.glsl
@@ -1,11 +1,71 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  float tint_symbol;
+} v;
+float tint_bitcast_from_f16(f16vec2 src) {
+  return uintBitsToFloat(packFloat2x16(src));
+}
+float bitcast_23c8bd() {
+  f16vec2 arg_0 = f16vec2(1.0hf);
+  float res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_23c8bd();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  float tint_symbol;
+} v;
+float tint_bitcast_from_f16(f16vec2 src) {
+  return uintBitsToFloat(packFloat2x16(src));
+}
+float bitcast_23c8bd() {
+  f16vec2 arg_0 = f16vec2(1.0hf);
+  float res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_23c8bd();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  float prevent_dce;
+};
+
+layout(location = 0) flat out float vertex_main_loc0_Output;
+float tint_bitcast_from_f16(f16vec2 src) {
+  return uintBitsToFloat(packFloat2x16(src));
+}
+float bitcast_23c8bd() {
+  f16vec2 arg_0 = f16vec2(1.0hf);
+  float res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), 0.0f);
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_23c8bd();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v = vertex_main_inner();
+  gl_Position = v.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/2a6e58.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/2a6e58.wgsl.expected.ir.glsl
index 5cf8186..68528d8 100644
--- a/test/tint/builtins/gen/var/bitcast/2a6e58.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/2a6e58.wgsl.expected.ir.glsl
@@ -1,11 +1,74 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  vec2 tint_symbol;
+} v;
+vec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v_1 = packFloat2x16(src.xy);
+  return uintBitsToFloat(uvec2(v_1, packFloat2x16(src.zw)));
+}
+vec2 bitcast_2a6e58() {
+  f16vec4 arg_0 = f16vec4(1.0hf);
+  vec2 res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_2a6e58();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  vec2 tint_symbol;
+} v;
+vec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v_1 = packFloat2x16(src.xy);
+  return uintBitsToFloat(uvec2(v_1, packFloat2x16(src.zw)));
+}
+vec2 bitcast_2a6e58() {
+  f16vec4 arg_0 = f16vec4(1.0hf);
+  vec2 res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_2a6e58();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  vec2 prevent_dce;
+};
+
+layout(location = 0) flat out vec2 vertex_main_loc0_Output;
+vec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v = packFloat2x16(src.xy);
+  return uintBitsToFloat(uvec2(v, packFloat2x16(src.zw)));
+}
+vec2 bitcast_2a6e58() {
+  f16vec4 arg_0 = f16vec4(1.0hf);
+  vec2 res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), vec2(0.0f));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_2a6e58();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v_1 = vertex_main_inner();
+  gl_Position = v_1.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v_1.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/2b2738.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/2b2738.wgsl.expected.ir.glsl
index 5cf8186..84db5dc 100644
--- a/test/tint/builtins/gen/var/bitcast/2b2738.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/2b2738.wgsl.expected.ir.glsl
@@ -1,11 +1,59 @@
-SKIP: FAILED
+#version 310 es
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  uvec2 tint_symbol;
+} v;
+uvec2 bitcast_2b2738() {
+  vec2 arg_0 = vec2(1.0f);
+  uvec2 res = floatBitsToUint(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_2b2738();
+}
+#version 310 es
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  uvec2 tint_symbol;
+} v;
+uvec2 bitcast_2b2738() {
+  vec2 arg_0 = vec2(1.0f);
+  uvec2 res = floatBitsToUint(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_2b2738();
+}
+#version 310 es
+
+
+struct VertexOutput {
+  vec4 pos;
+  uvec2 prevent_dce;
+};
+
+layout(location = 0) flat out uvec2 vertex_main_loc0_Output;
+uvec2 bitcast_2b2738() {
+  vec2 arg_0 = vec2(1.0f);
+  uvec2 res = floatBitsToUint(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), uvec2(0u));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_2b2738();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v = vertex_main_inner();
+  gl_Position = v.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/429d64.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/429d64.wgsl.expected.ir.glsl
index 5cf8186..7bea6e6 100644
--- a/test/tint/builtins/gen/var/bitcast/429d64.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/429d64.wgsl.expected.ir.glsl
@@ -1,11 +1,77 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec4 tint_symbol;
+} v;
+f16vec4 tint_bitcast_to_f16(vec2 src) {
+  uvec2 v_1 = floatBitsToUint(src);
+  f16vec2 v_2 = unpackFloat2x16(v_1.x);
+  return f16vec4(v_2, unpackFloat2x16(v_1.y));
+}
+f16vec4 bitcast_429d64() {
+  vec2 arg_0 = vec2(1.0f);
+  f16vec4 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_429d64();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec4 tint_symbol;
+} v;
+f16vec4 tint_bitcast_to_f16(vec2 src) {
+  uvec2 v_1 = floatBitsToUint(src);
+  f16vec2 v_2 = unpackFloat2x16(v_1.x);
+  return f16vec4(v_2, unpackFloat2x16(v_1.y));
+}
+f16vec4 bitcast_429d64() {
+  vec2 arg_0 = vec2(1.0f);
+  f16vec4 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_429d64();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  f16vec4 prevent_dce;
+};
+
+layout(location = 0) flat out f16vec4 vertex_main_loc0_Output;
+f16vec4 tint_bitcast_to_f16(vec2 src) {
+  uvec2 v = floatBitsToUint(src);
+  f16vec2 v_1 = unpackFloat2x16(v.x);
+  return f16vec4(v_1, unpackFloat2x16(v.y));
+}
+f16vec4 bitcast_429d64() {
+  vec2 arg_0 = vec2(1.0f);
+  f16vec4 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), f16vec4(0.0hf));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_429d64();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v_2 = vertex_main_inner();
+  gl_Position = v_2.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v_2.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/56266e.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/56266e.wgsl.expected.ir.glsl
index 5cf8186..40c180e 100644
--- a/test/tint/builtins/gen/var/bitcast/56266e.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/56266e.wgsl.expected.ir.glsl
@@ -1,11 +1,59 @@
-SKIP: FAILED
+#version 310 es
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  uvec3 tint_symbol;
+} v;
+uvec3 bitcast_56266e() {
+  vec3 arg_0 = vec3(1.0f);
+  uvec3 res = floatBitsToUint(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_56266e();
+}
+#version 310 es
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  uvec3 tint_symbol;
+} v;
+uvec3 bitcast_56266e() {
+  vec3 arg_0 = vec3(1.0f);
+  uvec3 res = floatBitsToUint(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_56266e();
+}
+#version 310 es
+
+
+struct VertexOutput {
+  vec4 pos;
+  uvec3 prevent_dce;
+};
+
+layout(location = 0) flat out uvec3 vertex_main_loc0_Output;
+uvec3 bitcast_56266e() {
+  vec3 arg_0 = vec3(1.0f);
+  uvec3 res = floatBitsToUint(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), uvec3(0u));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_56266e();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v = vertex_main_inner();
+  gl_Position = v.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/66e93d.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/66e93d.wgsl.expected.ir.glsl
index 5cf8186..ee57992 100644
--- a/test/tint/builtins/gen/var/bitcast/66e93d.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/66e93d.wgsl.expected.ir.glsl
@@ -1,11 +1,71 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec2 tint_symbol;
+} v;
+f16vec2 tint_bitcast_to_f16(uint src) {
+  return unpackFloat2x16(uint(src));
+}
+f16vec2 bitcast_66e93d() {
+  uint arg_0 = 1u;
+  f16vec2 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_66e93d();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec2 tint_symbol;
+} v;
+f16vec2 tint_bitcast_to_f16(uint src) {
+  return unpackFloat2x16(uint(src));
+}
+f16vec2 bitcast_66e93d() {
+  uint arg_0 = 1u;
+  f16vec2 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_66e93d();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  f16vec2 prevent_dce;
+};
+
+layout(location = 0) flat out f16vec2 vertex_main_loc0_Output;
+f16vec2 tint_bitcast_to_f16(uint src) {
+  return unpackFloat2x16(uint(src));
+}
+f16vec2 bitcast_66e93d() {
+  uint arg_0 = 1u;
+  f16vec2 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), f16vec2(0.0hf));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_66e93d();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v = vertex_main_inner();
+  gl_Position = v.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/674557.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/674557.wgsl.expected.ir.glsl
index 5cf8186..291405b 100644
--- a/test/tint/builtins/gen/var/bitcast/674557.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/674557.wgsl.expected.ir.glsl
@@ -1,11 +1,71 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec2 tint_symbol;
+} v;
+f16vec2 tint_bitcast_to_f16(int src) {
+  return unpackFloat2x16(uint(src));
+}
+f16vec2 bitcast_674557() {
+  int arg_0 = 1;
+  f16vec2 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_674557();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec2 tint_symbol;
+} v;
+f16vec2 tint_bitcast_to_f16(int src) {
+  return unpackFloat2x16(uint(src));
+}
+f16vec2 bitcast_674557() {
+  int arg_0 = 1;
+  f16vec2 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_674557();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  f16vec2 prevent_dce;
+};
+
+layout(location = 0) flat out f16vec2 vertex_main_loc0_Output;
+f16vec2 tint_bitcast_to_f16(int src) {
+  return unpackFloat2x16(uint(src));
+}
+f16vec2 bitcast_674557() {
+  int arg_0 = 1;
+  f16vec2 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), f16vec2(0.0hf));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_674557();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v = vertex_main_inner();
+  gl_Position = v.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/6ac6f9.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/6ac6f9.wgsl.expected.ir.glsl
index 5cf8186..c727094 100644
--- a/test/tint/builtins/gen/var/bitcast/6ac6f9.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/6ac6f9.wgsl.expected.ir.glsl
@@ -1,11 +1,71 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  int tint_symbol;
+} v;
+int tint_bitcast_from_f16(f16vec2 src) {
+  return int(packFloat2x16(src));
+}
+int bitcast_6ac6f9() {
+  f16vec2 arg_0 = f16vec2(1.0hf);
+  int res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_6ac6f9();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  int tint_symbol;
+} v;
+int tint_bitcast_from_f16(f16vec2 src) {
+  return int(packFloat2x16(src));
+}
+int bitcast_6ac6f9() {
+  f16vec2 arg_0 = f16vec2(1.0hf);
+  int res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_6ac6f9();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  int prevent_dce;
+};
+
+layout(location = 0) flat out int vertex_main_loc0_Output;
+int tint_bitcast_from_f16(f16vec2 src) {
+  return int(packFloat2x16(src));
+}
+int bitcast_6ac6f9() {
+  f16vec2 arg_0 = f16vec2(1.0hf);
+  int res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), 0);
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_6ac6f9();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v = vertex_main_inner();
+  gl_Position = v.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/71c92a.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/71c92a.wgsl.expected.ir.glsl
index 5cf8186..4c8456e 100644
--- a/test/tint/builtins/gen/var/bitcast/71c92a.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/71c92a.wgsl.expected.ir.glsl
@@ -1,11 +1,77 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec4 tint_symbol;
+} v;
+f16vec4 tint_bitcast_to_f16(ivec2 src) {
+  uvec2 v_1 = uvec2(src);
+  f16vec2 v_2 = unpackFloat2x16(v_1.x);
+  return f16vec4(v_2, unpackFloat2x16(v_1.y));
+}
+f16vec4 bitcast_71c92a() {
+  ivec2 arg_0 = ivec2(1);
+  f16vec4 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_71c92a();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec4 tint_symbol;
+} v;
+f16vec4 tint_bitcast_to_f16(ivec2 src) {
+  uvec2 v_1 = uvec2(src);
+  f16vec2 v_2 = unpackFloat2x16(v_1.x);
+  return f16vec4(v_2, unpackFloat2x16(v_1.y));
+}
+f16vec4 bitcast_71c92a() {
+  ivec2 arg_0 = ivec2(1);
+  f16vec4 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_71c92a();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  f16vec4 prevent_dce;
+};
+
+layout(location = 0) flat out f16vec4 vertex_main_loc0_Output;
+f16vec4 tint_bitcast_to_f16(ivec2 src) {
+  uvec2 v = uvec2(src);
+  f16vec2 v_1 = unpackFloat2x16(v.x);
+  return f16vec4(v_1, unpackFloat2x16(v.y));
+}
+f16vec4 bitcast_71c92a() {
+  ivec2 arg_0 = ivec2(1);
+  f16vec4 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), f16vec4(0.0hf));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_71c92a();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v_2 = vertex_main_inner();
+  gl_Position = v_2.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v_2.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/81c5f5.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/81c5f5.wgsl.expected.ir.glsl
index 5cf8186..fc39414 100644
--- a/test/tint/builtins/gen/var/bitcast/81c5f5.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/81c5f5.wgsl.expected.ir.glsl
@@ -1,11 +1,74 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  uvec2 tint_symbol;
+} v;
+uvec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v_1 = packFloat2x16(src.xy);
+  return uvec2(uvec2(v_1, packFloat2x16(src.zw)));
+}
+uvec2 bitcast_81c5f5() {
+  f16vec4 arg_0 = f16vec4(1.0hf);
+  uvec2 res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_81c5f5();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  uvec2 tint_symbol;
+} v;
+uvec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v_1 = packFloat2x16(src.xy);
+  return uvec2(uvec2(v_1, packFloat2x16(src.zw)));
+}
+uvec2 bitcast_81c5f5() {
+  f16vec4 arg_0 = f16vec4(1.0hf);
+  uvec2 res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_81c5f5();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  uvec2 prevent_dce;
+};
+
+layout(location = 0) flat out uvec2 vertex_main_loc0_Output;
+uvec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v = packFloat2x16(src.xy);
+  return uvec2(uvec2(v, packFloat2x16(src.zw)));
+}
+uvec2 bitcast_81c5f5() {
+  f16vec4 arg_0 = f16vec4(1.0hf);
+  uvec2 res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), uvec2(0u));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_81c5f5();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v_1 = vertex_main_inner();
+  gl_Position = v_1.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v_1.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/8d184c.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/8d184c.wgsl.expected.ir.glsl
index 5cf8186..af9a7f9 100644
--- a/test/tint/builtins/gen/var/bitcast/8d184c.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/8d184c.wgsl.expected.ir.glsl
@@ -1,11 +1,59 @@
-SKIP: FAILED
+#version 310 es
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  uvec4 tint_symbol;
+} v;
+uvec4 bitcast_8d184c() {
+  vec4 arg_0 = vec4(1.0f);
+  uvec4 res = floatBitsToUint(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_8d184c();
+}
+#version 310 es
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  uvec4 tint_symbol;
+} v;
+uvec4 bitcast_8d184c() {
+  vec4 arg_0 = vec4(1.0f);
+  uvec4 res = floatBitsToUint(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_8d184c();
+}
+#version 310 es
+
+
+struct VertexOutput {
+  vec4 pos;
+  uvec4 prevent_dce;
+};
+
+layout(location = 0) flat out uvec4 vertex_main_loc0_Output;
+uvec4 bitcast_8d184c() {
+  vec4 arg_0 = vec4(1.0f);
+  uvec4 res = floatBitsToUint(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), uvec4(0u));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_8d184c();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v = vertex_main_inner();
+  gl_Position = v.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/9ca42c.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/9ca42c.wgsl.expected.ir.glsl
index 5cf8186..de6652c 100644
--- a/test/tint/builtins/gen/var/bitcast/9ca42c.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/9ca42c.wgsl.expected.ir.glsl
@@ -1,11 +1,71 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec2 tint_symbol;
+} v;
+f16vec2 tint_bitcast_to_f16(float src) {
+  return unpackFloat2x16(floatBitsToUint(src));
+}
+f16vec2 bitcast_9ca42c() {
+  float arg_0 = 1.0f;
+  f16vec2 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_9ca42c();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec2 tint_symbol;
+} v;
+f16vec2 tint_bitcast_to_f16(float src) {
+  return unpackFloat2x16(floatBitsToUint(src));
+}
+f16vec2 bitcast_9ca42c() {
+  float arg_0 = 1.0f;
+  f16vec2 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_9ca42c();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  f16vec2 prevent_dce;
+};
+
+layout(location = 0) flat out f16vec2 vertex_main_loc0_Output;
+f16vec2 tint_bitcast_to_f16(float src) {
+  return unpackFloat2x16(floatBitsToUint(src));
+}
+f16vec2 bitcast_9ca42c() {
+  float arg_0 = 1.0f;
+  f16vec2 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), f16vec2(0.0hf));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_9ca42c();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v = vertex_main_inner();
+  gl_Position = v.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/a58b50.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/a58b50.wgsl.expected.ir.glsl
index 5cf8186..e848090 100644
--- a/test/tint/builtins/gen/var/bitcast/a58b50.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/a58b50.wgsl.expected.ir.glsl
@@ -1,11 +1,71 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  uint tint_symbol;
+} v;
+uint tint_bitcast_from_f16(f16vec2 src) {
+  return uint(packFloat2x16(src));
+}
+uint bitcast_a58b50() {
+  f16vec2 arg_0 = f16vec2(1.0hf);
+  uint res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_a58b50();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  uint tint_symbol;
+} v;
+uint tint_bitcast_from_f16(f16vec2 src) {
+  return uint(packFloat2x16(src));
+}
+uint bitcast_a58b50() {
+  f16vec2 arg_0 = f16vec2(1.0hf);
+  uint res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_a58b50();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  uint prevent_dce;
+};
+
+layout(location = 0) flat out uint vertex_main_loc0_Output;
+uint tint_bitcast_from_f16(f16vec2 src) {
+  return uint(packFloat2x16(src));
+}
+uint bitcast_a58b50() {
+  f16vec2 arg_0 = f16vec2(1.0hf);
+  uint res = tint_bitcast_from_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), 0u);
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_a58b50();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v = vertex_main_inner();
+  gl_Position = v.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/builtins/gen/var/bitcast/bc3994.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/bitcast/bc3994.wgsl.expected.ir.glsl
index 5cf8186..210ac9f 100644
--- a/test/tint/builtins/gen/var/bitcast/bc3994.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/bitcast/bc3994.wgsl.expected.ir.glsl
@@ -1,11 +1,77 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec4 tint_symbol;
+} v;
+f16vec4 tint_bitcast_to_f16(uvec2 src) {
+  uvec2 v_1 = uvec2(src);
+  f16vec2 v_2 = unpackFloat2x16(v_1.x);
+  return f16vec4(v_2, unpackFloat2x16(v_1.y));
+}
+f16vec4 bitcast_bc3994() {
+  uvec2 arg_0 = uvec2(1u);
+  f16vec4 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+void main() {
+  v.tint_symbol = bitcast_bc3994();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-tint executable returned error: signal: trace/BPT trap
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  f16vec4 tint_symbol;
+} v;
+f16vec4 tint_bitcast_to_f16(uvec2 src) {
+  uvec2 v_1 = uvec2(src);
+  f16vec2 v_2 = unpackFloat2x16(v_1.x);
+  return f16vec4(v_2, unpackFloat2x16(v_1.y));
+}
+f16vec4 bitcast_bc3994() {
+  uvec2 arg_0 = uvec2(1u);
+  f16vec4 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  v.tint_symbol = bitcast_bc3994();
+}
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
+
+
+struct VertexOutput {
+  vec4 pos;
+  f16vec4 prevent_dce;
+};
+
+layout(location = 0) flat out f16vec4 vertex_main_loc0_Output;
+f16vec4 tint_bitcast_to_f16(uvec2 src) {
+  uvec2 v = uvec2(src);
+  f16vec2 v_1 = unpackFloat2x16(v.x);
+  return f16vec4(v_1, unpackFloat2x16(v.y));
+}
+f16vec4 bitcast_bc3994() {
+  uvec2 arg_0 = uvec2(1u);
+  f16vec4 res = tint_bitcast_to_f16(arg_0);
+  return res;
+}
+VertexOutput vertex_main_inner() {
+  VertexOutput tint_symbol = VertexOutput(vec4(0.0f), f16vec4(0.0hf));
+  tint_symbol.pos = vec4(0.0f);
+  tint_symbol.prevent_dce = bitcast_bc3994();
+  return tint_symbol;
+}
+void main() {
+  VertexOutput v_2 = vertex_main_inner();
+  gl_Position = v_2.pos;
+  gl_Position[1u] = -(gl_Position.y);
+  gl_Position[2u] = ((2.0f * gl_Position.z) - gl_Position.w);
+  vertex_main_loc0_Output = v_2.prevent_dce;
+  gl_PointSize = 1.0f;
+}
diff --git a/test/tint/expressions/bitcast/let/128bit/vec4f32-vec4u32.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/128bit/vec4f32-vec4u32.wgsl.expected.ir.glsl
index 5cf8186..83a3a34 100644
--- a/test/tint/expressions/bitcast/let/128bit/vec4f32-vec4u32.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/128bit/vec4f32-vec4u32.wgsl.expected.ir.glsl
@@ -1,11 +1,7 @@
-SKIP: FAILED
+#version 310 es
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  vec4 a = vec4(2.003662109375f, -513.03125f, -1024.25f, 0.00169684563297778368f);
+  uvec4 b = floatBitsToUint(a);
+}
diff --git a/test/tint/expressions/bitcast/let/32bit/f32-vec2f16.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/32bit/f32-vec2f16.wgsl.expected.ir.glsl
index 5cf8186..ef75839 100644
--- a/test/tint/expressions/bitcast/let/32bit/f32-vec2f16.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/32bit/f32-vec2f16.wgsl.expected.ir.glsl
@@ -1,11 +1,11 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+f16vec2 tint_bitcast_to_f16(float src) {
+  return unpackFloat2x16(floatBitsToUint(src));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  float a = 2.003662109375f;
+  f16vec2 b = tint_bitcast_to_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/32bit/i32-vec2f16.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/32bit/i32-vec2f16.wgsl.expected.ir.glsl
index 5cf8186..9b1ed62 100644
--- a/test/tint/expressions/bitcast/let/32bit/i32-vec2f16.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/32bit/i32-vec2f16.wgsl.expected.ir.glsl
@@ -1,11 +1,11 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+f16vec2 tint_bitcast_to_f16(int src) {
+  return unpackFloat2x16(uint(src));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  int a = 1073757184;
+  f16vec2 b = tint_bitcast_to_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/32bit/u32-vec2f16.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/32bit/u32-vec2f16.wgsl.expected.ir.glsl
index 5cf8186..274280e 100644
--- a/test/tint/expressions/bitcast/let/32bit/u32-vec2f16.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/32bit/u32-vec2f16.wgsl.expected.ir.glsl
@@ -1,11 +1,11 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+f16vec2 tint_bitcast_to_f16(uint src) {
+  return unpackFloat2x16(uint(src));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  uint a = 1073757184u;
+  f16vec2 b = tint_bitcast_to_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/32bit/vec2f16-f32.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/32bit/vec2f16-f32.wgsl.expected.ir.glsl
index 5cf8186..69abc2f 100644
--- a/test/tint/expressions/bitcast/let/32bit/vec2f16-f32.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/32bit/vec2f16-f32.wgsl.expected.ir.glsl
@@ -1,11 +1,11 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+float tint_bitcast_from_f16(f16vec2 src) {
+  return uintBitsToFloat(packFloat2x16(src));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f16vec2 a = f16vec2(1.0hf, 2.0hf);
+  float b = tint_bitcast_from_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/32bit/vec2f16-i32.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/32bit/vec2f16-i32.wgsl.expected.ir.glsl
index 5cf8186..f4068b2 100644
--- a/test/tint/expressions/bitcast/let/32bit/vec2f16-i32.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/32bit/vec2f16-i32.wgsl.expected.ir.glsl
@@ -1,11 +1,11 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+int tint_bitcast_from_f16(f16vec2 src) {
+  return int(packFloat2x16(src));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f16vec2 a = f16vec2(1.0hf, 2.0hf);
+  int b = tint_bitcast_from_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/32bit/vec2f16-u32.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/32bit/vec2f16-u32.wgsl.expected.ir.glsl
index 5cf8186..f5c0730 100644
--- a/test/tint/expressions/bitcast/let/32bit/vec2f16-u32.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/32bit/vec2f16-u32.wgsl.expected.ir.glsl
@@ -1,11 +1,11 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+uint tint_bitcast_from_f16(f16vec2 src) {
+  return uint(packFloat2x16(src));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f16vec2 a = f16vec2(1.0hf, 2.0hf);
+  uint b = tint_bitcast_from_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/64bit/vec2f32-vec2u32.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/64bit/vec2f32-vec2u32.wgsl.expected.ir.glsl
index 5cf8186..bde926d 100644
--- a/test/tint/expressions/bitcast/let/64bit/vec2f32-vec2u32.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/64bit/vec2f32-vec2u32.wgsl.expected.ir.glsl
@@ -1,11 +1,7 @@
-SKIP: FAILED
+#version 310 es
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  vec2 a = vec2(2.003662109375f, -513.03125f);
+  uvec2 b = floatBitsToUint(a);
+}
diff --git a/test/tint/expressions/bitcast/let/64bit/vec2f32-vec4f16.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/64bit/vec2f32-vec4f16.wgsl.expected.ir.glsl
index 5cf8186..5dfa497 100644
--- a/test/tint/expressions/bitcast/let/64bit/vec2f32-vec4f16.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/64bit/vec2f32-vec4f16.wgsl.expected.ir.glsl
@@ -1,11 +1,13 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+f16vec4 tint_bitcast_to_f16(vec2 src) {
+  uvec2 v = floatBitsToUint(src);
+  f16vec2 v_1 = unpackFloat2x16(v.x);
+  return f16vec4(v_1, unpackFloat2x16(v.y));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  vec2 a = vec2(2.003662109375f, -513.03125f);
+  f16vec4 b = tint_bitcast_to_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/64bit/vec2i32-vec4f16.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/64bit/vec2i32-vec4f16.wgsl.expected.ir.glsl
index 5cf8186..319c3b4 100644
--- a/test/tint/expressions/bitcast/let/64bit/vec2i32-vec4f16.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/64bit/vec2i32-vec4f16.wgsl.expected.ir.glsl
@@ -1,11 +1,13 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+f16vec4 tint_bitcast_to_f16(ivec2 src) {
+  uvec2 v = uvec2(src);
+  f16vec2 v_1 = unpackFloat2x16(v.x);
+  return f16vec4(v_1, unpackFloat2x16(v.y));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  ivec2 a = ivec2(1073757184, -1006616064);
+  f16vec4 b = tint_bitcast_to_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/64bit/vec2u32-vec4f16.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/64bit/vec2u32-vec4f16.wgsl.expected.ir.glsl
index 5cf8186..93bb97a 100644
--- a/test/tint/expressions/bitcast/let/64bit/vec2u32-vec4f16.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/64bit/vec2u32-vec4f16.wgsl.expected.ir.glsl
@@ -1,11 +1,13 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+f16vec4 tint_bitcast_to_f16(uvec2 src) {
+  uvec2 v = uvec2(src);
+  f16vec2 v_1 = unpackFloat2x16(v.x);
+  return f16vec4(v_1, unpackFloat2x16(v.y));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  uvec2 a = uvec2(1073757184u, 3288351232u);
+  f16vec4 b = tint_bitcast_to_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2f32.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2f32.wgsl.expected.ir.glsl
index 5cf8186..526f889 100644
--- a/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2f32.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2f32.wgsl.expected.ir.glsl
@@ -1,11 +1,12 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+vec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v = packFloat2x16(src.xy);
+  return uintBitsToFloat(uvec2(v, packFloat2x16(src.zw)));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f16vec4 a = f16vec4(1.0hf, 2.0hf, 3.0hf, -4.0hf);
+  vec2 b = tint_bitcast_from_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2i32.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2i32.wgsl.expected.ir.glsl
index 5cf8186..4e85030 100644
--- a/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2i32.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2i32.wgsl.expected.ir.glsl
@@ -1,11 +1,12 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+ivec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v = packFloat2x16(src.xy);
+  return ivec2(uvec2(v, packFloat2x16(src.zw)));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f16vec4 a = f16vec4(1.0hf, 2.0hf, 3.0hf, -4.0hf);
+  ivec2 b = tint_bitcast_from_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2u32.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2u32.wgsl.expected.ir.glsl
index 5cf8186..4a24e02 100644
--- a/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2u32.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/64bit/vec4f16-vec2u32.wgsl.expected.ir.glsl
@@ -1,11 +1,12 @@
-SKIP: FAILED
+#version 310 es
+#extension GL_AMD_gpu_shader_half_float: require
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+uvec2 tint_bitcast_from_f16(f16vec4 src) {
+  uint v = packFloat2x16(src.xy);
+  return uvec2(uvec2(v, packFloat2x16(src.zw)));
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  f16vec4 a = f16vec4(1.0hf, 2.0hf, 3.0hf, -4.0hf);
+  uvec2 b = tint_bitcast_from_f16(a);
+}
diff --git a/test/tint/expressions/bitcast/let/96bit/vec3f32-vec3u32.wgsl.expected.ir.glsl b/test/tint/expressions/bitcast/let/96bit/vec3f32-vec3u32.wgsl.expected.ir.glsl
index 5cf8186..807f091 100644
--- a/test/tint/expressions/bitcast/let/96bit/vec3f32-vec3u32.wgsl.expected.ir.glsl
+++ b/test/tint/expressions/bitcast/let/96bit/vec3f32-vec3u32.wgsl.expected.ir.glsl
@@ -1,11 +1,7 @@
-SKIP: FAILED
+#version 310 es
 
-<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:1106 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Bitcast
-********************************************************************
-*  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.  *
-********************************************************************
-
-tint executable returned error: signal: trace/BPT trap
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+  vec3 a = vec3(2.003662109375f, -513.03125f, -1024.25f);
+  uvec3 b = floatBitsToUint(a);
+}