tint: implement const eval of binary divide

Bug: tint:1581
Change-Id: I72f7f34046086ad00d3bf8f21d67db831903d60b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/100861
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index a565160..8a80bf5 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -908,10 +908,10 @@
 @const("MultiplyVecMat") op * <T: fa_f32_f16, C: num, R: num> (vec<R, T>, mat<C, R, T>) -> vec<C, T>
 @const("MultiplyMatMat") op * <T: fa_f32_f16, K: num, C: num, R: num> (mat<K, R, T>, mat<C, K, T>) -> mat<C, R, T>
 
-op / <T: fiu32_f16>(T, T) -> T
-op / <T: fiu32_f16, N: num> (vec<N, T>, vec<N, T>) -> vec<N, T>
-op / <T: fiu32_f16, N: num> (vec<N, T>, T) -> vec<N, T>
-op / <T: fiu32_f16, N: num> (T, vec<N, T>) -> vec<N, T>
+@const op / <T: fia_fiu32_f16>(T, T) -> T
+@const op / <T: fia_fiu32_f16, N: num> (vec<N, T>, vec<N, T>) -> vec<N, T>
+@const op / <T: fia_fiu32_f16, N: num> (vec<N, T>, T) -> vec<N, T>
+@const op / <T: fia_fiu32_f16, N: num> (T, vec<N, T>) -> vec<N, T>
 
 op % <T: fiu32_f16>(T, T) -> T
 op % <T: fiu32_f16, N: num> (vec<N, T>, vec<N, T>) -> vec<N, T>
diff --git a/src/tint/number.h b/src/tint/number.h
index e96cfc7..5321158 100644
--- a/src/tint/number.h
+++ b/src/tint/number.h
@@ -64,19 +64,6 @@
 
 namespace tint {
 
-/// Evaluates to true iff T is a floating-point type or is NumberKindF16.
-template <typename T>
-constexpr bool IsFloatingPoint =
-    std::is_floating_point_v<T> || std::is_same_v<T, detail::NumberKindF16>;
-
-/// Evaluates to true iff T is an integer type.
-template <typename T>
-constexpr bool IsInteger = std::is_integral_v<T>;
-
-/// Evaluates to true iff T is an integer type, floating-point type or is NumberKindF16.
-template <typename T>
-constexpr bool IsNumeric = IsInteger<T> || IsFloatingPoint<T>;
-
 /// Evaluates to true iff T is a Number
 template <typename T>
 constexpr bool IsNumber = detail::IsNumber<T>::value;
@@ -85,6 +72,27 @@
 template <typename T>
 using UnwrapNumber = typename detail::NumberUnwrapper<T>::type;
 
+/// Evaluates to true iff T or Number<T> is a floating-point type or is NumberKindF16.
+template <typename T, typename U = std::conditional_t<IsNumber<T>, UnwrapNumber<T>, T>>
+constexpr bool IsFloatingPoint =
+    std::is_floating_point_v<U> || std::is_same_v<T, detail::NumberKindF16>;
+
+/// Evaluates to true iff T or Number<T> is an integral type.
+template <typename T, typename U = std::conditional_t<IsNumber<T>, UnwrapNumber<T>, T>>
+constexpr bool IsIntegral = std::is_integral_v<U>;
+
+/// Evaluates to true iff T or Number<T> is a signed integer type.
+template <typename T, typename U = std::conditional_t<IsNumber<T>, UnwrapNumber<T>, T>>
+constexpr bool IsSignedIntegral = std::is_integral_v<U> && std::is_signed_v<U>;
+
+/// Evaluates to true iff T or Number<T> is an unsigned integer type.
+template <typename T, typename U = std::conditional_t<IsNumber<T>, UnwrapNumber<T>, T>>
+constexpr bool IsUnsignedIntegral = std::is_integral_v<U> && std::is_unsigned_v<U>;
+
+/// Evaluates to true iff T is an integer type, floating-point type or is NumberKindF16.
+template <typename T>
+constexpr bool IsNumeric = IsIntegral<T> || IsFloatingPoint<T>;
+
 /// NumberBase is a CRTP base class for Number<T>
 template <typename NumberT>
 struct NumberBase {
diff --git a/src/tint/resolver/const_eval.cc b/src/tint/resolver/const_eval.cc
index 5b3cee2..0f4872b 100644
--- a/src/tint/resolver/const_eval.cc
+++ b/src/tint/resolver/const_eval.cc
@@ -1196,6 +1196,54 @@
     return CreateComposite(builder, ty, result_mat);
 }
 
+ConstEval::ConstantResult ConstEval::OpDivide(const sem::Type*,
+                                              utils::VectorRef<const sem::Constant*> args,
+                                              const Source& source) {
+    auto transform = [&](const sem::Constant* c0, const sem::Constant* c1) {
+        auto create = [&](auto i, auto j) -> const Constant* {
+            using NumberT = decltype(i);
+            NumberT result;
+            if constexpr (std::is_same_v<NumberT, AInt> || std::is_same_v<NumberT, AFloat>) {
+                // Check for over/underflow for abstract values
+                if (auto r = CheckedDiv(i, j)) {
+                    result = r->value;
+                } else {
+                    AddError(OverflowErrorMessage(i, "/", j), source);
+                    return nullptr;
+                }
+            } else {
+                using T = UnwrapNumber<NumberT>;
+                auto divide_values = [](T lhs, T rhs) {
+                    if constexpr (std::is_integral_v<T>) {
+                        // For integers, lhs / 0 returns lhs
+                        if (rhs == 0) {
+                            return lhs;
+                        }
+
+                        if constexpr (std::is_signed_v<T>) {
+                            // For signed integers, for lhs / -1, return lhs if lhs is the
+                            // most negative value
+                            if (rhs == -1 && lhs == std::numeric_limits<T>::min()) {
+                                return lhs;
+                            }
+                        }
+                    }
+                    return lhs / rhs;
+                };
+                result = divide_values(i.value, j.value);
+            }
+            return CreateElement(builder, c0->Type(), result);
+        };
+        return Dispatch_fia_fiu32_f16(create, c0, c1);
+    };
+
+    auto r = TransformBinaryElements(builder, transform, args[0], args[1]);
+    if (builder.Diagnostics().contains_errors()) {
+        return utils::Failure;
+    }
+    return r;
+}
+
 ConstEval::ConstantResult ConstEval::atan2(const sem::Type*,
                                            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 4007162..f84e28c 100644
--- a/src/tint/resolver/const_eval.h
+++ b/src/tint/resolver/const_eval.h
@@ -266,6 +266,15 @@
                                     utils::VectorRef<const sem::Constant*> args,
                                     const Source& source);
 
+    /// Divide operator '/'
+    /// @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
+    ConstantResult OpDivide(const sem::Type* ty,
+                            utils::VectorRef<const sem::Constant*> args,
+                            const Source& source);
+
     ////////////////////////////////////////////////////////////////////////////
     // Builtins
     ////////////////////////////////////////////////////////////////////////////
diff --git a/src/tint/resolver/const_eval_test.cc b/src/tint/resolver/const_eval_test.cc
index ff455dc..d21d60a 100644
--- a/src/tint/resolver/const_eval_test.cc
+++ b/src/tint/resolver/const_eval_test.cc
@@ -99,6 +99,20 @@
     return std::move(v1);
 }
 
