tint: const eval of extractBits

Bug: tint:1581
Change-Id: I56e9b7de9aef803eaf6304c122f40e5a0c4dce67
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/108203
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index 1894f8b..6bf8553 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -464,8 +464,8 @@
 fn exp<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
 fn exp2<T: f32_f16>(T) -> T
 fn exp2<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
-fn extractBits<T: iu32>(T, u32, u32) -> T
-fn extractBits<N: num, T: iu32>(vec<N, T>, u32, u32) -> vec<N, T>
+@const fn extractBits<T: iu32>(T, u32, u32) -> T
+@const fn extractBits<N: num, T: iu32>(vec<N, T>, u32, u32) -> vec<N, T>
 fn faceForward<N: num, T: f32_f16>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T>
 @const fn firstLeadingBit<T: iu32>(T) -> T
 @const fn firstLeadingBit<N: num, T: iu32>(vec<N, T>) -> vec<N, T>
diff --git a/src/tint/resolver/const_eval.cc b/src/tint/resolver/const_eval.cc
index f18c0d5..c94ed3b 100644
--- a/src/tint/resolver/const_eval.cc
+++ b/src/tint/resolver/const_eval.cc
@@ -1726,6 +1726,61 @@
     return TransformElements(builder, ty, transform, args[0]);
 }
 
+ConstEval::Result ConstEval::extractBits(const sem::Type* ty,
+                                         utils::VectorRef<const sem::Constant*> args,
+                                         const Source& source) {
+    auto transform = [&](const sem::Constant* c0) {
+        auto create = [&](auto in_e) -> ImplResult {
+            using NumberT = decltype(in_e);
+            using T = UnwrapNumber<NumberT>;
+            using UT = std::make_unsigned_t<T>;
+            using NumberUT = Number<UT>;
+
+            // Read args that are always scalar
+            NumberUT in_offset = args[1]->As<NumberUT>();
+            NumberUT in_count = args[2]->As<NumberUT>();
+
+            constexpr UT w = sizeof(UT) * 8;
+            if ((in_offset + in_count) > w) {
+                AddError("'offset + 'count' must be less than or equal to the bit width of 'e'",
+                         source);
+                return utils::Failure;
+            }
+
+            // Cast all to unsigned
+            UT e = static_cast<UT>(in_e);
+            UT o = static_cast<UT>(in_offset);
+            UT c = static_cast<UT>(in_count);
+
+            NumberT result;
+            if (c == UT{0}) {
+                // The result is 0 if c is 0
+                result = NumberT{0};
+            } else if (c == w) {
+                // The result is e if c is w
+                result = NumberT{e};
+            } else {
+                // Otherwise, bits 0..c - 1 of the result are copied from bits o..o + c - 1 of e.
+                UT src_mask = ((UT{1} << c) - UT{1}) << o;
+                UT r = (e & src_mask) >> o;
+                if constexpr (IsSignedIntegral<NumberT>) {
+                    // Other bits of the result are the same as bit c - 1 of the result.
+                    // Only need to set other bits if bit at c - 1 of result is 1
+                    if ((r & (UT{1} << (c - UT{1}))) != UT{0}) {
+                        UT dst_mask = src_mask >> o;
+                        r = r | (~UT{0} & ~dst_mask);
+                    }
+                }
+
+                result = NumberT{r};
+            }
+            return CreateElement(builder, c0->Type(), result);
+        };
+        return Dispatch_iu32(create, c0);
+    };
+    return TransformElements(builder, ty, transform, args[0]);
+}
+
 ConstEval::Result ConstEval::firstLeadingBit(const sem::Type* ty,
                                              utils::VectorRef<const sem::Constant*> args,
                                              const Source&) {
diff --git a/src/tint/resolver/const_eval.h b/src/tint/resolver/const_eval.h
index d6f5594..1fd7412 100644
--- a/src/tint/resolver/const_eval.h
+++ b/src/tint/resolver/const_eval.h
@@ -476,6 +476,15 @@
                               utils::VectorRef<const sem::Constant*> args,
                               const Source& source);
 
+    /// extractBits builtin
+    /// @param ty the expression type
+    /// @param args the input arguments
+    /// @param source the source location of the conversion
+    /// @return the result value, or null if the value cannot be calculated
+    Result extractBits(const sem::Type* ty,
+        utils::VectorRef<const sem::Constant*> args,
+        const Source& source);
+
     /// firstLeadingBit builtin
     /// @param ty the expression type
     /// @param args the input arguments
diff --git a/src/tint/resolver/const_eval_builtin_test.cc b/src/tint/resolver/const_eval_builtin_test.cc
index b0fa425..7496214 100644
--- a/src/tint/resolver/const_eval_builtin_test.cc
+++ b/src/tint/resolver/const_eval_builtin_test.cc
@@ -831,6 +831,109 @@
                              std::make_tuple(u32::Highest(), u32::Highest())));
 
 template <typename T>