+template <typename Vec, typename... Vecs>
+void ConcatInto(Vec& v1, Vecs&&... vs) {
+    auto total_size = v1.size() + (vs.size() + ...);
+    v1.reserve(total_size);
+    (std::move(vs.begin(), vs.end(), std::back_inserter(v1)), ...);
+}
+
+template <bool condition, typename Vec, typename... Vecs>
+void ConcatIntoIf([[maybe_unused]] Vec& v1, [[maybe_unused]] Vecs&&... vs) {
+    if constexpr (condition) {
+        ConcatInto(v1, std::forward<Vecs>(vs)...);
+    }
+}
+
 using ResolverConstEvalTest = ResolverTest;
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -3071,7 +3085,7 @@
             EXPECT_TYPE(value->Type(), sem->Type());
             EXPECT_EQ(value->As<T>(), values.expect);
 
-            if constexpr (IsInteger<UnwrapNumber<T>>) {
+            if constexpr (IsIntegral<UnwrapNumber<T>>) {
                 // Check that the constant's integer doesn't contain unexpected data in the MSBs
                 // that are outside of the bit-width of T.
                 EXPECT_EQ(value->As<AInt>(), AInt(values.expect));
@@ -3329,7 +3343,7 @@
             ForEachElemPair(value, expected_value,
                             [&](const sem::Constant* a, const sem::Constant* b) {
                                 EXPECT_EQ(a->As<T>(), b->As<T>());
-                                if constexpr (IsInteger<UnwrapNumber<T>>) {
+                                if constexpr (IsIntegral<UnwrapNumber<T>>) {
                                     // Check that the constant's integer doesn't contain unexpected
                                     // data in the MSBs that are outside of the bit-width of T.
                                     EXPECT_EQ(a->As<AInt>(), b->As<AInt>());
@@ -3351,7 +3365,7 @@
 
 template <typename T>
 std::vector<Case> OpAddIntCases() {
-    static_assert(IsInteger<UnwrapNumber<T>>);
+    static_assert(IsIntegral<UnwrapNumber<T>>);
     return {
         C(T{0}, T{0}, T{0}),
         C(T{1}, T{2}, T{3}),
@@ -3388,7 +3402,7 @@
 
 template <typename T>
 std::vector<Case> OpSubIntCases() {
-    static_assert(IsInteger<UnwrapNumber<T>>);
+    static_assert(IsIntegral<UnwrapNumber<T>>);
     return {
         C(T{0}, T{0}, T{0}),
         C(T{3}, T{2}, T{1}),
@@ -3510,6 +3524,64 @@
                                  OpMulMatCases<f32>(),
                                  OpMulMatCases<f16>()))));
 
+template <typename T>
+std::vector<Case> OpDivIntCases() {
+    std::vector<Case> r = {
+        C(Val(T{0}), Val(T{1}), Val(T{0})),
+        C(Val(T{1}), Val(T{1}), Val(T{1})),
+        C(Val(T{1}), Val(T{1}), Val(T{1})),
+        C(Val(T{2}), Val(T{1}), Val(T{2})),
+        C(Val(T{4}), Val(T{2}), Val(T{2})),
+        C(Val(T::Highest()), Val(T{1}), Val(T::Highest())),
+        C(Val(T::Lowest()), Val(T{1}), Val(T::Lowest())),
+        C(Val(T::Highest()), Val(T::Highest()), Val(T{1})),
+        C(Val(T{0}), Val(T::Highest()), Val(T{0})),
+        C(Val(T{0}), Val(T::Lowest()), Val(T{0})),
+    };
+    ConcatIntoIf<IsIntegral<T>>(  //
+        r, std::vector<Case>{
+               // e1, when e2 is zero.
+               C(T{123}, T{0}, T{123}, true),
+           });
+    ConcatIntoIf<IsSignedIntegral<T>>(  //
+        r, std::vector<Case>{
+               // e1, when e1 is the most negative value in T, and e2 is -1.
+               C(T::Smallest(), T{-1}, T::Smallest(), true),
+           });
+    return r;
+}
+
+template <typename T>
+std::vector<Case> OpDivFloatCases() {
+    return {
+        C(Val(T{0}), Val(T{1}), Val(T{0})),
+        C(Val(T{1}), Val(T{1}), Val(T{1})),
+        C(Val(T{1}), Val(T{1}), Val(T{1})),
+        C(Val(T{2}), Val(T{1}), Val(T{2})),
+        C(Val(T{4}), Val(T{2}), Val(T{2})),
+        C(Val(T::Highest()), Val(T{1}), Val(T::Highest())),
+        C(Val(T::Lowest()), Val(T{1}), Val(T::Lowest())),
+        C(Val(T::Highest()), Val(T::Highest()), Val(T{1})),
+        C(Val(T{0}), Val(T::Highest()), Val(T{0})),
+        C(Val(T{0}), Val(T::Lowest()), Val(-T{0})),
+        C(T{123}, T{0}, T::Inf(), true),
+        C(T{-123}, -T{0}, T::Inf(), true),
+        C(T{-123}, T{0}, -T::Inf(), true),
+        C(T{123}, -T{0}, -T::Inf(), true),
+    };
+}
+INSTANTIATE_TEST_SUITE_P(Div,
+                         ResolverConstEvalBinaryOpTest,
+                         testing::Combine(  //
+                             testing::Values(ast::BinaryOp::kDivide),
+                             testing::ValuesIn(Concat(  //
+                                 OpDivIntCases<AInt>(),
+                                 OpDivIntCases<i32>(),
+                                 OpDivIntCases<u32>(),
+                                 OpDivFloatCases<AFloat>(),
+                                 OpDivFloatCases<f32>(),
+                                 OpDivFloatCases<f16>()))));
+
 // Tests for errors on overflow/underflow of binary operations with abstract numbers
 struct OverflowCase {
     ast::BinaryOp op;
@@ -3618,7 +3690,16 @@
                      Mat({AFloat::Highest(), 1.0_a},   //
                          {AFloat::Highest(), 1.0_a}),  //
                      Mat({1.0_a, 1.0_a},               //
-                         {1.0_a, 1.0_a})}
+                         {1.0_a, 1.0_a})},
+
+        // Divide by zero
+        OverflowCase{ast::BinaryOp::kDivide, Val(123_a), Val(0_a)},
+        OverflowCase{ast::BinaryOp::kDivide, Val(-123_a), Val(-0_a)},
+        OverflowCase{ast::BinaryOp::kDivide, Val(-123_a), Val(0_a)},
+        OverflowCase{ast::BinaryOp::kDivide, Val(123_a), Val(-0_a)},
+
+        // Most negative value divided by -1
+        OverflowCase{ast::BinaryOp::kDivide, Val(AInt::Lowest()), Val(-1_a)}
 
         ));
 
@@ -3749,7 +3830,7 @@
                 EXPECT_EQ(c.result_pos_or_neg ? Abs(actual) : actual, result);
             }
 
-            if constexpr (IsInteger<UnwrapNumber<T>>) {
+            if constexpr (IsIntegral<UnwrapNumber<T>>) {
                 // Check that the constant's integer doesn't contain unexpected data in the MSBs
                 // that are outside of the bit-width of T.
                 EXPECT_EQ(value->As<AInt>(), AInt(result));
diff --git a/src/tint/resolver/intrinsic_table.inl b/src/tint/resolver/intrinsic_table.inl
index e0a8ddc..675aa41 100644
--- a/src/tint/resolver/intrinsic_table.inl
+++ b/src/tint/resolver/intrinsic_table.inl
@@ -11276,48 +11276,48 @@
     /* num parameters */ 2,
     /* num template types */ 1,
     /* num template numbers */ 0,
-    /* template types */ &kTemplateTypes[15],
+    /* template types */ &kTemplateTypes[13],
     /* template numbers */ &kTemplateNumbers[10],
     /* parameters */ &kParameters[709],
     /* return matcher indices */ &kMatcherIndices[1],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
-    /* const eval */ nullptr,
+    /* const eval */ &ConstEval::OpDivide,
   },
   {
     /* [260] */
     /* num parameters */ 2,
     /* num template types */ 1,
     /* num template numbers */ 1,
-    /* template types */ &kTemplateTypes[15],
+    /* template types */ &kTemplateTypes[13],
     /* template numbers */ &kTemplateNumbers[6],
     /* parameters */ &kParameters[707],
     /* return matcher indices */ &kMatcherIndices[30],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
-    /* const eval */ nullptr,
+    /* const eval */ &ConstEval::OpDivide,
   },
   {
     /* [261] */
     /* num parameters */ 2,
     /* num template types */ 1,
     /* num template numbers */ 1,
-    /* template types */ &kTemplateTypes[15],
+    /* template types */ &kTemplateTypes[13],
     /* template numbers */ &kTemplateNumbers[6],
     /* parameters */ &kParameters[705],
     /* return matcher indices */ &kMatcherIndices[30],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
-    /* const eval */ nullptr,
+    /* const eval */ &ConstEval::OpDivide,
   },
   {
     /* [262] */
     /* num parameters */ 2,
     /* num template types */ 1,
     /* num template numbers */ 1,
-    /* template types */ &kTemplateTypes[15],
+    /* template types */ &kTemplateTypes[13],
     /* template numbers */ &kTemplateNumbers[6],
     /* parameters */ &kParameters[781],
     /* return matcher indices */ &kMatcherIndices[30],
     /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
-    /* const eval */ nullptr,
+    /* const eval */ &ConstEval::OpDivide,
   },
   {
     /* [263] */
@@ -14644,10 +14644,10 @@
   },
   {
     /* [3] */
-    /* op /<T : fiu32_f16>(T, T) -> T */
-    /* op /<T : fiu32_f16, N : num>(vec<N, T>, vec<N, T>) -> vec<N, T> */
-    /* op /<T : fiu32_f16, N : num>(vec<N, T>, T) -> vec<N, T> */
-    /* op /<T : fiu32_f16, N : num>(T, vec<N, T>) -> vec<N, T> */
+    /* op /<T : fia_fiu32_f16>(T, T) -> T */
+    /* op /<T : fia_fiu32_f16, N : num>(vec<N, T>, vec<N, T>) -> vec<N, T> */
+    /* op /<T : fia_fiu32_f16, N : num>(vec<N, T>, T) -> vec<N, T> */
+    /* op /<T : fia_fiu32_f16, N : num>(T, vec<N, T>) -> vec<N, T> */
     /* num overloads */ 4,
     /* overloads */ &kOverloads[259],
   },
diff --git a/test/tint/bug/tint/1083.wgsl.expected.dxc.hlsl b/test/tint/bug/tint/1083.wgsl.expected.dxc.hlsl
index e793e0d..4035cda 100644
--- a/test/tint/bug/tint/1083.wgsl.expected.dxc.hlsl
+++ b/test/tint/bug/tint/1083.wgsl.expected.dxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const int c = (1 / 1);
+  const int c = 1;
   return;
 }
diff --git a/test/tint/bug/tint/1083.wgsl.expected.fxc.hlsl b/test/tint/bug/tint/1083.wgsl.expected.fxc.hlsl
index e793e0d..4035cda 100644
--- a/test/tint/bug/tint/1083.wgsl.expected.fxc.hlsl
+++ b/test/tint/bug/tint/1083.wgsl.expected.fxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const int c = (1 / 1);
+  const int c = 1;
   return;
 }
diff --git a/test/tint/bug/tint/1083.wgsl.expected.glsl b/test/tint/bug/tint/1083.wgsl.expected.glsl
index b8445d6..9daaea1 100644
--- a/test/tint/bug/tint/1083.wgsl.expected.glsl
+++ b/test/tint/bug/tint/1083.wgsl.expected.glsl
@@ -1,7 +1,7 @@
 #version 310 es
 
 void f() {
-  int c = (1 / 0);
+  int c = 1;
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/bug/tint/914.wgsl.expected.dxc.hlsl b/test/tint/bug/tint/914.wgsl.expected.dxc.hlsl
index ee10d6f..de30317 100644
--- a/test/tint/bug/tint/914.wgsl.expected.dxc.hlsl
+++ b/test/tint/bug/tint/914.wgsl.expected.dxc.hlsl
@@ -72,9 +72,9 @@
       acc[index] = 0.0f;
     }
   }
-  const uint ColPerThreadA = (64u / 16u);
+  const uint ColPerThreadA = 4u;
   const uint tileColA = (local_id.x * ColPerThreadA);
-  const uint RowPerThreadB = (64u / 16u);
+  const uint RowPerThreadB = 4u;
   const uint tileRowB = (local_id.y * RowPerThreadB);
   {
     [loop] for(uint t = 0u; (t < numTiles); t = (t + 1u)) {
diff --git a/test/tint/bug/tint/914.wgsl.expected.fxc.hlsl b/test/tint/bug/tint/914.wgsl.expected.fxc.hlsl
index ee10d6f..de30317 100644
--- a/test/tint/bug/tint/914.wgsl.expected.fxc.hlsl
+++ b/test/tint/bug/tint/914.wgsl.expected.fxc.hlsl
@@ -72,9 +72,9 @@
       acc[index] = 0.0f;
     }
   }
-  const uint ColPerThreadA = (64u / 16u);
+  const uint ColPerThreadA = 4u;
   const uint tileColA = (local_id.x * ColPerThreadA);
-  const uint RowPerThreadB = (64u / 16u);
+  const uint RowPerThreadB = 4u;
   const uint tileRowB = (local_id.y * RowPerThreadB);
   {
     [loop] for(uint t = 0u; (t < numTiles); t = (t + 1u)) {
diff --git a/test/tint/bug/tint/914.wgsl.expected.glsl b/test/tint/bug/tint/914.wgsl.expected.glsl
index 284ace8..25ef733 100644
--- a/test/tint/bug/tint/914.wgsl.expected.glsl
+++ b/test/tint/bug/tint/914.wgsl.expected.glsl
@@ -78,9 +78,9 @@
       acc[index] = 0.0f;
     }
   }
-  uint ColPerThreadA = (64u / 16u);
+  uint ColPerThreadA = 4u;
   uint tileColA = (local_id.x * ColPerThreadA);