+std::vector<Case> ExtractBitsCases() {
+    using UT = Number<std::make_unsigned_t<UnwrapNumber<T>>>;
+
+    // If T is signed, fills most significant bits of `val` with 1s
+    auto set_msbs_if_signed = [](T val) {
+        if constexpr (IsSignedIntegral<T>) {
+            T result = T(~0);
+            for (size_t b = 0; val; ++b) {
+                if ((val & 1) == 0) {
+                    result = result & ~(1 << b);  // Clear bit b
+                }
+                val = val >> 1;
+            }
+            return result;
+        } else {
+            return val;
+        }
+    };
+
+    auto e = T(0b10100011110001011010001111000101);
+    auto f = T(0b01010101010101010101010101010101);
+    auto g = T(0b11111010001111000101101000111100);
+
+    auto r = std::vector<Case>{
+        // args: e, offset, count
+
+        // If count is 0, result is 0
+        C({e, UT(0), UT(0)}, T(0)),  //
+        C({e, UT(1), UT(0)}, T(0)),  //
+        C({e, UT(2), UT(0)}, T(0)),  //
+        C({e, UT(3), UT(0)}, T(0)),
+        // ...
+        C({e, UT(29), UT(0)}, T(0)),  //
+        C({e, UT(30), UT(0)}, T(0)),  //
+        C({e, UT(31), UT(0)}, T(0)),
+
+        // Extract at offset 0, varying counts
+        C({e, UT(0), UT(1)}, set_msbs_if_signed(T(0b1))),    //
+        C({e, UT(0), UT(2)}, T(0b01)),                       //
+        C({e, UT(0), UT(3)}, set_msbs_if_signed(T(0b101))),  //
+        C({e, UT(0), UT(4)}, T(0b0101)),                     //
+        C({e, UT(0), UT(5)}, T(0b00101)),                    //
+        C({e, UT(0), UT(6)}, T(0b000101)),                   //
+        // ...
+        C({e, UT(0), UT(28)}, T(0b0011110001011010001111000101)),                        //
+        C({e, UT(0), UT(29)}, T(0b00011110001011010001111000101)),                       //
+        C({e, UT(0), UT(30)}, set_msbs_if_signed(T(0b100011110001011010001111000101))),  //
+        C({e, UT(0), UT(31)}, T(0b0100011110001011010001111000101)),                     //
+        C({e, UT(0), UT(32)}, T(0b10100011110001011010001111000101)),                    //
+
+        // Extract at varying offsets and counts
+        C({e, UT(0), UT(1)}, set_msbs_if_signed(T(0b1))),                   //
+        C({e, UT(31), UT(1)}, set_msbs_if_signed(T(0b1))),                  //
+        C({e, UT(3), UT(5)}, set_msbs_if_signed(T(0b11000))),               //
+        C({e, UT(4), UT(7)}, T(0b0111100)),                                 //
+        C({e, UT(10), UT(16)}, set_msbs_if_signed(T(0b1111000101101000))),  //
+        C({e, UT(10), UT(22)}, set_msbs_if_signed(T(0b1010001111000101101000))),
+
+        // Vector tests
+        C({Vec(e, f, g),                          //
+           Val(UT(5)), Val(UT(8))},               //
+          Vec(T(0b00011110),                      //
+              set_msbs_if_signed(T(0b10101010)),  //
+              set_msbs_if_signed(T(0b11010001)))),
+    };
+
+    return r;
+}
+INSTANTIATE_TEST_SUITE_P(  //
+    ExtractBits,
+    ResolverConstEvalBuiltinTest,
+    testing::Combine(testing::Values(sem::BuiltinType::kExtractBits),
+                     testing::ValuesIn(Concat(ExtractBitsCases<i32>(),  //
+                                              ExtractBitsCases<u32>()))));
+
+using ResolverConstEvalBuiltinTest_ExtractBits_InvalidOffsetAndCount =
+    ResolverTestWithParam<std::tuple<size_t, size_t>>;
+TEST_P(ResolverConstEvalBuiltinTest_ExtractBits_InvalidOffsetAndCount, Test) {
+    auto& p = GetParam();
+    auto* expr = Call(Source{{12, 24}}, sem::str(sem::BuiltinType::kExtractBits), Expr(1_u),
+                      Expr(u32(std::get<0>(p))), Expr(u32(std::get<1>(p))));
+    GlobalConst("C", expr);
+    EXPECT_FALSE(r()->Resolve());
+    EXPECT_EQ(r()->error(),
+              "12:24 error: 'offset + 'count' must be less than or equal to the bit width of 'e'");
+}
+INSTANTIATE_TEST_SUITE_P(ExtractBits,
+                         ResolverConstEvalBuiltinTest_ExtractBits_InvalidOffsetAndCount,
+                         testing::Values(                         //
+                             std::make_tuple(33, 0),              //
+                             std::make_tuple(34, 0),              //
+                             std::make_tuple(1000, 0),            //
+                             std::make_tuple(u32::Highest(), 0),  //
+                             std::make_tuple(0, 33),              //
+                             std::make_tuple(0, 34),              //
+                             std::make_tuple(0, 1000),            //
+                             std::make_tuple(0, u32::Highest()),  //
+                             std::make_tuple(33, 33),             //
+                             std::make_tuple(34, 34),             //
+                             std::make_tuple(1000, 1000),         //
+                             std::make_tuple(u32::Highest(), u32::Highest())));
+
+template <typename T>
 std::vector<Case> SaturateCases() {
     return {
         C({T(0)}, T(0)),
diff --git a/src/tint/resolver/intrinsic_table.inl b/src/tint/resolver/intrinsic_table.inl
index 021d993..f8dbd43 100644
--- a/src/tint/resolver/intrinsic_table.inl
+++ b/src/tint/resolver/intrinsic_table.inl
@@ -12230,7 +12230,7 @@
     /* parameters */ &kParameters[594],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
-    /* const eval */ nullptr,
+    /* const eval */ &ConstEval::extractBits,
   },
   {
     /* [325] */
@@ -12242,7 +12242,7 @@
     /* parameters */ &kParameters[459],
     /* return matcher indices */ &kMatcherIndices[30],
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
-    /* const eval */ nullptr,
+    /* const eval */ &ConstEval::extractBits,
   },
   {
     /* [326] */
diff --git a/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.dxc.hlsl
index a151040..895f98b 100644
--- a/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.dxc.hlsl
@@ -1,13 +1,5 @@
-uint3 tint_extract_bits(uint3 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint3((shl).xxx)) >> uint3((shr).xxx));
-}
-
 void extractBits_12b197() {
-  uint3 res = tint_extract_bits((1u).xxx, 1u, 1u);
+  uint3 res = (0u).xxx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.fxc.hlsl
index a151040..895f98b 100644
--- a/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.fxc.hlsl
@@ -1,13 +1,5 @@
-uint3 tint_extract_bits(uint3 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint3((shl).xxx)) >> uint3((shr).xxx));
-}
-
 void extractBits_12b197() {
-  uint3 res = tint_extract_bits((1u).xxx, 1u, 1u);
+  uint3 res = (0u).xxx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.glsl b/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.glsl
index c40ed7d..42ad28d 100644
--- a/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.glsl
@@ -1,13 +1,7 @@
 #version 310 es
 
-uvec3 tint_extract_bits(uvec3 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_12b197() {
-  uvec3 res = tint_extract_bits(uvec3(1u), 1u, 1u);
+  uvec3 res = uvec3(0u);
 }
 
 vec4 vertex_main() {
@@ -26,14 +20,8 @@
 #version 310 es
 precision mediump float;
 
-uvec3 tint_extract_bits(uvec3 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_12b197() {
-  uvec3 res = tint_extract_bits(uvec3(1u), 1u, 1u);
+  uvec3 res = uvec3(0u);
 }
 
 void fragment_main() {
@@ -46,14 +34,8 @@
 }
 #version 310 es
 
-uvec3 tint_extract_bits(uvec3 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_12b197() {
-  uvec3 res = tint_extract_bits(uvec3(1u), 1u, 1u);
+  uvec3 res = uvec3(0u);
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.msl b/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.msl
index 9a65f19..e54b745 100644
--- a/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.msl
@@ -1,14 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-uint3 tint_extract_bits(uint3 v, uint offset, uint count) {
-  uint const s = min(offset, 32u);
-  uint const e = min(32u, (s + count));
-  return extract_bits(v, s, (e - s));
-}
-
 void extractBits_12b197() {
-  uint3 res = tint_extract_bits(uint3(1u), 1u, 1u);
+  uint3 res = uint3(0u);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.spvasm
index 6edac5a..1c44720 100644
--- a/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/extractBits/12b197.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 48
+; Bound: 32
 ; Schema: 0
                OpCapability Shader
-         %18 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -13,10 +12,6 @@
                OpExecutionMode %compute_main LocalSize 1 1 1
                OpName %value "value"
                OpName %vertex_point_size "vertex_point_size"
-               OpName %tint_extract_bits "tint_extract_bits"
-               OpName %v "v"
-               OpName %offset "offset"
-               OpName %count "count"
                OpName %extractBits_12b197 "extractBits_12b197"
                OpName %res "res"
                OpName %vertex_main_inner "vertex_main_inner"
@@ -33,56 +28,39 @@
 %_ptr_Output_float = OpTypePointer Output %float
           %8 = OpConstantNull %float
 %vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
        %uint = OpTypeInt 32 0
      %v3uint = OpTypeVector %uint 3
-          %9 = OpTypeFunction %v3uint %v3uint %uint %uint
-    %uint_32 = OpConstant %uint 32
-       %void = OpTypeVoid
-         %24 = OpTypeFunction %void
-     %uint_1 = OpConstant %uint 1
-         %30 = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
+         %15 = OpConstantNull %v3uint
 %_ptr_Function_v3uint = OpTypePointer Function %v3uint
-         %33 = OpConstantNull %v3uint
-         %34 = OpTypeFunction %v4float
+         %18 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
-%tint_extract_bits = OpFunction %v3uint None %9
-          %v = OpFunctionParameter %v3uint
-     %offset = OpFunctionParameter %uint
-      %count = OpFunctionParameter %uint
-         %16 = OpLabel
-         %17 = OpExtInst %uint %18 UMin %offset %uint_32
-         %21 = OpIAdd %uint %17 %count
-         %20 = OpExtInst %uint %18 UMin %uint_32 %21
-         %23 = OpISub %uint %20 %17
-         %22 = OpBitFieldUExtract %v3uint %v %17 %23
-               OpReturnValue %22
-               OpFunctionEnd
-%extractBits_12b197 = OpFunction %void None %24
-         %27 = OpLabel
-        %res = OpVariable %_ptr_Function_v3uint Function %33
-         %28 = OpFunctionCall %v3uint %tint_extract_bits %30 %uint_1 %uint_1
-               OpStore %res %28
+%extractBits_12b197 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function_v3uint Function %15
+               OpStore %res %15
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %34
-         %36 = OpLabel
-         %37 = OpFunctionCall %void %extractBits_12b197
+%vertex_main_inner = OpFunction %v4float None %18
+         %20 = OpLabel
+         %21 = OpFunctionCall %void %extractBits_12b197
                OpReturnValue %5
                OpFunctionEnd
-%vertex_main = OpFunction %void None %24
-         %39 = OpLabel
-         %40 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %40
+%vertex_main = OpFunction %void None %9
+         %23 = OpLabel
+         %24 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %24
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
-%fragment_main = OpFunction %void None %24
-         %43 = OpLabel
-         %44 = OpFunctionCall %void %extractBits_12b197
+%fragment_main = OpFunction %void None %9
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %extractBits_12b197
                OpReturn
                OpFunctionEnd
-%compute_main = OpFunction %void None %24
-         %46 = OpLabel
-         %47 = OpFunctionCall %void %extractBits_12b197
+%compute_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %void %extractBits_12b197
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.dxc.hlsl
index 870063d..6a01326 100644
--- a/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.dxc.hlsl
@@ -1,13 +1,5 @@
-int tint_extract_bits(int v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << shl) >> shr);
-}
-
 void extractBits_249874() {
-  int res = tint_extract_bits(1, 1u, 1u);
+  int res = 0;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.fxc.hlsl
index 870063d..6a01326 100644
--- a/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.fxc.hlsl
@@ -1,13 +1,5 @@
-int tint_extract_bits(int v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << shl) >> shr);
-}
-
 void extractBits_249874() {
-  int res = tint_extract_bits(1, 1u, 1u);
+  int res = 0;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.glsl b/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.glsl
index e0523f2..5b1cf69 100644
--- a/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.glsl
@@ -1,13 +1,7 @@
 #version 310 es
 
-int tint_extract_bits(int v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_249874() {
-  int res = tint_extract_bits(1, 1u, 1u);
+  int res = 0;
 }
 
 vec4 vertex_main() {
@@ -26,14 +20,8 @@
 #version 310 es
 precision mediump float;
 
-int tint_extract_bits(int v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_249874() {
-  int res = tint_extract_bits(1, 1u, 1u);
+  int res = 0;
 }
 
 void fragment_main() {
@@ -46,14 +34,8 @@
 }
 #version 310 es
 
-int tint_extract_bits(int v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_249874() {
-  int res = tint_extract_bits(1, 1u, 1u);
+  int res = 0;
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.msl b/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.msl
index 7b3e488..1cc7b4c 100644
--- a/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.msl
@@ -1,14 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-int tint_extract_bits(int v, uint offset, uint count) {
-  uint const s = min(offset, 32u);
-  uint const e = min(32u, (s + count));
-  return extract_bits(v, s, (e - s));
-}
-
 void extractBits_249874() {
-  int res = tint_extract_bits(1, 1u, 1u);
+  int res = 0;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.spvasm
index 6758f24..a59e9c3 100644
--- a/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/extractBits/249874.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 48
+; Bound: 31
 ; Schema: 0
                OpCapability Shader
-         %18 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -13,10 +12,6 @@
                OpExecutionMode %compute_main LocalSize 1 1 1
                OpName %value "value"
                OpName %vertex_point_size "vertex_point_size"
-               OpName %tint_extract_bits "tint_extract_bits"
-               OpName %v "v"
-               OpName %offset "offset"
-               OpName %count "count"
                OpName %extractBits_249874 "extractBits_249874"
                OpName %res "res"
                OpName %vertex_main_inner "vertex_main_inner"
@@ -33,56 +28,38 @@
 %_ptr_Output_float = OpTypePointer Output %float
           %8 = OpConstantNull %float
 %vertex_point_size = OpVariable %_ptr_Output_float Output %8
-        %int = OpTypeInt 32 1
-       %uint = OpTypeInt 32 0
-          %9 = OpTypeFunction %int %int %uint %uint
-    %uint_32 = OpConstant %uint 32
        %void = OpTypeVoid
-         %24 = OpTypeFunction %void
-      %int_1 = OpConstant %int 1
-     %uint_1 = OpConstant %uint 1
+          %9 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+         %14 = OpConstantNull %int
 %_ptr_Function_int = OpTypePointer Function %int
-         %33 = OpConstantNull %int
-         %34 = OpTypeFunction %v4float
+         %17 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
-%tint_extract_bits = OpFunction %int None %9
-          %v = OpFunctionParameter %int
-     %offset = OpFunctionParameter %uint
-      %count = OpFunctionParameter %uint
-         %16 = OpLabel
-         %17 = OpExtInst %uint %18 UMin %offset %uint_32
-         %21 = OpIAdd %uint %17 %count
-         %20 = OpExtInst %uint %18 UMin %uint_32 %21
-         %23 = OpISub %uint %20 %17
-         %22 = OpBitFieldSExtract %int %v %17 %23
-               OpReturnValue %22
-               OpFunctionEnd
-%extractBits_249874 = OpFunction %void None %24
-         %27 = OpLabel
-        %res = OpVariable %_ptr_Function_int Function %33
-         %28 = OpFunctionCall %int %tint_extract_bits %int_1 %uint_1 %uint_1
-               OpStore %res %28
+%extractBits_249874 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function_int Function %14
+               OpStore %res %14
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %34
-         %36 = OpLabel
-         %37 = OpFunctionCall %void %extractBits_249874
+%vertex_main_inner = OpFunction %v4float None %17
+         %19 = OpLabel
+         %20 = OpFunctionCall %void %extractBits_249874
                OpReturnValue %5
                OpFunctionEnd
-%vertex_main = OpFunction %void None %24
-         %39 = OpLabel
-         %40 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %40
+%vertex_main = OpFunction %void None %9
+         %22 = OpLabel
+         %23 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %23
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
-%fragment_main = OpFunction %void None %24
-         %43 = OpLabel
-         %44 = OpFunctionCall %void %extractBits_249874
+%fragment_main = OpFunction %void None %9
+         %26 = OpLabel
+         %27 = OpFunctionCall %void %extractBits_249874
                OpReturn
                OpFunctionEnd
-%compute_main = OpFunction %void None %24
-         %46 = OpLabel
-         %47 = OpFunctionCall %void %extractBits_249874
+%compute_main = OpFunction %void None %9
+         %29 = OpLabel
+         %30 = OpFunctionCall %void %extractBits_249874
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.dxc.hlsl
index 2b42e6a..a1ed698 100644
--- a/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.dxc.hlsl
@@ -1,13 +1,5 @@
-uint4 tint_extract_bits(uint4 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint4((shl).xxxx)) >> uint4((shr).xxxx));
-}
-
 void extractBits_631377() {
-  uint4 res = tint_extract_bits((1u).xxxx, 1u, 1u);
+  uint4 res = (0u).xxxx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.fxc.hlsl
index 2b42e6a..a1ed698 100644
--- a/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.fxc.hlsl
@@ -1,13 +1,5 @@
-uint4 tint_extract_bits(uint4 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint4((shl).xxxx)) >> uint4((shr).xxxx));
-}
-
 void extractBits_631377() {
-  uint4 res = tint_extract_bits((1u).xxxx, 1u, 1u);
+  uint4 res = (0u).xxxx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.glsl b/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.glsl
index b88b73b..85fb7c7 100644
--- a/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.glsl
@@ -1,13 +1,7 @@
 #version 310 es
 
-uvec4 tint_extract_bits(uvec4 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_631377() {
-  uvec4 res = tint_extract_bits(uvec4(1u), 1u, 1u);
+  uvec4 res = uvec4(0u);
 }
 
 vec4 vertex_main() {
@@ -26,14 +20,8 @@
 #version 310 es
 precision mediump float;
 
-uvec4 tint_extract_bits(uvec4 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_631377() {
-  uvec4 res = tint_extract_bits(uvec4(1u), 1u, 1u);
+  uvec4 res = uvec4(0u);
 }
 
 void fragment_main() {
@@ -46,14 +34,8 @@
 }
 #version 310 es
 
-uvec4 tint_extract_bits(uvec4 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_631377() {
-  uvec4 res = tint_extract_bits(uvec4(1u), 1u, 1u);
+  uvec4 res = uvec4(0u);
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.msl b/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.msl
index 2190ecd..803774c 100644
--- a/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.msl
@@ -1,14 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-uint4 tint_extract_bits(uint4 v, uint offset, uint count) {
-  uint const s = min(offset, 32u);
-  uint const e = min(32u, (s + count));
-  return extract_bits(v, s, (e - s));
-}
-
 void extractBits_631377() {
-  uint4 res = tint_extract_bits(uint4(1u), 1u, 1u);
+  uint4 res = uint4(0u);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.spvasm
index 6f34fb5..c2bad0a 100644
--- a/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/extractBits/631377.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 48
+; Bound: 32
 ; Schema: 0
                OpCapability Shader
-         %18 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -13,10 +12,6 @@
                OpExecutionMode %compute_main LocalSize 1 1 1
                OpName %value "value"
                OpName %vertex_point_size "vertex_point_size"
-               OpName %tint_extract_bits "tint_extract_bits"
-               OpName %v "v"
-               OpName %offset "offset"
-               OpName %count "count"
                OpName %extractBits_631377 "extractBits_631377"
                OpName %res "res"
                OpName %vertex_main_inner "vertex_main_inner"
@@ -33,56 +28,39 @@
 %_ptr_Output_float = OpTypePointer Output %float
           %8 = OpConstantNull %float
 %vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
        %uint = OpTypeInt 32 0
      %v4uint = OpTypeVector %uint 4
-          %9 = OpTypeFunction %v4uint %v4uint %uint %uint
-    %uint_32 = OpConstant %uint 32
-       %void = OpTypeVoid
-         %24 = OpTypeFunction %void
-     %uint_1 = OpConstant %uint 1
-         %30 = OpConstantComposite %v4uint %uint_1 %uint_1 %uint_1 %uint_1
+         %15 = OpConstantNull %v4uint
 %_ptr_Function_v4uint = OpTypePointer Function %v4uint
-         %33 = OpConstantNull %v4uint
-         %34 = OpTypeFunction %v4float
+         %18 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
-%tint_extract_bits = OpFunction %v4uint None %9
-          %v = OpFunctionParameter %v4uint
-     %offset = OpFunctionParameter %uint
-      %count = OpFunctionParameter %uint
-         %16 = OpLabel
-         %17 = OpExtInst %uint %18 UMin %offset %uint_32
-         %21 = OpIAdd %uint %17 %count
-         %20 = OpExtInst %uint %18 UMin %uint_32 %21
-         %23 = OpISub %uint %20 %17
-         %22 = OpBitFieldUExtract %v4uint %v %17 %23
-               OpReturnValue %22
-               OpFunctionEnd
-%extractBits_631377 = OpFunction %void None %24
-         %27 = OpLabel
-        %res = OpVariable %_ptr_Function_v4uint Function %33
-         %28 = OpFunctionCall %v4uint %tint_extract_bits %30 %uint_1 %uint_1
-               OpStore %res %28
+%extractBits_631377 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function_v4uint Function %15
+               OpStore %res %15
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %34
-         %36 = OpLabel
-         %37 = OpFunctionCall %void %extractBits_631377
+%vertex_main_inner = OpFunction %v4float None %18
+         %20 = OpLabel
+         %21 = OpFunctionCall %void %extractBits_631377
                OpReturnValue %5
                OpFunctionEnd
-%vertex_main = OpFunction %void None %24
-         %39 = OpLabel
-         %40 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %40
+%vertex_main = OpFunction %void None %9
+         %23 = OpLabel
+         %24 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %24
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
-%fragment_main = OpFunction %void None %24
-         %43 = OpLabel
-         %44 = OpFunctionCall %void %extractBits_631377
+%fragment_main = OpFunction %void None %9
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %extractBits_631377
                OpReturn
                OpFunctionEnd
-%compute_main = OpFunction %void None %24
-         %46 = OpLabel
-         %47 = OpFunctionCall %void %extractBits_631377
+%compute_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %void %extractBits_631377
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.dxc.hlsl
index 301bcf6..8a3423e 100644
--- a/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.dxc.hlsl
@@ -1,13 +1,5 @@
-int2 tint_extract_bits(int2 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint2((shl).xx)) >> uint2((shr).xx));
-}
-
 void extractBits_a99a8d() {
-  int2 res = tint_extract_bits((1).xx, 1u, 1u);
+  int2 res = (0).xx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.fxc.hlsl
index 301bcf6..8a3423e 100644
--- a/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.fxc.hlsl
@@ -1,13 +1,5 @@
-int2 tint_extract_bits(int2 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint2((shl).xx)) >> uint2((shr).xx));
-}
-
 void extractBits_a99a8d() {
-  int2 res = tint_extract_bits((1).xx, 1u, 1u);
+  int2 res = (0).xx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.glsl b/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.glsl
index fa42616..ed2d067 100644
--- a/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.glsl
@@ -1,13 +1,7 @@
 #version 310 es
 
-ivec2 tint_extract_bits(ivec2 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_a99a8d() {
-  ivec2 res = tint_extract_bits(ivec2(1), 1u, 1u);
+  ivec2 res = ivec2(0);
 }
 
 vec4 vertex_main() {
@@ -26,14 +20,8 @@
 #version 310 es
 precision mediump float;
 
-ivec2 tint_extract_bits(ivec2 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_a99a8d() {
-  ivec2 res = tint_extract_bits(ivec2(1), 1u, 1u);
+  ivec2 res = ivec2(0);
 }
 
 void fragment_main() {
@@ -46,14 +34,8 @@
 }
 #version 310 es
 
-ivec2 tint_extract_bits(ivec2 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_a99a8d() {
-  ivec2 res = tint_extract_bits(ivec2(1), 1u, 1u);
+  ivec2 res = ivec2(0);
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.msl b/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.msl
index 915b684..a3275ce 100644
--- a/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.msl
@@ -1,14 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-int2 tint_extract_bits(int2 v, uint offset, uint count) {
-  uint const s = min(offset, 32u);
-  uint const e = min(32u, (s + count));
-  return extract_bits(v, s, (e - s));
-}
-
 void extractBits_a99a8d() {
-  int2 res = tint_extract_bits(int2(1), 1u, 1u);
+  int2 res = int2(0);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.spvasm
index 8f66972..f599ffb 100644
--- a/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/extractBits/a99a8d.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 50
+; Bound: 32
 ; Schema: 0
                OpCapability Shader
-         %19 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -13,10 +12,6 @@
                OpExecutionMode %compute_main LocalSize 1 1 1
                OpName %value "value"
                OpName %vertex_point_size "vertex_point_size"
-               OpName %tint_extract_bits "tint_extract_bits"
-               OpName %v "v"
-               OpName %offset "offset"
-               OpName %count "count"
                OpName %extractBits_a99a8d "extractBits_a99a8d"
                OpName %res "res"
                OpName %vertex_main_inner "vertex_main_inner"
@@ -33,58 +28,39 @@
 %_ptr_Output_float = OpTypePointer Output %float
           %8 = OpConstantNull %float
 %vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
         %int = OpTypeInt 32 1
       %v2int = OpTypeVector %int 2
-       %uint = OpTypeInt 32 0
-          %9 = OpTypeFunction %v2int %v2int %uint %uint
-    %uint_32 = OpConstant %uint 32
-       %void = OpTypeVoid
-         %25 = OpTypeFunction %void
-      %int_1 = OpConstant %int 1
-         %31 = OpConstantComposite %v2int %int_1 %int_1
-     %uint_1 = OpConstant %uint 1
+         %15 = OpConstantNull %v2int
 %_ptr_Function_v2int = OpTypePointer Function %v2int
-         %35 = OpConstantNull %v2int
-         %36 = OpTypeFunction %v4float
+         %18 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
-%tint_extract_bits = OpFunction %v2int None %9
-          %v = OpFunctionParameter %v2int
-     %offset = OpFunctionParameter %uint
-      %count = OpFunctionParameter %uint
-         %17 = OpLabel
-         %18 = OpExtInst %uint %19 UMin %offset %uint_32
-         %22 = OpIAdd %uint %18 %count
-         %21 = OpExtInst %uint %19 UMin %uint_32 %22
-         %24 = OpISub %uint %21 %18
-         %23 = OpBitFieldSExtract %v2int %v %18 %24
-               OpReturnValue %23
-               OpFunctionEnd
-%extractBits_a99a8d = OpFunction %void None %25
-         %28 = OpLabel
-        %res = OpVariable %_ptr_Function_v2int Function %35
-         %29 = OpFunctionCall %v2int %tint_extract_bits %31 %uint_1 %uint_1
-               OpStore %res %29
+%extractBits_a99a8d = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function_v2int Function %15
+               OpStore %res %15
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %36
-         %38 = OpLabel
-         %39 = OpFunctionCall %void %extractBits_a99a8d
+%vertex_main_inner = OpFunction %v4float None %18
+         %20 = OpLabel
+         %21 = OpFunctionCall %void %extractBits_a99a8d
                OpReturnValue %5
                OpFunctionEnd
-%vertex_main = OpFunction %void None %25
-         %41 = OpLabel
-         %42 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %42
+%vertex_main = OpFunction %void None %9
+         %23 = OpLabel
+         %24 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %24
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
-%fragment_main = OpFunction %void None %25
-         %45 = OpLabel
-         %46 = OpFunctionCall %void %extractBits_a99a8d
+%fragment_main = OpFunction %void None %9
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %extractBits_a99a8d
                OpReturn
                OpFunctionEnd
-%compute_main = OpFunction %void None %25
-         %48 = OpLabel
-         %49 = OpFunctionCall %void %extractBits_a99a8d
+%compute_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %void %extractBits_a99a8d
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.dxc.hlsl
index 95e631e..7d634c6 100644
--- a/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.dxc.hlsl
@@ -1,13 +1,5 @@
-uint tint_extract_bits(uint v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << shl) >> shr);
-}
-
 void extractBits_ce81f8() {
-  uint res = tint_extract_bits(1u, 1u, 1u);
+  uint res = 0u;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.fxc.hlsl
index 95e631e..7d634c6 100644
--- a/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.fxc.hlsl
@@ -1,13 +1,5 @@
-uint tint_extract_bits(uint v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << shl) >> shr);
-}
-
 void extractBits_ce81f8() {
-  uint res = tint_extract_bits(1u, 1u, 1u);
+  uint res = 0u;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.glsl b/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.glsl
index 814cdc1..98abc22 100644
--- a/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.glsl
@@ -1,13 +1,7 @@
 #version 310 es
 
-uint tint_extract_bits(uint v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_ce81f8() {
-  uint res = tint_extract_bits(1u, 1u, 1u);
+  uint res = 0u;
 }
 
 vec4 vertex_main() {
@@ -26,14 +20,8 @@
 #version 310 es
 precision mediump float;
 
-uint tint_extract_bits(uint v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_ce81f8() {
-  uint res = tint_extract_bits(1u, 1u, 1u);
+  uint res = 0u;
 }
 
 void fragment_main() {
@@ -46,14 +34,8 @@
 }
 #version 310 es
 
-uint tint_extract_bits(uint v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_ce81f8() {
-  uint res = tint_extract_bits(1u, 1u, 1u);
+  uint res = 0u;
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.msl b/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.msl
index dfa4102..17f4809 100644
--- a/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.msl
@@ -1,14 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-uint tint_extract_bits(uint v, uint offset, uint count) {
-  uint const s = min(offset, 32u);
-  uint const e = min(32u, (s + count));
-  return extract_bits(v, s, (e - s));
-}
-
 void extractBits_ce81f8() {
-  uint res = tint_extract_bits(1u, 1u, 1u);
+  uint res = 0u;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.spvasm
index 2a11707..dd2f870 100644
--- a/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/extractBits/ce81f8.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 46
+; Bound: 31
 ; Schema: 0
                OpCapability Shader
-         %17 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -13,10 +12,6 @@
                OpExecutionMode %compute_main LocalSize 1 1 1
                OpName %value "value"
                OpName %vertex_point_size "vertex_point_size"
-               OpName %tint_extract_bits "tint_extract_bits"
-               OpName %v "v"
-               OpName %offset "offset"
-               OpName %count "count"
                OpName %extractBits_ce81f8 "extractBits_ce81f8"
                OpName %res "res"
                OpName %vertex_main_inner "vertex_main_inner"
@@ -33,54 +28,38 @@
 %_ptr_Output_float = OpTypePointer Output %float
           %8 = OpConstantNull %float
 %vertex_point_size = OpVariable %_ptr_Output_float Output %8
-       %uint = OpTypeInt 32 0
-          %9 = OpTypeFunction %uint %uint %uint %uint
-    %uint_32 = OpConstant %uint 32
        %void = OpTypeVoid
-         %23 = OpTypeFunction %void
-     %uint_1 = OpConstant %uint 1
+          %9 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+         %14 = OpConstantNull %uint
 %_ptr_Function_uint = OpTypePointer Function %uint
-         %31 = OpConstantNull %uint
-         %32 = OpTypeFunction %v4float
+         %17 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
-%tint_extract_bits = OpFunction %uint None %9
-          %v = OpFunctionParameter %uint
-     %offset = OpFunctionParameter %uint
-      %count = OpFunctionParameter %uint
-         %15 = OpLabel
-         %16 = OpExtInst %uint %17 UMin %offset %uint_32
-         %20 = OpIAdd %uint %16 %count
-         %19 = OpExtInst %uint %17 UMin %uint_32 %20
-         %22 = OpISub %uint %19 %16
-         %21 = OpBitFieldUExtract %uint %v %16 %22
-               OpReturnValue %21
-               OpFunctionEnd
-%extractBits_ce81f8 = OpFunction %void None %23
-         %26 = OpLabel
-        %res = OpVariable %_ptr_Function_uint Function %31
-         %27 = OpFunctionCall %uint %tint_extract_bits %uint_1 %uint_1 %uint_1
-               OpStore %res %27
+%extractBits_ce81f8 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function_uint Function %14
+               OpStore %res %14
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %32
-         %34 = OpLabel
-         %35 = OpFunctionCall %void %extractBits_ce81f8
+%vertex_main_inner = OpFunction %v4float None %17
+         %19 = OpLabel
+         %20 = OpFunctionCall %void %extractBits_ce81f8
                OpReturnValue %5
                OpFunctionEnd
-%vertex_main = OpFunction %void None %23
-         %37 = OpLabel
-         %38 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %38
+%vertex_main = OpFunction %void None %9
+         %22 = OpLabel
+         %23 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %23
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
-%fragment_main = OpFunction %void None %23
-         %41 = OpLabel
-         %42 = OpFunctionCall %void %extractBits_ce81f8
+%fragment_main = OpFunction %void None %9
+         %26 = OpLabel
+         %27 = OpFunctionCall %void %extractBits_ce81f8
                OpReturn
                OpFunctionEnd
-%compute_main = OpFunction %void None %23
-         %44 = OpLabel
-         %45 = OpFunctionCall %void %extractBits_ce81f8
+%compute_main = OpFunction %void None %9
+         %29 = OpLabel
+         %30 = OpFunctionCall %void %extractBits_ce81f8
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.dxc.hlsl
index d140d24..1a9ccc4 100644
--- a/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.dxc.hlsl
@@ -1,13 +1,5 @@
-int3 tint_extract_bits(int3 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint3((shl).xxx)) >> uint3((shr).xxx));
-}
-
 void extractBits_e04f5d() {
-  int3 res = tint_extract_bits((1).xxx, 1u, 1u);
+  int3 res = (0).xxx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.fxc.hlsl
index d140d24..1a9ccc4 100644
--- a/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.fxc.hlsl
@@ -1,13 +1,5 @@
-int3 tint_extract_bits(int3 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint3((shl).xxx)) >> uint3((shr).xxx));
-}
-
 void extractBits_e04f5d() {
-  int3 res = tint_extract_bits((1).xxx, 1u, 1u);
+  int3 res = (0).xxx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.glsl b/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.glsl
index de21ca0..d246f70 100644
--- a/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.glsl
@@ -1,13 +1,7 @@
 #version 310 es
 
-ivec3 tint_extract_bits(ivec3 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_e04f5d() {
-  ivec3 res = tint_extract_bits(ivec3(1), 1u, 1u);
+  ivec3 res = ivec3(0);
 }
 
 vec4 vertex_main() {
@@ -26,14 +20,8 @@
 #version 310 es
 precision mediump float;
 
-ivec3 tint_extract_bits(ivec3 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_e04f5d() {
-  ivec3 res = tint_extract_bits(ivec3(1), 1u, 1u);
+  ivec3 res = ivec3(0);
 }
 
 void fragment_main() {
@@ -46,14 +34,8 @@
 }
 #version 310 es
 
-ivec3 tint_extract_bits(ivec3 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_e04f5d() {
-  ivec3 res = tint_extract_bits(ivec3(1), 1u, 1u);
+  ivec3 res = ivec3(0);
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.msl b/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.msl
index c3a4673..4e7e9f3 100644
--- a/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.msl
@@ -1,14 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-int3 tint_extract_bits(int3 v, uint offset, uint count) {
-  uint const s = min(offset, 32u);
-  uint const e = min(32u, (s + count));
-  return extract_bits(v, s, (e - s));
-}
-
 void extractBits_e04f5d() {
-  int3 res = tint_extract_bits(int3(1), 1u, 1u);
+  int3 res = int3(0);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.spvasm
index 043e515..5bdeeef 100644
--- a/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/extractBits/e04f5d.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 50
+; Bound: 32
 ; Schema: 0
                OpCapability Shader
-         %19 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -13,10 +12,6 @@
                OpExecutionMode %compute_main LocalSize 1 1 1
                OpName %value "value"
                OpName %vertex_point_size "vertex_point_size"
-               OpName %tint_extract_bits "tint_extract_bits"
-               OpName %v "v"
-               OpName %offset "offset"
-               OpName %count "count"
                OpName %extractBits_e04f5d "extractBits_e04f5d"
                OpName %res "res"
                OpName %vertex_main_inner "vertex_main_inner"
@@ -33,58 +28,39 @@
 %_ptr_Output_float = OpTypePointer Output %float
           %8 = OpConstantNull %float
 %vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
         %int = OpTypeInt 32 1
       %v3int = OpTypeVector %int 3
-       %uint = OpTypeInt 32 0
-          %9 = OpTypeFunction %v3int %v3int %uint %uint
-    %uint_32 = OpConstant %uint 32
-       %void = OpTypeVoid
-         %25 = OpTypeFunction %void
-      %int_1 = OpConstant %int 1
-         %31 = OpConstantComposite %v3int %int_1 %int_1 %int_1
-     %uint_1 = OpConstant %uint 1
+         %15 = OpConstantNull %v3int
 %_ptr_Function_v3int = OpTypePointer Function %v3int
-         %35 = OpConstantNull %v3int
-         %36 = OpTypeFunction %v4float
+         %18 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
-%tint_extract_bits = OpFunction %v3int None %9
-          %v = OpFunctionParameter %v3int
-     %offset = OpFunctionParameter %uint
-      %count = OpFunctionParameter %uint
-         %17 = OpLabel
-         %18 = OpExtInst %uint %19 UMin %offset %uint_32
-         %22 = OpIAdd %uint %18 %count
-         %21 = OpExtInst %uint %19 UMin %uint_32 %22
-         %24 = OpISub %uint %21 %18
-         %23 = OpBitFieldSExtract %v3int %v %18 %24
-               OpReturnValue %23
-               OpFunctionEnd
-%extractBits_e04f5d = OpFunction %void None %25
-         %28 = OpLabel
-        %res = OpVariable %_ptr_Function_v3int Function %35
-         %29 = OpFunctionCall %v3int %tint_extract_bits %31 %uint_1 %uint_1
-               OpStore %res %29
+%extractBits_e04f5d = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function_v3int Function %15
+               OpStore %res %15
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %36
-         %38 = OpLabel
-         %39 = OpFunctionCall %void %extractBits_e04f5d
+%vertex_main_inner = OpFunction %v4float None %18
+         %20 = OpLabel
+         %21 = OpFunctionCall %void %extractBits_e04f5d
                OpReturnValue %5
                OpFunctionEnd
-%vertex_main = OpFunction %void None %25
-         %41 = OpLabel
-         %42 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %42
+%vertex_main = OpFunction %void None %9
+         %23 = OpLabel
+         %24 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %24
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
-%fragment_main = OpFunction %void None %25
-         %45 = OpLabel
-         %46 = OpFunctionCall %void %extractBits_e04f5d
+%fragment_main = OpFunction %void None %9
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %extractBits_e04f5d
                OpReturn
                OpFunctionEnd
-%compute_main = OpFunction %void None %25
-         %48 = OpLabel
-         %49 = OpFunctionCall %void %extractBits_e04f5d
+%compute_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %void %extractBits_e04f5d
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.dxc.hlsl
index 2b1ac94..dd5b07a 100644
--- a/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.dxc.hlsl
@@ -1,13 +1,5 @@
-uint2 tint_extract_bits(uint2 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint2((shl).xx)) >> uint2((shr).xx));
-}
-
 void extractBits_f28f69() {
-  uint2 res = tint_extract_bits((1u).xx, 1u, 1u);
+  uint2 res = (0u).xx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.fxc.hlsl
index 2b1ac94..dd5b07a 100644
--- a/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.fxc.hlsl
@@ -1,13 +1,5 @@
-uint2 tint_extract_bits(uint2 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint2((shl).xx)) >> uint2((shr).xx));
-}
-
 void extractBits_f28f69() {
-  uint2 res = tint_extract_bits((1u).xx, 1u, 1u);
+  uint2 res = (0u).xx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.glsl b/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.glsl
index 79a6a6c..e9efb96 100644
--- a/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.glsl
@@ -1,13 +1,7 @@
 #version 310 es
 
-uvec2 tint_extract_bits(uvec2 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_f28f69() {
-  uvec2 res = tint_extract_bits(uvec2(1u), 1u, 1u);
+  uvec2 res = uvec2(0u);
 }
 
 vec4 vertex_main() {
@@ -26,14 +20,8 @@
 #version 310 es
 precision mediump float;
 
-uvec2 tint_extract_bits(uvec2 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_f28f69() {
-  uvec2 res = tint_extract_bits(uvec2(1u), 1u, 1u);
+  uvec2 res = uvec2(0u);
 }
 
 void fragment_main() {
@@ -46,14 +34,8 @@
 }
 #version 310 es
 
-uvec2 tint_extract_bits(uvec2 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_f28f69() {
-  uvec2 res = tint_extract_bits(uvec2(1u), 1u, 1u);
+  uvec2 res = uvec2(0u);
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.msl b/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.msl
index f16211a..a42bf13 100644
--- a/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.msl
@@ -1,14 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-uint2 tint_extract_bits(uint2 v, uint offset, uint count) {
-  uint const s = min(offset, 32u);
-  uint const e = min(32u, (s + count));
-  return extract_bits(v, s, (e - s));
-}
-
 void extractBits_f28f69() {
-  uint2 res = tint_extract_bits(uint2(1u), 1u, 1u);
+  uint2 res = uint2(0u);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.spvasm
index c1279b1..f5b1f26 100644
--- a/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/extractBits/f28f69.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 48
+; Bound: 32
 ; Schema: 0
                OpCapability Shader
-         %18 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -13,10 +12,6 @@
                OpExecutionMode %compute_main LocalSize 1 1 1
                OpName %value "value"
                OpName %vertex_point_size "vertex_point_size"
-               OpName %tint_extract_bits "tint_extract_bits"
-               OpName %v "v"
-               OpName %offset "offset"
-               OpName %count "count"
                OpName %extractBits_f28f69 "extractBits_f28f69"
                OpName %res "res"
                OpName %vertex_main_inner "vertex_main_inner"
@@ -33,56 +28,39 @@
 %_ptr_Output_float = OpTypePointer Output %float
           %8 = OpConstantNull %float
 %vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
        %uint = OpTypeInt 32 0
      %v2uint = OpTypeVector %uint 2
-          %9 = OpTypeFunction %v2uint %v2uint %uint %uint
-    %uint_32 = OpConstant %uint 32
-       %void = OpTypeVoid
-         %24 = OpTypeFunction %void
-     %uint_1 = OpConstant %uint 1
-         %30 = OpConstantComposite %v2uint %uint_1 %uint_1
+         %15 = OpConstantNull %v2uint
 %_ptr_Function_v2uint = OpTypePointer Function %v2uint
-         %33 = OpConstantNull %v2uint
-         %34 = OpTypeFunction %v4float
+         %18 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
-%tint_extract_bits = OpFunction %v2uint None %9
-          %v = OpFunctionParameter %v2uint
-     %offset = OpFunctionParameter %uint
-      %count = OpFunctionParameter %uint
-         %16 = OpLabel
-         %17 = OpExtInst %uint %18 UMin %offset %uint_32
-         %21 = OpIAdd %uint %17 %count
-         %20 = OpExtInst %uint %18 UMin %uint_32 %21
-         %23 = OpISub %uint %20 %17
-         %22 = OpBitFieldUExtract %v2uint %v %17 %23
-               OpReturnValue %22
-               OpFunctionEnd
-%extractBits_f28f69 = OpFunction %void None %24
-         %27 = OpLabel
-        %res = OpVariable %_ptr_Function_v2uint Function %33
-         %28 = OpFunctionCall %v2uint %tint_extract_bits %30 %uint_1 %uint_1
-               OpStore %res %28
+%extractBits_f28f69 = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function_v2uint Function %15
+               OpStore %res %15
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %34
-         %36 = OpLabel
-         %37 = OpFunctionCall %void %extractBits_f28f69
+%vertex_main_inner = OpFunction %v4float None %18
+         %20 = OpLabel
+         %21 = OpFunctionCall %void %extractBits_f28f69
                OpReturnValue %5
                OpFunctionEnd
-%vertex_main = OpFunction %void None %24
-         %39 = OpLabel
-         %40 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %40
+%vertex_main = OpFunction %void None %9
+         %23 = OpLabel
+         %24 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %24
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
-%fragment_main = OpFunction %void None %24
-         %43 = OpLabel
-         %44 = OpFunctionCall %void %extractBits_f28f69
+%fragment_main = OpFunction %void None %9
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %extractBits_f28f69
                OpReturn
                OpFunctionEnd
-%compute_main = OpFunction %void None %24
-         %46 = OpLabel
-         %47 = OpFunctionCall %void %extractBits_f28f69
+%compute_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %void %extractBits_f28f69
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.dxc.hlsl
index 249b9aa..e843b7c 100644
--- a/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.dxc.hlsl
@@ -1,13 +1,5 @@
-int4 tint_extract_bits(int4 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint4((shl).xxxx)) >> uint4((shr).xxxx));
-}
-
 void extractBits_fb850f() {
-  int4 res = tint_extract_bits((1).xxxx, 1u, 1u);
+  int4 res = (0).xxxx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.fxc.hlsl
index 249b9aa..e843b7c 100644
--- a/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.fxc.hlsl
@@ -1,13 +1,5 @@
-int4 tint_extract_bits(int4 v, uint offset, uint count) {
-  const uint s = min(offset, 32u);
-  const uint e = min(32u, (s + count));
-  const uint shl = (32u - e);
-  const uint shr = (shl + s);
-  return ((v << uint4((shl).xxxx)) >> uint4((shr).xxxx));
-}
-
 void extractBits_fb850f() {
-  int4 res = tint_extract_bits((1).xxxx, 1u, 1u);
+  int4 res = (0).xxxx;
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.glsl b/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.glsl
index e075fcd..c132e9a 100644
--- a/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.glsl
@@ -1,13 +1,7 @@
 #version 310 es
 
-ivec4 tint_extract_bits(ivec4 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_fb850f() {
-  ivec4 res = tint_extract_bits(ivec4(1), 1u, 1u);
+  ivec4 res = ivec4(0);
 }
 
 vec4 vertex_main() {
@@ -26,14 +20,8 @@
 #version 310 es
 precision mediump float;
 
-ivec4 tint_extract_bits(ivec4 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_fb850f() {
-  ivec4 res = tint_extract_bits(ivec4(1), 1u, 1u);
+  ivec4 res = ivec4(0);
 }
 
 void fragment_main() {
@@ -46,14 +34,8 @@
 }
 #version 310 es
 
-ivec4 tint_extract_bits(ivec4 v, uint offset, uint count) {
-  uint s = min(offset, 32u);
-  uint e = min(32u, (s + count));
-  return bitfieldExtract(v, int(s), int((e - s)));
-}
-
 void extractBits_fb850f() {
-  ivec4 res = tint_extract_bits(ivec4(1), 1u, 1u);
+  ivec4 res = ivec4(0);
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.msl b/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.msl
index db0c906..bc43177 100644
--- a/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.msl
@@ -1,14 +1,8 @@
 #include <metal_stdlib>
 
 using namespace metal;
-int4 tint_extract_bits(int4 v, uint offset, uint count) {
-  uint const s = min(offset, 32u);
-  uint const e = min(32u, (s + count));
-  return extract_bits(v, s, (e - s));
-}
-
 void extractBits_fb850f() {
-  int4 res = tint_extract_bits(int4(1), 1u, 1u);
+  int4 res = int4(0);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.spvasm
index 99cc4e4..b257879 100644
--- a/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/extractBits/fb850f.wgsl.expected.spvasm
@@ -1,10 +1,9 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 50
+; Bound: 32
 ; Schema: 0
                OpCapability Shader
-         %19 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Vertex %vertex_main "vertex_main" %value %vertex_point_size
                OpEntryPoint Fragment %fragment_main "fragment_main"
@@ -13,10 +12,6 @@
                OpExecutionMode %compute_main LocalSize 1 1 1
                OpName %value "value"
                OpName %vertex_point_size "vertex_point_size"
-               OpName %tint_extract_bits "tint_extract_bits"
-               OpName %v "v"
-               OpName %offset "offset"
-               OpName %count "count"
                OpName %extractBits_fb850f "extractBits_fb850f"
                OpName %res "res"
                OpName %vertex_main_inner "vertex_main_inner"
@@ -33,58 +28,39 @@
 %_ptr_Output_float = OpTypePointer Output %float
           %8 = OpConstantNull %float
 %vertex_point_size = OpVariable %_ptr_Output_float Output %8
+       %void = OpTypeVoid
+          %9 = OpTypeFunction %void
         %int = OpTypeInt 32 1
       %v4int = OpTypeVector %int 4
-       %uint = OpTypeInt 32 0
-          %9 = OpTypeFunction %v4int %v4int %uint %uint
-    %uint_32 = OpConstant %uint 32
-       %void = OpTypeVoid
-         %25 = OpTypeFunction %void
-      %int_1 = OpConstant %int 1
-         %31 = OpConstantComposite %v4int %int_1 %int_1 %int_1 %int_1
-     %uint_1 = OpConstant %uint 1
+         %15 = OpConstantNull %v4int
 %_ptr_Function_v4int = OpTypePointer Function %v4int
-         %35 = OpConstantNull %v4int
-         %36 = OpTypeFunction %v4float
+         %18 = OpTypeFunction %v4float
     %float_1 = OpConstant %float 1
-%tint_extract_bits = OpFunction %v4int None %9
-          %v = OpFunctionParameter %v4int
-     %offset = OpFunctionParameter %uint
-      %count = OpFunctionParameter %uint
-         %17 = OpLabel
-         %18 = OpExtInst %uint %19 UMin %offset %uint_32
-         %22 = OpIAdd %uint %18 %count
-         %21 = OpExtInst %uint %19 UMin %uint_32 %22
-         %24 = OpISub %uint %21 %18
-         %23 = OpBitFieldSExtract %v4int %v %18 %24
-               OpReturnValue %23
-               OpFunctionEnd
-%extractBits_fb850f = OpFunction %void None %25
-         %28 = OpLabel
-        %res = OpVariable %_ptr_Function_v4int Function %35
-         %29 = OpFunctionCall %v4int %tint_extract_bits %31 %uint_1 %uint_1
-               OpStore %res %29
+%extractBits_fb850f = OpFunction %void None %9
+         %12 = OpLabel
+        %res = OpVariable %_ptr_Function_v4int Function %15
+               OpStore %res %15
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %36
-         %38 = OpLabel
-         %39 = OpFunctionCall %void %extractBits_fb850f
+%vertex_main_inner = OpFunction %v4float None %18
+         %20 = OpLabel
+         %21 = OpFunctionCall %void %extractBits_fb850f
                OpReturnValue %5
                OpFunctionEnd
-%vertex_main = OpFunction %void None %25
-         %41 = OpLabel
-         %42 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %42
+%vertex_main = OpFunction %void None %9
+         %23 = OpLabel
+         %24 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %24
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
-%fragment_main = OpFunction %void None %25
-         %45 = OpLabel
-         %46 = OpFunctionCall %void %extractBits_fb850f
+%fragment_main = OpFunction %void None %9
+         %27 = OpLabel
+         %28 = OpFunctionCall %void %extractBits_fb850f
                OpReturn
                OpFunctionEnd
-%compute_main = OpFunction %void None %25
-         %48 = OpLabel
-         %49 = OpFunctionCall %void %extractBits_fb850f
+%compute_main = OpFunction %void None %9
+         %30 = OpLabel
+         %31 = OpFunctionCall %void %extractBits_fb850f
                OpReturn
                OpFunctionEnd
diff --git a/webgpu-cts/expectations.txt b/webgpu-cts/expectations.txt
index 934866d..40adbbe 100644
--- a/webgpu-cts/expectations.txt
+++ b/webgpu-cts/expectations.txt
@@ -439,14 +439,6 @@
 crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,exp:f32:inputSource="const";vectorize=2 [ Failure ]
 crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,exp:f32:inputSource="const";vectorize=3 [ Failure ]
 crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,exp:f32:inputSource="const";vectorize=4 [ Failure ]
-crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,extractBits:i32:inputSource="const";width=1 [ Failure ]
-crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,extractBits:i32:inputSource="const";width=2 [ Failure ]
-crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,extractBits:i32:inputSource="const";width=3 [ Failure ]
-crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,extractBits:i32:inputSource="const";width=4 [ Failure ]
-crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,extractBits:u32:inputSource="const";width=1 [ Failure ]
-crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,extractBits:u32:inputSource="const";width=2 [ Failure ]
-crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,extractBits:u32:inputSource="const";width=3 [ Failure ]
-crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,extractBits:u32:inputSource="const";width=4 [ Failure ]
 crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,floor:f32:inputSource="const";vectorize="_undef_" [ Failure ]
 crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,floor:f32:inputSource="const";vectorize=2 [ Failure ]
 crbug.com/tint/1613 webgpu:shader,execution,expression,call,builtin,floor:f32:inputSource="const";vectorize=3 [ Failure ]