-  uint RowPerThreadB = (64u / 16u);
+  uint RowPerThreadB = 4u;
   uint tileRowB = (local_id.y * RowPerThreadB);
   {
     for(uint t = 0u; (t < numTiles); t = (t + 1u)) {
diff --git a/test/tint/bug/tint/914.wgsl.expected.msl b/test/tint/bug/tint/914.wgsl.expected.msl
index 714fdf9..e1eaf8e 100644
--- a/test/tint/bug/tint/914.wgsl.expected.msl
+++ b/test/tint/bug/tint/914.wgsl.expected.msl
@@ -66,9 +66,9 @@
   for(uint index = 0u; (index < 16u); index = (index + 1u)) {
     acc[index] = 0.0f;
   }
-  uint const ColPerThreadA = (64u / 16u);
+  uint const ColPerThreadA = 4u;
   uint const tileColA = (local_id[0] * ColPerThreadA);
-  uint const RowPerThreadB = (64u / 16u);
+  uint const RowPerThreadB = 4u;
   uint const tileRowB = (local_id[1] * RowPerThreadB);
   for(uint t = 0u; (t < numTiles); t = (t + 1u)) {
     for(uint innerRow = 0u; (innerRow < 4u); innerRow = (innerRow + 1u)) {
diff --git a/test/tint/bug/tint/914.wgsl.expected.spvasm b/test/tint/bug/tint/914.wgsl.expected.spvasm
index 86e951e..daf3f3b 100644
--- a/test/tint/bug/tint/914.wgsl.expected.spvasm
+++ b/test/tint/bug/tint/914.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 373
+; Bound: 371
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
@@ -127,7 +127,7 @@
 %_arr_float_uint_4 = OpTypeArray %float %uint_4
 %_ptr_Function__arr_float_uint_4 = OpTypePointer Function %_arr_float_uint_4
         %152 = OpConstantNull %_arr_float_uint_4
-        %366 = OpTypeFunction %void
+        %364 = OpTypeFunction %void
    %mm_readA = OpFunction %float None %24
         %row = OpFunctionParameter %uint
         %col = OpFunctionParameter %uint
@@ -304,316 +304,314 @@
                OpStore %index %166
                OpBranch %154
         %155 = OpLabel
-        %167 = OpUDiv %uint %uint_64 %uint_16
-        %168 = OpCompositeExtract %uint %local_id 0
-        %169 = OpIMul %uint %168 %167
-        %170 = OpUDiv %uint %uint_64 %uint_16
-        %171 = OpCompositeExtract %uint %local_id 1
-        %172 = OpIMul %uint %171 %170
+        %167 = OpCompositeExtract %uint %local_id 0
+        %168 = OpIMul %uint %167 %uint_4
+        %169 = OpCompositeExtract %uint %local_id 1
+        %170 = OpIMul %uint %169 %uint_4
                OpStore %t %105
-               OpBranch %174
-        %174 = OpLabel
-               OpLoopMerge %175 %176 None
-               OpBranch %177
-        %177 = OpLabel
-        %179 = OpLoad %uint %t
-        %180 = OpULessThan %bool %179 %141
-        %178 = OpLogicalNot %bool %180
-               OpSelectionMerge %181 None
-               OpBranchConditional %178 %182 %181
-        %182 = OpLabel
+               OpBranch %172
+        %172 = OpLabel
+               OpLoopMerge %173 %174 None
                OpBranch %175
-        %181 = OpLabel
+        %175 = OpLabel
+        %177 = OpLoad %uint %t
+        %178 = OpULessThan %bool %177 %141
+        %176 = OpLogicalNot %bool %178
+               OpSelectionMerge %179 None
+               OpBranchConditional %176 %180 %179
+        %180 = OpLabel
+               OpBranch %173
+        %179 = OpLabel
                OpStore %innerRow %105
-               OpBranch %184
-        %184 = OpLabel
-               OpLoopMerge %185 %186 None
-               OpBranch %187
-        %187 = OpLabel
-        %189 = OpLoad %uint %innerRow
-        %190 = OpULessThan %bool %189 %uint_4
-        %188 = OpLogicalNot %bool %190
-               OpSelectionMerge %191 None
-               OpBranchConditional %188 %192 %191
-        %192 = OpLabel
+               OpBranch %182
+        %182 = OpLabel
+               OpLoopMerge %183 %184 None
                OpBranch %185
-        %191 = OpLabel
+        %185 = OpLabel
+        %187 = OpLoad %uint %innerRow
+        %188 = OpULessThan %bool %187 %uint_4
+        %186 = OpLogicalNot %bool %188
+               OpSelectionMerge %189 None
+               OpBranchConditional %186 %190 %189
+        %190 = OpLabel
+               OpBranch %183
+        %189 = OpLabel
                OpStore %innerCol %105
+               OpBranch %192
+        %192 = OpLabel
+               OpLoopMerge %193 %194 None
+               OpBranch %195
+        %195 = OpLabel
+        %197 = OpLoad %uint %innerCol
+        %198 = OpULessThan %bool %197 %uint_4
+        %196 = OpLogicalNot %bool %198
+               OpSelectionMerge %199 None
+               OpBranchConditional %196 %200 %199
+        %200 = OpLabel
+               OpBranch %193
+        %199 = OpLabel
+        %201 = OpLoad %uint %innerRow
+        %202 = OpIAdd %uint %130 %201
+        %203 = OpLoad %uint %innerCol
+        %204 = OpIAdd %uint %168 %203
+        %206 = OpLoad %uint %innerRow
+        %207 = OpIAdd %uint %134 %206
+        %208 = OpLoad %uint %t
+        %209 = OpIMul %uint %208 %uint_64
+        %210 = OpIAdd %uint %209 %204
+        %205 = OpFunctionCall %float %mm_readA %207 %210
+        %211 = OpAccessChain %_ptr_Workgroup_float %mm_Asub %202 %204
+               OpStore %211 %205
                OpBranch %194
         %194 = OpLabel
-               OpLoopMerge %195 %196 None
-               OpBranch %197
-        %197 = OpLabel
-        %199 = OpLoad %uint %innerCol
-        %200 = OpULessThan %bool %199 %167
-        %198 = OpLogicalNot %bool %200
-               OpSelectionMerge %201 None
-               OpBranchConditional %198 %202 %201
-        %202 = OpLabel
-               OpBranch %195
-        %201 = OpLabel
-        %203 = OpLoad %uint %innerRow
-        %204 = OpIAdd %uint %130 %203
-        %205 = OpLoad %uint %innerCol
-        %206 = OpIAdd %uint %169 %205
-        %208 = OpLoad %uint %innerRow
-        %209 = OpIAdd %uint %134 %208
-        %210 = OpLoad %uint %t
-        %211 = OpIMul %uint %210 %uint_64
-        %212 = OpIAdd %uint %211 %206
-        %207 = OpFunctionCall %float %mm_readA %209 %212
-        %213 = OpAccessChain %_ptr_Workgroup_float %mm_Asub %204 %206
-               OpStore %213 %207
-               OpBranch %196
-        %196 = OpLabel
-        %214 = OpLoad %uint %innerCol
-        %215 = OpIAdd %uint %214 %uint_1
-               OpStore %innerCol %215
-               OpBranch %194
-        %195 = OpLabel
-               OpBranch %186
-        %186 = OpLabel
-        %216 = OpLoad %uint %innerRow
-        %217 = OpIAdd %uint %216 %uint_1
-               OpStore %innerRow %217
+        %212 = OpLoad %uint %innerCol
+        %213 = OpIAdd %uint %212 %uint_1
+               OpStore %innerCol %213
+               OpBranch %192
+        %193 = OpLabel
                OpBranch %184
-        %185 = OpLabel
+        %184 = OpLabel
+        %214 = OpLoad %uint %innerRow
+        %215 = OpIAdd %uint %214 %uint_1
+               OpStore %innerRow %215
+               OpBranch %182
+        %183 = OpLabel
                OpStore %innerRow_0 %105
-               OpBranch %219
-        %219 = OpLabel
-               OpLoopMerge %220 %221 None
-               OpBranch %222
-        %222 = OpLabel
-        %224 = OpLoad %uint %innerRow_0
-        %225 = OpULessThan %bool %224 %170
-        %223 = OpLogicalNot %bool %225
-               OpSelectionMerge %226 None
-               OpBranchConditional %223 %227 %226
-        %227 = OpLabel
+               OpBranch %217
+        %217 = OpLabel
+               OpLoopMerge %218 %219 None
                OpBranch %220
-        %226 = OpLabel
+        %220 = OpLabel
+        %222 = OpLoad %uint %innerRow_0
+        %223 = OpULessThan %bool %222 %uint_4
+        %221 = OpLogicalNot %bool %223
+               OpSelectionMerge %224 None
+               OpBranchConditional %221 %225 %224
+        %225 = OpLabel
+               OpBranch %218
+        %224 = OpLabel
                OpStore %innerCol_0 %105
+               OpBranch %227
+        %227 = OpLabel
+               OpLoopMerge %228 %229 None
+               OpBranch %230
+        %230 = OpLabel
+        %232 = OpLoad %uint %innerCol_0
+        %233 = OpULessThan %bool %232 %uint_4
+        %231 = OpLogicalNot %bool %233
+               OpSelectionMerge %234 None
+               OpBranchConditional %231 %235 %234
+        %235 = OpLabel
+               OpBranch %228
+        %234 = OpLabel
+        %236 = OpLoad %uint %innerRow_0
+        %237 = OpIAdd %uint %170 %236
+        %238 = OpLoad %uint %innerCol_0
+        %239 = OpIAdd %uint %132 %238
+        %241 = OpLoad %uint %t
+        %242 = OpIMul %uint %241 %uint_64
+        %243 = OpIAdd %uint %242 %237
+        %244 = OpLoad %uint %innerCol_0
+        %245 = OpIAdd %uint %136 %244
+        %240 = OpFunctionCall %float %mm_readB %243 %245
+        %246 = OpLoad %uint %innerCol_0
+        %247 = OpAccessChain %_ptr_Workgroup_float %mm_Bsub %246 %239
+               OpStore %247 %240
                OpBranch %229
         %229 = OpLabel
-               OpLoopMerge %230 %231 None
-               OpBranch %232
-        %232 = OpLabel
-        %234 = OpLoad %uint %innerCol_0
-        %235 = OpULessThan %bool %234 %uint_4
-        %233 = OpLogicalNot %bool %235
-               OpSelectionMerge %236 None
-               OpBranchConditional %233 %237 %236
-        %237 = OpLabel
-               OpBranch %230
-        %236 = OpLabel
-        %238 = OpLoad %uint %innerRow_0
-        %239 = OpIAdd %uint %172 %238
-        %240 = OpLoad %uint %innerCol_0
-        %241 = OpIAdd %uint %132 %240
-        %243 = OpLoad %uint %t
-        %244 = OpIMul %uint %243 %uint_64
-        %245 = OpIAdd %uint %244 %239
-        %246 = OpLoad %uint %innerCol_0
-        %247 = OpIAdd %uint %136 %246
-        %242 = OpFunctionCall %float %mm_readB %245 %247
         %248 = OpLoad %uint %innerCol_0
-        %249 = OpAccessChain %_ptr_Workgroup_float %mm_Bsub %248 %241
-               OpStore %249 %242
-               OpBranch %231
-        %231 = OpLabel
-        %250 = OpLoad %uint %innerCol_0
-        %251 = OpIAdd %uint %250 %uint_1
-               OpStore %innerCol_0 %251
-               OpBranch %229
-        %230 = OpLabel
-               OpBranch %221
-        %221 = OpLabel
-        %252 = OpLoad %uint %innerRow_0
-        %253 = OpIAdd %uint %252 %uint_1
-               OpStore %innerRow_0 %253
+        %249 = OpIAdd %uint %248 %uint_1
+               OpStore %innerCol_0 %249
+               OpBranch %227
+        %228 = OpLabel
                OpBranch %219
-        %220 = OpLabel
+        %219 = OpLabel
+        %250 = OpLoad %uint %innerRow_0
+        %251 = OpIAdd %uint %250 %uint_1
+               OpStore %innerRow_0 %251
+               OpBranch %217
+        %218 = OpLabel
                OpControlBarrier %uint_2 %uint_2 %uint_264
                OpStore %k %105
-               OpBranch %256
-        %256 = OpLabel
-               OpLoopMerge %257 %258 None
-               OpBranch %259
-        %259 = OpLabel
-        %261 = OpLoad %uint %k
-        %262 = OpULessThan %bool %261 %uint_64
-        %260 = OpLogicalNot %bool %262
-               OpSelectionMerge %263 None
-               OpBranchConditional %260 %264 %263
-        %264 = OpLabel
+               OpBranch %254
+        %254 = OpLabel
+               OpLoopMerge %255 %256 None
                OpBranch %257
-        %263 = OpLabel
+        %257 = OpLabel
+        %259 = OpLoad %uint %k
+        %260 = OpULessThan %bool %259 %uint_64
+        %258 = OpLogicalNot %bool %260
+               OpSelectionMerge %261 None
+               OpBranchConditional %258 %262 %261
+        %262 = OpLabel
+               OpBranch %255
+        %261 = OpLabel
                OpStore %inner %105
+               OpBranch %264
+        %264 = OpLabel
+               OpLoopMerge %265 %266 None
+               OpBranch %267
+        %267 = OpLabel
+        %269 = OpLoad %uint %inner
+        %270 = OpULessThan %bool %269 %uint_4
+        %268 = OpLogicalNot %bool %270
+               OpSelectionMerge %271 None
+               OpBranchConditional %268 %272 %271
+        %272 = OpLabel
+               OpBranch %265
+        %271 = OpLabel
+        %273 = OpLoad %uint %inner
+        %274 = OpAccessChain %_ptr_Function_float %BCached %273
+        %275 = OpLoad %uint %k
+        %276 = OpLoad %uint %inner
+        %277 = OpIAdd %uint %132 %276
+        %278 = OpAccessChain %_ptr_Workgroup_float %mm_Bsub %275 %277
+        %279 = OpLoad %float %278
+               OpStore %274 %279
                OpBranch %266
         %266 = OpLabel
-               OpLoopMerge %267 %268 None
-               OpBranch %269
-        %269 = OpLabel
-        %271 = OpLoad %uint %inner
-        %272 = OpULessThan %bool %271 %uint_4
-        %270 = OpLogicalNot %bool %272
-               OpSelectionMerge %273 None
-               OpBranchConditional %270 %274 %273
-        %274 = OpLabel
-               OpBranch %267
-        %273 = OpLabel
-        %275 = OpLoad %uint %inner
-        %276 = OpAccessChain %_ptr_Function_float %BCached %275
-        %277 = OpLoad %uint %k
-        %278 = OpLoad %uint %inner
-        %279 = OpIAdd %uint %132 %278
-        %280 = OpAccessChain %_ptr_Workgroup_float %mm_Bsub %277 %279
-        %281 = OpLoad %float %280
-               OpStore %276 %281
-               OpBranch %268
-        %268 = OpLabel
-        %282 = OpLoad %uint %inner
-        %283 = OpIAdd %uint %282 %uint_1
-               OpStore %inner %283
-               OpBranch %266
-        %267 = OpLabel
+        %280 = OpLoad %uint %inner
+        %281 = OpIAdd %uint %280 %uint_1
+               OpStore %inner %281
+               OpBranch %264
+        %265 = OpLabel
                OpStore %innerRow_1 %105
-               OpBranch %285
-        %285 = OpLabel
-               OpLoopMerge %286 %287 None
-               OpBranch %288
-        %288 = OpLabel
-        %290 = OpLoad %uint %innerRow_1
-        %291 = OpULessThan %bool %290 %uint_4
-        %289 = OpLogicalNot %bool %291
-               OpSelectionMerge %292 None
-               OpBranchConditional %289 %293 %292
-        %293 = OpLabel
+               OpBranch %283
+        %283 = OpLabel
+               OpLoopMerge %284 %285 None
                OpBranch %286
-        %292 = OpLabel
-        %294 = OpLoad %uint %innerRow_1
-        %295 = OpIAdd %uint %130 %294
-        %296 = OpLoad %uint %k
-        %297 = OpAccessChain %_ptr_Workgroup_float %mm_Asub %295 %296
-        %298 = OpLoad %float %297
-               OpStore %ACached %298
+        %286 = OpLabel
+        %288 = OpLoad %uint %innerRow_1
+        %289 = OpULessThan %bool %288 %uint_4
+        %287 = OpLogicalNot %bool %289
+               OpSelectionMerge %290 None
+               OpBranchConditional %287 %291 %290
+        %291 = OpLabel
+               OpBranch %284
+        %290 = OpLabel
+        %292 = OpLoad %uint %innerRow_1
+        %293 = OpIAdd %uint %130 %292
+        %294 = OpLoad %uint %k
+        %295 = OpAccessChain %_ptr_Workgroup_float %mm_Asub %293 %294
+        %296 = OpLoad %float %295
+               OpStore %ACached %296
                OpStore %innerCol_1 %105
+               OpBranch %298
+        %298 = OpLabel
+               OpLoopMerge %299 %300 None
+               OpBranch %301
+        %301 = OpLabel
+        %303 = OpLoad %uint %innerCol_1
+        %304 = OpULessThan %bool %303 %uint_4
+        %302 = OpLogicalNot %bool %304
+               OpSelectionMerge %305 None
+               OpBranchConditional %302 %306 %305
+        %306 = OpLabel
+               OpBranch %299
+        %305 = OpLabel
+        %307 = OpLoad %uint %innerRow_1
+        %308 = OpIMul %uint %307 %uint_4
+        %309 = OpLoad %uint %innerCol_1
+        %310 = OpIAdd %uint %308 %309
+        %311 = OpAccessChain %_ptr_Function_float %acc %310
+        %312 = OpAccessChain %_ptr_Function_float %acc %310
+        %313 = OpLoad %float %312
+        %314 = OpLoad %float %ACached
+        %315 = OpLoad %uint %innerCol_1
+        %316 = OpAccessChain %_ptr_Function_float %BCached %315
+        %317 = OpLoad %float %316
+        %318 = OpFMul %float %314 %317
+        %319 = OpFAdd %float %313 %318
+               OpStore %311 %319
                OpBranch %300
         %300 = OpLabel
-               OpLoopMerge %301 %302 None
-               OpBranch %303
-        %303 = OpLabel
-        %305 = OpLoad %uint %innerCol_1
-        %306 = OpULessThan %bool %305 %uint_4
-        %304 = OpLogicalNot %bool %306
-               OpSelectionMerge %307 None
-               OpBranchConditional %304 %308 %307
-        %308 = OpLabel
-               OpBranch %301
-        %307 = OpLabel
-        %309 = OpLoad %uint %innerRow_1
-        %310 = OpIMul %uint %309 %uint_4
-        %311 = OpLoad %uint %innerCol_1
-        %312 = OpIAdd %uint %310 %311
-        %313 = OpAccessChain %_ptr_Function_float %acc %312
-        %314 = OpAccessChain %_ptr_Function_float %acc %312
-        %315 = OpLoad %float %314
-        %316 = OpLoad %float %ACached
-        %317 = OpLoad %uint %innerCol_1
-        %318 = OpAccessChain %_ptr_Function_float %BCached %317
-        %319 = OpLoad %float %318
-        %320 = OpFMul %float %316 %319
-        %321 = OpFAdd %float %315 %320
-               OpStore %313 %321
-               OpBranch %302
-        %302 = OpLabel
-        %322 = OpLoad %uint %innerCol_1
-        %323 = OpIAdd %uint %322 %uint_1
-               OpStore %innerCol_1 %323
-               OpBranch %300
-        %301 = OpLabel
-               OpBranch %287
-        %287 = OpLabel
-        %324 = OpLoad %uint %innerRow_1
-        %325 = OpIAdd %uint %324 %uint_1
-               OpStore %innerRow_1 %325
+        %320 = OpLoad %uint %innerCol_1
+        %321 = OpIAdd %uint %320 %uint_1
+               OpStore %innerCol_1 %321
+               OpBranch %298
+        %299 = OpLabel
                OpBranch %285
-        %286 = OpLabel
-               OpBranch %258
-        %258 = OpLabel
-        %326 = OpLoad %uint %k
-        %327 = OpIAdd %uint %326 %uint_1
-               OpStore %k %327
+        %285 = OpLabel
+        %322 = OpLoad %uint %innerRow_1
+        %323 = OpIAdd %uint %322 %uint_1
+               OpStore %innerRow_1 %323
+               OpBranch %283
+        %284 = OpLabel
                OpBranch %256
-        %257 = OpLabel
+        %256 = OpLabel
+        %324 = OpLoad %uint %k
+        %325 = OpIAdd %uint %324 %uint_1
+               OpStore %k %325
+               OpBranch %254
+        %255 = OpLabel
                OpControlBarrier %uint_2 %uint_2 %uint_264
-               OpBranch %176
-        %176 = OpLabel
-        %329 = OpLoad %uint %t
-        %330 = OpIAdd %uint %329 %uint_1
-               OpStore %t %330
                OpBranch %174
-        %175 = OpLabel
+        %174 = OpLabel
+        %327 = OpLoad %uint %t
+        %328 = OpIAdd %uint %327 %uint_1
+               OpStore %t %328
+               OpBranch %172
+        %173 = OpLabel
                OpStore %innerRow_2 %105
-               OpBranch %332
-        %332 = OpLabel
-               OpLoopMerge %333 %334 None
-               OpBranch %335
-        %335 = OpLabel
-        %337 = OpLoad %uint %innerRow_2
-        %338 = OpULessThan %bool %337 %uint_4
-        %336 = OpLogicalNot %bool %338
-               OpSelectionMerge %339 None
-               OpBranchConditional %336 %340 %339
-        %340 = OpLabel
+               OpBranch %330
+        %330 = OpLabel
+               OpLoopMerge %331 %332 None
                OpBranch %333
-        %339 = OpLabel
+        %333 = OpLabel
+        %335 = OpLoad %uint %innerRow_2
+        %336 = OpULessThan %bool %335 %uint_4
+        %334 = OpLogicalNot %bool %336
+               OpSelectionMerge %337 None
+               OpBranchConditional %334 %338 %337
+        %338 = OpLabel
+               OpBranch %331
+        %337 = OpLabel
                OpStore %innerCol_2 %105
+               OpBranch %340
+        %340 = OpLabel
+               OpLoopMerge %341 %342 None
+               OpBranch %343
+        %343 = OpLabel
+        %345 = OpLoad %uint %innerCol_2
+        %346 = OpULessThan %bool %345 %uint_4
+        %344 = OpLogicalNot %bool %346
+               OpSelectionMerge %347 None
+               OpBranchConditional %344 %348 %347
+        %348 = OpLabel
+               OpBranch %341
+        %347 = OpLabel
+        %349 = OpLoad %uint %innerRow_2
+        %350 = OpIMul %uint %349 %uint_4
+        %351 = OpLoad %uint %innerCol_2
+        %352 = OpIAdd %uint %350 %351
+        %354 = OpLoad %uint %innerRow_2
+        %355 = OpIAdd %uint %134 %354
+        %356 = OpLoad %uint %innerCol_2
+        %357 = OpIAdd %uint %136 %356
+        %358 = OpAccessChain %_ptr_Function_float %acc %352
+        %359 = OpLoad %float %358
+        %353 = OpFunctionCall %void %mm_write %355 %357 %359
                OpBranch %342
         %342 = OpLabel
-               OpLoopMerge %343 %344 None
-               OpBranch %345
-        %345 = OpLabel
-        %347 = OpLoad %uint %innerCol_2
-        %348 = OpULessThan %bool %347 %uint_4
-        %346 = OpLogicalNot %bool %348
-               OpSelectionMerge %349 None
-               OpBranchConditional %346 %350 %349
-        %350 = OpLabel
-               OpBranch %343
-        %349 = OpLabel
-        %351 = OpLoad %uint %innerRow_2
-        %352 = OpIMul %uint %351 %uint_4
-        %353 = OpLoad %uint %innerCol_2
-        %354 = OpIAdd %uint %352 %353
-        %356 = OpLoad %uint %innerRow_2
-        %357 = OpIAdd %uint %134 %356
-        %358 = OpLoad %uint %innerCol_2
-        %359 = OpIAdd %uint %136 %358
-        %360 = OpAccessChain %_ptr_Function_float %acc %354
-        %361 = OpLoad %float %360
-        %355 = OpFunctionCall %void %mm_write %357 %359 %361
-               OpBranch %344
-        %344 = OpLabel
-        %362 = OpLoad %uint %innerCol_2
-        %363 = OpIAdd %uint %362 %uint_1
-               OpStore %innerCol_2 %363
-               OpBranch %342
-        %343 = OpLabel
-               OpBranch %334
-        %334 = OpLabel
-        %364 = OpLoad %uint %innerRow_2
-        %365 = OpIAdd %uint %364 %uint_1
-               OpStore %innerRow_2 %365
+        %360 = OpLoad %uint %innerCol_2
+        %361 = OpIAdd %uint %360 %uint_1
+               OpStore %innerCol_2 %361
+               OpBranch %340
+        %341 = OpLabel
                OpBranch %332
-        %333 = OpLabel
+        %332 = OpLabel
+        %362 = OpLoad %uint %innerRow_2
+        %363 = OpIAdd %uint %362 %uint_1
+               OpStore %innerRow_2 %363
+               OpBranch %330
+        %331 = OpLabel
                OpReturn
                OpFunctionEnd
-       %main = OpFunction %void None %366
-        %368 = OpLabel
-        %370 = OpLoad %v3uint %local_id_1
-        %371 = OpLoad %v3uint %global_id_1
-        %372 = OpLoad %uint %local_invocation_index_1
-        %369 = OpFunctionCall %void %main_inner %370 %371 %372
+       %main = OpFunction %void None %364
+        %366 = OpLabel
+        %368 = OpLoad %v3uint %local_id_1
+        %369 = OpLoad %v3uint %global_id_1
+        %370 = OpLoad %uint %local_invocation_index_1
+        %367 = OpFunctionCall %void %main_inner %368 %369 %370
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/expressions/binary/div/scalar-scalar/f16.wgsl.expected.dxc.hlsl b/test/tint/expressions/binary/div/scalar-scalar/f16.wgsl.expected.dxc.hlsl
index 6d24970..bc9e347 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/f16.wgsl.expected.dxc.hlsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/f16.wgsl.expected.dxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const float16_t r = (float16_t(1.0h) / float16_t(2.0h));
+  const float16_t r = float16_t(0.5h);
   return;
 }
diff --git a/test/tint/expressions/binary/div/scalar-scalar/f16.wgsl.expected.glsl b/test/tint/expressions/binary/div/scalar-scalar/f16.wgsl.expected.glsl
index 19336bf..23604ba 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/f16.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/f16.wgsl.expected.glsl
@@ -2,7 +2,7 @@
 #extension GL_AMD_gpu_shader_half_float : require
 
 void f() {
-  float16_t r = (1.0hf / 2.0hf);
+  float16_t r = 0.5hf;
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.dxc.hlsl b/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.dxc.hlsl
index e9f00ff..3231de6 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.dxc.hlsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.dxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const float r = (1.0f / 2.0f);
+  const float r = 0.5f;
   return;
 }
diff --git a/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.fxc.hlsl b/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.fxc.hlsl
index e9f00ff..3231de6 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.fxc.hlsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.fxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const float r = (1.0f / 2.0f);
+  const float r = 0.5f;
   return;
 }
diff --git a/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.glsl b/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.glsl
index bd250c4..63663f6 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/f32.wgsl.expected.glsl
@@ -1,7 +1,7 @@
 #version 310 es
 
 void f() {
-  float r = (1.0f / 2.0f);
+  float r = 0.5f;
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.dxc.hlsl b/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.dxc.hlsl
index 8fe265a..06dda3a 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.dxc.hlsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.dxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const int r = (1 / 2);
+  const int r = 0;
   return;
 }
diff --git a/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.fxc.hlsl b/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.fxc.hlsl
index 8fe265a..06dda3a 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.fxc.hlsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.fxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const int r = (1 / 2);
+  const int r = 0;
   return;
 }
diff --git a/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.glsl b/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.glsl
index fdaa3f8..a12de41 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.glsl
@@ -1,7 +1,7 @@
 #version 310 es
 
 void f() {
-  int r = (1 / 2);
+  int r = 0;
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.dxc.hlsl b/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.dxc.hlsl
index f1d7c0c..263908a 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.dxc.hlsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.dxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const uint r = (1u / 2u);
+  const uint r = 0u;
   return;
 }
diff --git a/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.fxc.hlsl b/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.fxc.hlsl
index f1d7c0c..263908a 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.fxc.hlsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.fxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const uint r = (1u / 2u);
+  const uint r = 0u;
   return;
 }
diff --git a/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.glsl b/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.glsl
index 4facf8e..dece736 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/div/scalar-scalar/u32.wgsl.expected.glsl
@@ -1,7 +1,7 @@
 #version 310 es
 
 void f() {
-  uint r = (1u / 2u);
+  uint r = 0u;
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f16.wgsl.expected.dxc.hlsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f16.wgsl.expected.dxc.hlsl
index 82d70e4..f383c54 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f16.wgsl.expected.dxc.hlsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f16.wgsl.expected.dxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const float16_t r = (float16_t(1.0h) / float16_t(0.0h));
+  const float16_t r = float16_t(0.0h /* inf */);
   return;
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f16.wgsl.expected.glsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f16.wgsl.expected.glsl
index f2529d1..559b92b 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f16.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f16.wgsl.expected.glsl
@@ -2,7 +2,7 @@
 #extension GL_AMD_gpu_shader_half_float : require
 
 void f() {
-  float16_t r = (1.0hf / 0.0hf);
+  float16_t r = 0.0hf /* inf */;
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.dxc.hlsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.dxc.hlsl
index a06ee90..27bbecd 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.dxc.hlsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.dxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const float r = (1.0f / 0.0f);
+  const float r = 0.0f /* inf */;
   return;
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.fxc.hlsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.fxc.hlsl
index a06ee90..27bbecd 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.fxc.hlsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.fxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const float r = (1.0f / 0.0f);
+  const float r = 0.0f /* inf */;
   return;
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.glsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.glsl
index 7633cf6..7f869ee 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.glsl
@@ -1,7 +1,7 @@
 #version 310 es
 
 void f() {
-  float r = (1.0f / 0.0f);
+  float r = 0.0f /* inf */;
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.dxc.hlsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.dxc.hlsl
index 67f002e..15cea75 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.dxc.hlsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.dxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const int r = (1 / 1);
+  const int r = 1;
   return;
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.fxc.hlsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.fxc.hlsl
index 67f002e..15cea75 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.fxc.hlsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.fxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const int r = (1 / 1);
+  const int r = 1;
   return;
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.glsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.glsl
index 3904265..db428ec 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.glsl
@@ -1,7 +1,7 @@
 #version 310 es
 
 void f() {
-  int r = (1 / 0);
+  int r = 1;
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.dxc.hlsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.dxc.hlsl
index 60e18ed..01cbfa3 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.dxc.hlsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.dxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const uint r = (1u / 1u);
+  const uint r = 1u;
   return;
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.fxc.hlsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.fxc.hlsl
index 60e18ed..01cbfa3 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.fxc.hlsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.fxc.hlsl
@@ -1,5 +1,5 @@
 [numthreads(1, 1, 1)]
 void f() {
-  const uint r = (1u / 1u);
+  const uint r = 1u;
   return;
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.glsl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.glsl
index 586c708..9a9d0ad 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/u32.wgsl.expected.glsl
@@ -1,7 +1,7 @@
 #version 310 es
 
 void f() {
-  uint r = (1u / 0u);
+  uint r = 1u;
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/test/tint/samples/function.wgsl.expected.dxc.hlsl b/test/tint/samples/function.wgsl.expected.dxc.hlsl
index 7245500..8073117 100644
--- a/test/tint/samples/function.wgsl.expected.dxc.hlsl
+++ b/test/tint/samples/function.wgsl.expected.dxc.hlsl
@@ -1,5 +1,5 @@
 float main() {
-  return (2.0f / 5.0f);
+  return 0.400000006f;
 }
 
 [numthreads(2, 1, 1)]
diff --git a/test/tint/samples/function.wgsl.expected.fxc.hlsl b/test/tint/samples/function.wgsl.expected.fxc.hlsl
index 7245500..8073117 100644
--- a/test/tint/samples/function.wgsl.expected.fxc.hlsl
+++ b/test/tint/samples/function.wgsl.expected.fxc.hlsl
@@ -1,5 +1,5 @@
 float main() {
-  return (2.0f / 5.0f);
+  return 0.400000006f;
 }
 
 [numthreads(2, 1, 1)]
diff --git a/test/tint/samples/function.wgsl.expected.msl b/test/tint/samples/function.wgsl.expected.msl
index b0f4f9b..6c3ffad 100644
--- a/test/tint/samples/function.wgsl.expected.msl
+++ b/test/tint/samples/function.wgsl.expected.msl
@@ -2,7 +2,7 @@
 
 using namespace metal;
 float tint_symbol() {
-  return (2.0f / 5.0f);
+  return 0.400000006f;
 }
 
 kernel void ep() {
diff --git a/test/tint/samples/function.wgsl.expected.spvasm b/test/tint/samples/function.wgsl.expected.spvasm
index d6ef6f7..7dc2cc2 100644
--- a/test/tint/samples/function.wgsl.expected.spvasm
+++ b/test/tint/samples/function.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 12
+; Bound: 10
 ; Schema: 0
                OpCapability Shader
                OpMemoryModel Logical GLSL450
@@ -11,16 +11,14 @@
                OpName %ep "ep"
       %float = OpTypeFloat 32
           %1 = OpTypeFunction %float
-    %float_2 = OpConstant %float 2
-    %float_5 = OpConstant %float 5
+%float_0_400000006 = OpConstant %float 0.400000006
        %void = OpTypeVoid
-          %8 = OpTypeFunction %void
+          %6 = OpTypeFunction %void
        %main = OpFunction %float None %1
           %4 = OpLabel
-          %7 = OpFDiv %float %float_2 %float_5
-               OpReturnValue %7
+               OpReturnValue %float_0_400000006
                OpFunctionEnd
-         %ep = OpFunction %void None %8
-         %11 = OpLabel
+         %ep = OpFunction %void None %6
+          %9 = OpLabel
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-mod-zero/0-opt.wgsl b/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-mod-zero/0-opt.wgsl
index 3766aef..13c0255 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-mod-zero/0-opt.wgsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-mod-zero/0-opt.wgsl
@@ -30,7 +30,7 @@
   var undefined : f32;
   var x_51 : bool;
   var x_52_phi : bool;
-  undefined = (5.0 - (0.0 * floor((5.0 / 0.0))));
+  undefined = (5.0 - (0.0 * floor((5.0 / 0.0f))));
   let x_10 : i32 = x_6.x_GLF_uniform_int_values[0].el;
   let x_11 : i32 = x_6.x_GLF_uniform_int_values[0].el;
   let x_12 : i32 = x_6.x_GLF_uniform_int_values[1].el;