[msl] Fix logical boolean operators

MSL does not have boolean overloads for `&` and `|`, so it promotes
the operands to integers.  Make this explicit in the IR and then
convert the result of the instruction back to a boolean.

Bug: 42251016
Change-Id: I230b43624714daaa1e9f74c3cde38db642a6f90d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/198277
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Auto-Submit: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/msl/writer/raise/binary_polyfill.cc b/src/tint/lang/msl/writer/raise/binary_polyfill.cc
index 68f8b52..927b8da 100644
--- a/src/tint/lang/msl/writer/raise/binary_polyfill.cc
+++ b/src/tint/lang/msl/writer/raise/binary_polyfill.cc
@@ -51,19 +51,27 @@
     void Process() {
         // Find the binary operators that need replacing.
         Vector<core::ir::CoreBinary*, 4> fmod_worklist;
+        Vector<core::ir::CoreBinary*, 4> logical_bool_worklist;
         for (auto* inst : ir.Instructions()) {
             if (auto* binary = inst->As<core::ir::CoreBinary>()) {
                 if (binary->Op() == core::BinaryOp::kModulo &&
                     binary->LHS()->Type()->is_float_scalar_or_vector()) {
                     fmod_worklist.Push(binary);
+                } else if ((binary->Op() == core::BinaryOp::kAnd ||
+                            binary->Op() == core::BinaryOp::kOr) &&
+                           binary->LHS()->Type()->is_bool_scalar_or_vector()) {
+                    logical_bool_worklist.Push(binary);
                 }
             }
         }
 
-        // Replace the fmod instructions that we found.
+        // Replace the instructions that we found.
         for (auto* fmod : fmod_worklist) {
             FMod(fmod);
         }
+        for (auto* logical_bool : logical_bool_worklist) {
+            LogicalBool(logical_bool);
+        }
     }
 
     /// Replace a floating point modulo binary instruction with the equivalent MSL intrinsic.
@@ -74,6 +82,26 @@
         call->InsertBefore(binary);
         binary->Destroy();
     }
+
+    /// Replace a logical boolean binary instruction.
+    /// @param binary the logical boolean binary instruction
+    void LogicalBool(core::ir::CoreBinary* binary) {
+        // MSL does not have boolean overloads for `&` and `|`, so it promotes the operands to
+        // integers. Make this explicit in the IR and then convert the result of the binary
+        // instruction back to a boolean.
+        auto* result_ty = binary->Result(0)->Type();
+        const core::type::Type* int_ty = ty.u32();
+        if (auto* vec = result_ty->As<core::type::Vector>()) {
+            int_ty = ty.vec(int_ty, vec->Width());
+        }
+        b.InsertBefore(binary, [&] {
+            auto* int_lhs = b.Convert(int_ty, binary->LHS());
+            auto* int_rhs = b.Convert(int_ty, binary->RHS());
+            auto* int_binary = b.Binary(binary->Op(), int_ty, int_lhs, int_rhs);
+            b.ConvertWithResult(binary->DetachResult(), int_binary);
+        });
+        binary->Destroy();
+    }
 };
 
 }  // namespace
diff --git a/src/tint/lang/msl/writer/raise/binary_polyfill_test.cc b/src/tint/lang/msl/writer/raise/binary_polyfill_test.cc
index ec9b195..20ceaaf 100644
--- a/src/tint/lang/msl/writer/raise/binary_polyfill_test.cc
+++ b/src/tint/lang/msl/writer/raise/binary_polyfill_test.cc
@@ -110,5 +110,180 @@
     EXPECT_EQ(expect, str());
 }
 
+TEST_F(MslWriter_BinaryPolyfillTest, NoModify_I32And) {
+    auto* lhs = b.FunctionParam<i32>("lhs");
+    auto* rhs = b.FunctionParam<i32>("rhs");
+    auto* func = b.Function("foo", ty.i32());
+    func->SetParams({lhs, rhs});
+    b.Append(func->Block(), [&] {
+        auto* result = b.And<i32>(lhs, rhs);
+        b.Return(func, result);
+    });
+
+    auto* src = R"(
+%foo = func(%lhs:i32, %rhs:i32):i32 {
+  $B1: {
+    %4:i32 = and %lhs, %rhs
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = src;
+
+    Run(BinaryPolyfill);
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(MslWriter_BinaryPolyfillTest, BoolAnd_Scalar) {
+    auto* lhs = b.FunctionParam<bool>("lhs");
+    auto* rhs = b.FunctionParam<bool>("rhs");
+    auto* func = b.Function("foo", ty.bool_());
+    func->SetParams({lhs, rhs});
+    b.Append(func->Block(), [&] {
+        auto* result = b.And<bool>(lhs, rhs);
+        b.Return(func, result);
+    });
+
+    auto* src = R"(
+%foo = func(%lhs:bool, %rhs:bool):bool {
+  $B1: {
+    %4:bool = and %lhs, %rhs
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = func(%lhs:bool, %rhs:bool):bool {
+  $B1: {
+    %4:u32 = convert %lhs
+    %5:u32 = convert %rhs
+    %6:u32 = and %4, %5
+    %7:bool = convert %6
+    ret %7
+  }
+}
+)";
+
+    Run(BinaryPolyfill);
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(MslWriter_BinaryPolyfillTest, BoolAnd_Vector) {
+    auto* lhs = b.FunctionParam<vec4<bool>>("lhs");
+    auto* rhs = b.FunctionParam<vec4<bool>>("rhs");
+    auto* func = b.Function("foo", ty.vec4<bool>());
+    func->SetParams({lhs, rhs});
+    b.Append(func->Block(), [&] {
+        auto* result = b.And<vec4<bool>>(lhs, rhs);
+        b.Return(func, result);
+    });
+
+    auto* src = R"(
+%foo = func(%lhs:vec4<bool>, %rhs:vec4<bool>):vec4<bool> {
+  $B1: {
+    %4:vec4<bool> = and %lhs, %rhs
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = func(%lhs:vec4<bool>, %rhs:vec4<bool>):vec4<bool> {
+  $B1: {
+    %4:vec4<u32> = convert %lhs
+    %5:vec4<u32> = convert %rhs
+    %6:vec4<u32> = and %4, %5
+    %7:vec4<bool> = convert %6
+    ret %7
+  }
+}
+)";
+
+    Run(BinaryPolyfill);
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(MslWriter_BinaryPolyfillTest, BoolOr_Scalar) {
+    auto* lhs = b.FunctionParam<bool>("lhs");
+    auto* rhs = b.FunctionParam<bool>("rhs");
+    auto* func = b.Function("foo", ty.bool_());
+    func->SetParams({lhs, rhs});
+    b.Append(func->Block(), [&] {
+        auto* result = b.Or<bool>(lhs, rhs);
+        b.Return(func, result);
+    });
+
+    auto* src = R"(
+%foo = func(%lhs:bool, %rhs:bool):bool {
+  $B1: {
+    %4:bool = or %lhs, %rhs
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = func(%lhs:bool, %rhs:bool):bool {
+  $B1: {
+    %4:u32 = convert %lhs
+    %5:u32 = convert %rhs
+    %6:u32 = or %4, %5
+    %7:bool = convert %6
+    ret %7
+  }
+}
+)";
+
+    Run(BinaryPolyfill);
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(MslWriter_BinaryPolyfillTest, BoolOr_Vector) {
+    auto* lhs = b.FunctionParam<vec4<bool>>("lhs");
+    auto* rhs = b.FunctionParam<vec4<bool>>("rhs");
+    auto* func = b.Function("foo", ty.vec4<bool>());
+    func->SetParams({lhs, rhs});
+    b.Append(func->Block(), [&] {
+        auto* result = b.Or<vec4<bool>>(lhs, rhs);
+        b.Return(func, result);
+    });
+
+    auto* src = R"(
+%foo = func(%lhs:vec4<bool>, %rhs:vec4<bool>):vec4<bool> {
+  $B1: {
+    %4:vec4<bool> = or %lhs, %rhs
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = func(%lhs:vec4<bool>, %rhs:vec4<bool>):vec4<bool> {
+  $B1: {
+    %4:vec4<u32> = convert %lhs
+    %5:vec4<u32> = convert %rhs
+    %6:vec4<u32> = or %4, %5
+    %7:vec4<bool> = convert %6
+    ret %7
+  }
+}
+)";
+
+    Run(BinaryPolyfill);
+
+    EXPECT_EQ(expect, str());
+}
+
 }  // namespace
 }  // namespace tint::msl::writer::raise
diff --git a/test/tint/bug/tint/1083.wgsl.expected.ir.msl b/test/tint/bug/tint/1083.wgsl.expected.ir.msl
index b043b80..b449bf9 100644
--- a/test/tint/bug/tint/1083.wgsl.expected.ir.msl
+++ b/test/tint/bug/tint/1083.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int tint_div_i32(int lhs, int rhs) {
-  return (lhs / select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1)))));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  return (lhs / select(rhs, 1, bool((v_2 | uint(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/bug/tint/1520.spvasm.expected.ir.msl b/test/tint/bug/tint/1520.spvasm.expected.ir.msl
index 9056f6d..e8a7c2a 100644
--- a/test/tint/bug/tint/1520.spvasm.expected.ir.msl
+++ b/test/tint/bug/tint/1520.spvasm.expected.ir.msl
@@ -28,7 +28,10 @@
 };
 
 int4 tint_div_v4i32(int4 lhs, int4 rhs) {
-  return (lhs / select(rhs, int4(1), ((rhs == int4(0)) | ((lhs == int4((-2147483647 - 1))) & (rhs == int4(-1))))));
+  uint4 const v = uint4((lhs == int4((-2147483647 - 1))));
+  bool4 const v_1 = bool4((v & uint4((rhs == int4(-1)))));
+  uint4 const v_2 = uint4((rhs == int4(0)));
+  return (lhs / select(rhs, int4(1), bool4((v_2 | uint4(v_1)))));
 }
 
 int tint_f32_to_i32(float value) {
diff --git a/test/tint/bug/tint/1540.wgsl.expected.ir.msl b/test/tint/bug/tint/1540.wgsl.expected.ir.msl
index b650ca3..40e3690 100644
--- a/test/tint/bug/tint/1540.wgsl.expected.ir.msl
+++ b/test/tint/bug/tint/1540.wgsl.expected.ir.msl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 #include <metal_stdlib>
 using namespace metal;
 
@@ -9,16 +7,7 @@
 
 kernel void tint_symbol() {
   bool b = false;
-  S v = S{.e=(true & b)};
+  bool const v_1 = b;
+  uint const v_2 = uint(true);
+  S v = S{.e=bool((v_2 & uint(v_1)))};
 }
-program_source:10:14: error: non-constant-expression cannot be narrowed from type 'int' to 'bool' in initializer list [-Wc++11-narrowing]
-  S v = S{.e=(true & b)};
-             ^~~~~~~~~~
-program_source:10:14: note: insert an explicit cast to silence this issue
-  S v = S{.e=(true & b)};
-             ^~~~~~~~~~
-             static_cast<bool>( )
-program_source:10:5: warning: unused variable 'v' [-Wunused-variable]
-  S v = S{.e=(true & b)};
-    ^
-
diff --git a/test/tint/bug/tint/1541.wgsl.expected.ir.msl b/test/tint/bug/tint/1541.wgsl.expected.ir.msl
index 19fa371..e89d83a 100644
--- a/test/tint/bug/tint/1541.wgsl.expected.ir.msl
+++ b/test/tint/bug/tint/1541.wgsl.expected.ir.msl
@@ -1,19 +1,8 @@
-SKIP: FAILED
-
 #include <metal_stdlib>
 using namespace metal;
 
 kernel void tint_symbol() {
   bool const a = true;
-  bool v = select((a & true), true, false);
+  uint const v_1 = uint(a);
+  bool v = select(bool((v_1 & uint(true))), true, false);
 }
-program_source:6:12: error: call to 'select' is ambiguous
-  bool v = select((a & true), true, false);
-           ^~~~~~
-/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.194/include/metal/metal_relational:780:17: note: candidate function
-METAL_FUNC bool select(bool x, bool y, bool c)
-                ^
-/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.194/include/metal/metal_relational:920:16: note: candidate function
-METAL_FUNC int select(int x, int y, bool c)
-               ^
-
diff --git a/test/tint/expressions/binary/bit-and/scalar-scalar/bool.wgsl.expected.ir.msl b/test/tint/expressions/binary/bit-and/scalar-scalar/bool.wgsl.expected.ir.msl
index 0633302..e8c45f6 100644
--- a/test/tint/expressions/binary/bit-and/scalar-scalar/bool.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/bit-and/scalar-scalar/bool.wgsl.expected.ir.msl
@@ -4,5 +4,6 @@
 kernel void f() {
   bool const a = true;
   bool const b = false;
-  bool const r = (a & b);
+  uint const v = uint(a);
+  bool const r = bool((v & uint(b)));
 }
diff --git a/test/tint/expressions/binary/bit-and/vec3-vec3/bool.wgsl.expected.ir.msl b/test/tint/expressions/binary/bit-and/vec3-vec3/bool.wgsl.expected.ir.msl
index f616a02..9a2b3a7 100644
--- a/test/tint/expressions/binary/bit-and/vec3-vec3/bool.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/bit-and/vec3-vec3/bool.wgsl.expected.ir.msl
@@ -4,5 +4,6 @@
 kernel void f() {
   bool3 const a = bool3(true, true, false);
   bool3 const b = bool3(true, false, true);
-  bool3 const r = (a & b);
+  uint3 const v = uint3(a);
+  bool3 const r = bool3((v & uint3(b)));
 }
diff --git a/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.ir.msl
index 6694d60..0002eb9 100644
--- a/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div/scalar-scalar/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int tint_div_i32(int lhs, int rhs) {
-  return (lhs / select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1)))));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  return (lhs / select(rhs, 1, bool((v_2 | uint(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div/scalar-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div/scalar-vec3/i32.wgsl.expected.ir.msl
index ea681d1..c216e8b 100644
--- a/test/tint/expressions/binary/div/scalar-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div/scalar-vec3/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div/vec3-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div/vec3-scalar/i32.wgsl.expected.ir.msl
index ba58edf..d2e3300 100644
--- a/test/tint/expressions/binary/div/vec3-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div/vec3-scalar/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div/vec3-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div/vec3-vec3/i32.wgsl.expected.ir.msl
index 0fdfc84..2ac8ed7 100644
--- a/test/tint/expressions/binary/div/vec3-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div/vec3-vec3/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.ir.msl
index 88e8cc8..cdbbcae 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int tint_div_i32(int lhs, int rhs) {
-  return (lhs / select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1)))));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  return (lhs / select(rhs, 1, bool((v_2 | uint(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-vec3/i32.wgsl.expected.ir.msl
index d268a1f..4ca9053 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/scalar-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/scalar-vec3/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/vec3-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_constant/vec3-scalar/i32.wgsl.expected.ir.msl
index 0ff7604..8409633 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/vec3-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/vec3-scalar/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div_by_zero/by_constant/vec3-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_constant/vec3-vec3/i32.wgsl.expected.ir.msl
index 8869798..cee4293 100644
--- a/test/tint/expressions/binary/div_by_zero/by_constant/vec3-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_constant/vec3-vec3/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div_by_zero/by_expression/scalar-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_expression/scalar-scalar/i32.wgsl.expected.ir.msl
index 7cf5259..80bf690 100644
--- a/test/tint/expressions/binary/div_by_zero/by_expression/scalar-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_expression/scalar-scalar/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int tint_div_i32(int lhs, int rhs) {
-  return (lhs / select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1)))));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  return (lhs / select(rhs, 1, bool((v_2 | uint(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.ir.msl
index 49606de..07405f7 100644
--- a/test/tint/expressions/binary/div_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.ir.msl
@@ -2,12 +2,15 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
   int a = 4;
   int3 b = int3(0, 2, 0);
-  int3 const v = (b + b);
-  int3 const r = tint_div_v3i32(int3(a), v);
+  int3 const v_3 = (b + b);
+  int3 const r = tint_div_v3i32(int3(a), v_3);
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_expression/vec3-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_expression/vec3-scalar/i32.wgsl.expected.ir.msl
index 70e8271..875a9e2 100644
--- a/test/tint/expressions/binary/div_by_zero/by_expression/vec3-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_expression/vec3-scalar/i32.wgsl.expected.ir.msl
@@ -2,12 +2,15 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
   int3 a = int3(1, 2, 3);
   int b = 0;
-  int3 const v = a;
-  int3 const r = tint_div_v3i32(v, int3((b + b)));
+  int3 const v_3 = a;
+  int3 const r = tint_div_v3i32(v_3, int3((b + b)));
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.ir.msl
index bd289d6..c65386e 100644
--- a/test/tint/expressions/binary/div_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div_by_zero/by_identifier/scalar-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_identifier/scalar-scalar/i32.wgsl.expected.ir.msl
index c564e18..ad9aa06 100644
--- a/test/tint/expressions/binary/div_by_zero/by_identifier/scalar-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_identifier/scalar-scalar/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int tint_div_i32(int lhs, int rhs) {
-  return (lhs / select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1)))));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  return (lhs / select(rhs, 1, bool((v_2 | uint(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/div_by_zero/by_identifier/scalar-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_identifier/scalar-vec3/i32.wgsl.expected.ir.msl
index c47c48a..6fe1cd0 100644
--- a/test/tint/expressions/binary/div_by_zero/by_identifier/scalar-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_identifier/scalar-vec3/i32.wgsl.expected.ir.msl
@@ -2,12 +2,15 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
   int a = 4;
   int3 b = int3(0, 2, 0);
-  int3 const v = b;
-  int3 const r = tint_div_v3i32(int3(a), v);
+  int3 const v_3 = b;
+  int3 const r = tint_div_v3i32(int3(a), v_3);
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_identifier/vec3-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_identifier/vec3-scalar/i32.wgsl.expected.ir.msl
index 696657c..4ee604a 100644
--- a/test/tint/expressions/binary/div_by_zero/by_identifier/vec3-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_identifier/vec3-scalar/i32.wgsl.expected.ir.msl
@@ -2,12 +2,15 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
   int3 a = int3(1, 2, 3);
   int b = 0;
-  int3 const v = a;
-  int3 const r = tint_div_v3i32(v, int3(b));
+  int3 const v_3 = a;
+  int3 const r = tint_div_v3i32(v_3, int3(b));
 }
diff --git a/test/tint/expressions/binary/div_by_zero/by_identifier/vec3-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/div_by_zero/by_identifier/vec3-vec3/i32.wgsl.expected.ir.msl
index 8668457..f1a1e43 100644
--- a/test/tint/expressions/binary/div_by_zero/by_identifier/vec3-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_identifier/vec3-vec3/i32.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int3 tint_div_v3i32(int3 lhs, int3 rhs) {
-  return (lhs / select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1))))));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  return (lhs / select(rhs, int3(1), bool3((v_2 | uint3(v_1)))));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod/scalar-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod/scalar-scalar/i32.wgsl.expected.ir.msl
index f40f5db..d11d161 100644
--- a/test/tint/expressions/binary/mod/scalar-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod/scalar-scalar/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int tint_mod_i32(int lhs, int rhs) {
-  int const v = select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1))));
-  return (lhs - ((lhs / v) * v));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  int const v_3 = select(rhs, 1, bool((v_2 | uint(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod/scalar-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod/scalar-vec3/i32.wgsl.expected.ir.msl
index d55a3fc..4eb5587 100644
--- a/test/tint/expressions/binary/mod/scalar-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod/scalar-vec3/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod/vec3-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod/vec3-scalar/i32.wgsl.expected.ir.msl
index 52f4c4c..aaa74db 100644
--- a/test/tint/expressions/binary/mod/vec3-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod/vec3-scalar/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod/vec3-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod/vec3-vec3/i32.wgsl.expected.ir.msl
index 6e4071f..453a6ae 100644
--- a/test/tint/expressions/binary/mod/vec3-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod/vec3-vec3/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.ir.msl
index cb96a71..2efc410 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-scalar/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int tint_mod_i32(int lhs, int rhs) {
-  int const v = select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1))));
-  return (lhs - ((lhs / v) * v));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  int const v_3 = select(rhs, 1, bool((v_2 | uint(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-vec3/i32.wgsl.expected.ir.msl
index 9d26041..48ea2d3 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-vec3/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-scalar/i32.wgsl.expected.ir.msl
index 0f4b281..7c73d60 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-scalar/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-vec3/i32.wgsl.expected.ir.msl
index dbd4616..4899742 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-vec3/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-scalar/i32.wgsl.expected.ir.msl
index 4112d2b..11f2288 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-scalar/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int tint_mod_i32(int lhs, int rhs) {
-  int const v = select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1))));
-  return (lhs - ((lhs / v) * v));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  int const v_3 = select(rhs, 1, bool((v_2 | uint(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.ir.msl
index a1b4e4f..0f9428d 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.ir.msl
@@ -2,13 +2,16 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
   int a = 4;
   int3 b = int3(0, 2, 0);
-  int3 const v_1 = (b + b);
-  int3 const r = tint_mod_v3i32(int3(a), v_1);
+  int3 const v_4 = (b + b);
+  int3 const r = tint_mod_v3i32(int3(a), v_4);
 }
diff --git a/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-scalar/i32.wgsl.expected.ir.msl
index a745133..5fb0c50 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-scalar/i32.wgsl.expected.ir.msl
@@ -2,13 +2,16 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
   int3 a = int3(1, 2, 3);
   int b = 0;
-  int3 const v_1 = a;
-  int3 const r = tint_mod_v3i32(v_1, int3((b + b)));
+  int3 const v_4 = a;
+  int3 const r = tint_mod_v3i32(v_4, int3((b + b)));
 }
diff --git a/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.ir.msl
index 5cde32d..d989a1b 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-scalar/i32.wgsl.expected.ir.msl
index c8d3d96..a655b85 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-scalar/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int tint_mod_i32(int lhs, int rhs) {
-  int const v = select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1))));
-  return (lhs - ((lhs / v) * v));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  int const v_3 = select(rhs, 1, bool((v_2 | uint(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-vec3/i32.wgsl.expected.ir.msl
index 46d77b7..c17dd02 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-vec3/i32.wgsl.expected.ir.msl
@@ -2,13 +2,16 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
   int a = 4;
   int3 b = int3(0, 2, 0);
-  int3 const v_1 = b;
-  int3 const r = tint_mod_v3i32(int3(a), v_1);
+  int3 const v_4 = b;
+  int3 const r = tint_mod_v3i32(int3(a), v_4);
 }
diff --git a/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-scalar/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-scalar/i32.wgsl.expected.ir.msl
index 73bdc47..c3291c2 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-scalar/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-scalar/i32.wgsl.expected.ir.msl
@@ -2,13 +2,16 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
   int3 a = int3(1, 2, 3);
   int b = 0;
-  int3 const v_1 = a;
-  int3 const r = tint_mod_v3i32(v_1, int3(b));
+  int3 const v_4 = a;
+  int3 const r = tint_mod_v3i32(v_4, int3(b));
 }
diff --git a/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-vec3/i32.wgsl.expected.ir.msl b/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-vec3/i32.wgsl.expected.ir.msl
index 9572df9..f36c4fa 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-vec3/i32.wgsl.expected.ir.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-vec3/i32.wgsl.expected.ir.msl
@@ -2,8 +2,11 @@
 using namespace metal;
 
 int3 tint_mod_v3i32(int3 lhs, int3 rhs) {
-  int3 const v = select(rhs, int3(1), ((rhs == int3(0)) | ((lhs == int3((-2147483647 - 1))) & (rhs == int3(-1)))));
-  return (lhs - ((lhs / v) * v));
+  uint3 const v = uint3((lhs == int3((-2147483647 - 1))));
+  bool3 const v_1 = bool3((v & uint3((rhs == int3(-1)))));
+  uint3 const v_2 = uint3((rhs == int3(0)));
+  int3 const v_3 = select(rhs, int3(1), bool3((v_2 | uint3(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 kernel void f() {
diff --git a/test/tint/statements/compound_assign/divide_by_zero.wgsl.expected.ir.msl b/test/tint/statements/compound_assign/divide_by_zero.wgsl.expected.ir.msl
index 8494843..7ebf422 100644
--- a/test/tint/statements/compound_assign/divide_by_zero.wgsl.expected.ir.msl
+++ b/test/tint/statements/compound_assign/divide_by_zero.wgsl.expected.ir.msl
@@ -7,12 +7,18 @@
 };
 
 int tint_mod_i32(int lhs, int rhs) {
-  int const v = select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1))));
-  return (lhs - ((lhs / v) * v));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  int const v_3 = select(rhs, 1, bool((v_2 | uint(v_1))));
+  return (lhs - ((lhs / v_3) * v_3));
 }
 
 int tint_div_i32(int lhs, int rhs) {
-  return (lhs / select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1)))));
+  uint const v_4 = uint((lhs == (-2147483647 - 1)));
+  bool const v_5 = bool((v_4 & uint((rhs == -1))));
+  uint const v_6 = uint((rhs == 0));
+  return (lhs / select(rhs, 1, bool((v_6 | uint(v_5)))));
 }
 
 void foo(int maybe_zero, tint_module_vars_struct tint_module_vars) {
@@ -22,8 +28,8 @@
   (*tint_module_vars.a) = tint_mod_i32((*tint_module_vars.a), maybe_zero);
   (*tint_module_vars.b) = ((*tint_module_vars.b) / 0.0f);
   (*tint_module_vars.b) = fmod((*tint_module_vars.b), 0.0f);
-  float const v_1 = float(maybe_zero);
-  (*tint_module_vars.b) = ((*tint_module_vars.b) / v_1);
-  float const v_2 = float(maybe_zero);
-  (*tint_module_vars.b) = fmod((*tint_module_vars.b), v_2);
+  float const v_7 = float(maybe_zero);
+  (*tint_module_vars.b) = ((*tint_module_vars.b) / v_7);
+  float const v_8 = float(maybe_zero);
+  (*tint_module_vars.b) = fmod((*tint_module_vars.b), v_8);
 }
diff --git a/test/tint/statements/compound_assign/function.wgsl.expected.ir.msl b/test/tint/statements/compound_assign/function.wgsl.expected.ir.msl
index 69b373f..cde6fb1 100644
--- a/test/tint/statements/compound_assign/function.wgsl.expected.ir.msl
+++ b/test/tint/statements/compound_assign/function.wgsl.expected.ir.msl
@@ -2,7 +2,10 @@
 using namespace metal;
 
 int tint_div_i32(int lhs, int rhs) {
-  return (lhs / select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1)))));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  return (lhs / select(rhs, 1, bool((v_2 | uint(v_1)))));
 }
 
 void foo() {
diff --git a/test/tint/statements/compound_assign/private.wgsl.expected.ir.msl b/test/tint/statements/compound_assign/private.wgsl.expected.ir.msl
index d15e159..6744173 100644
--- a/test/tint/statements/compound_assign/private.wgsl.expected.ir.msl
+++ b/test/tint/statements/compound_assign/private.wgsl.expected.ir.msl
@@ -8,7 +8,10 @@
 };
 
 int tint_div_i32(int lhs, int rhs) {
-  return (lhs / select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1)))));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  return (lhs / select(rhs, 1, bool((v_2 | uint(v_1)))));
 }
 
 void foo(tint_module_vars_struct tint_module_vars) {
diff --git a/test/tint/statements/compound_assign/scalar/divide.wgsl.expected.ir.msl b/test/tint/statements/compound_assign/scalar/divide.wgsl.expected.ir.msl
index b9f0ed4..aa63360 100644
--- a/test/tint/statements/compound_assign/scalar/divide.wgsl.expected.ir.msl
+++ b/test/tint/statements/compound_assign/scalar/divide.wgsl.expected.ir.msl
@@ -10,7 +10,10 @@
 };
 
 int tint_div_i32(int lhs, int rhs) {
-  return (lhs / select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1)))));
+  uint const v_1 = uint((lhs == (-2147483647 - 1)));
+  bool const v_2 = bool((v_1 & uint((rhs == -1))));
+  uint const v_3 = uint((rhs == 0));
+  return (lhs / select(rhs, 1, bool((v_3 | uint(v_2)))));
 }
 
 void foo(tint_module_vars_struct tint_module_vars) {
diff --git a/test/tint/statements/compound_assign/scalar/modulo.wgsl.expected.ir.msl b/test/tint/statements/compound_assign/scalar/modulo.wgsl.expected.ir.msl
index 0576628..13c96b9 100644
--- a/test/tint/statements/compound_assign/scalar/modulo.wgsl.expected.ir.msl
+++ b/test/tint/statements/compound_assign/scalar/modulo.wgsl.expected.ir.msl
@@ -10,8 +10,11 @@
 };
 
 int tint_mod_i32(int lhs, int rhs) {
-  int const v_1 = select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1))));
-  return (lhs - ((lhs / v_1) * v_1));
+  uint const v_1 = uint((lhs == (-2147483647 - 1)));
+  bool const v_2 = bool((v_1 & uint((rhs == -1))));
+  uint const v_3 = uint((rhs == 0));
+  int const v_4 = select(rhs, 1, bool((v_3 | uint(v_2))));
+  return (lhs - ((lhs / v_4) * v_4));
 }
 
 void foo(tint_module_vars_struct tint_module_vars) {
diff --git a/test/tint/statements/compound_assign/vector/divide.wgsl.expected.ir.msl b/test/tint/statements/compound_assign/vector/divide.wgsl.expected.ir.msl
index 6c0f937..c96abe7 100644
--- a/test/tint/statements/compound_assign/vector/divide.wgsl.expected.ir.msl
+++ b/test/tint/statements/compound_assign/vector/divide.wgsl.expected.ir.msl
@@ -10,7 +10,10 @@
 };
 
 int4 tint_div_v4i32(int4 lhs, int4 rhs) {
-  return (lhs / select(rhs, int4(1), ((rhs == int4(0)) | ((lhs == int4((-2147483647 - 1))) & (rhs == int4(-1))))));
+  uint4 const v_1 = uint4((lhs == int4((-2147483647 - 1))));
+  bool4 const v_2 = bool4((v_1 & uint4((rhs == int4(-1)))));
+  uint4 const v_3 = uint4((rhs == int4(0)));
+  return (lhs / select(rhs, int4(1), bool4((v_3 | uint4(v_2)))));
 }
 
 void foo(tint_module_vars_struct tint_module_vars) {
diff --git a/test/tint/statements/compound_assign/vector/modulo-scalar.wgsl.expected.ir.msl b/test/tint/statements/compound_assign/vector/modulo-scalar.wgsl.expected.ir.msl
index a2d4ce4..095716d 100644
--- a/test/tint/statements/compound_assign/vector/modulo-scalar.wgsl.expected.ir.msl
+++ b/test/tint/statements/compound_assign/vector/modulo-scalar.wgsl.expected.ir.msl
@@ -10,11 +10,14 @@
 };
 
 int4 tint_mod_v4i32(int4 lhs, int4 rhs) {
-  int4 const v_1 = select(rhs, int4(1), ((rhs == int4(0)) | ((lhs == int4((-2147483647 - 1))) & (rhs == int4(-1)))));
-  return (lhs - ((lhs / v_1) * v_1));
+  uint4 const v_1 = uint4((lhs == int4((-2147483647 - 1))));
+  bool4 const v_2 = bool4((v_1 & uint4((rhs == int4(-1)))));
+  uint4 const v_3 = uint4((rhs == int4(0)));
+  int4 const v_4 = select(rhs, int4(1), bool4((v_3 | uint4(v_2))));
+  return (lhs - ((lhs / v_4) * v_4));
 }
 
 void foo(tint_module_vars_struct tint_module_vars) {
-  int4 const v_2 = (*tint_module_vars.v).a;
-  (*tint_module_vars.v).a = tint_mod_v4i32(v_2, int4(2));
+  int4 const v_5 = (*tint_module_vars.v).a;
+  (*tint_module_vars.v).a = tint_mod_v4i32(v_5, int4(2));
 }
diff --git a/test/tint/statements/compound_assign/vector/modulo.wgsl.expected.ir.msl b/test/tint/statements/compound_assign/vector/modulo.wgsl.expected.ir.msl
index 4b2ae5b..3783e0f 100644
--- a/test/tint/statements/compound_assign/vector/modulo.wgsl.expected.ir.msl
+++ b/test/tint/statements/compound_assign/vector/modulo.wgsl.expected.ir.msl
@@ -10,8 +10,11 @@
 };
 
 int4 tint_mod_v4i32(int4 lhs, int4 rhs) {
-  int4 const v_1 = select(rhs, int4(1), ((rhs == int4(0)) | ((lhs == int4((-2147483647 - 1))) & (rhs == int4(-1)))));
-  return (lhs - ((lhs / v_1) * v_1));
+  uint4 const v_1 = uint4((lhs == int4((-2147483647 - 1))));
+  bool4 const v_2 = bool4((v_1 & uint4((rhs == int4(-1)))));
+  uint4 const v_3 = uint4((rhs == int4(0)));
+  int4 const v_4 = select(rhs, int4(1), bool4((v_3 | uint4(v_2))));
+  return (lhs - ((lhs / v_4) * v_4));
 }
 
 void foo(tint_module_vars_struct tint_module_vars) {
diff --git a/test/tint/statements/compound_assign/workgroup.wgsl.expected.ir.msl b/test/tint/statements/compound_assign/workgroup.wgsl.expected.ir.msl
index 03c8198..78d4246 100644
--- a/test/tint/statements/compound_assign/workgroup.wgsl.expected.ir.msl
+++ b/test/tint/statements/compound_assign/workgroup.wgsl.expected.ir.msl
@@ -8,7 +8,10 @@
 };
 
 int tint_div_i32(int lhs, int rhs) {
-  return (lhs / select(rhs, 1, ((rhs == 0) | ((lhs == (-2147483647 - 1)) & (rhs == -1)))));
+  uint const v = uint((lhs == (-2147483647 - 1)));
+  bool const v_1 = bool((v & uint((rhs == -1))));
+  uint const v_2 = uint((rhs == 0));
+  return (lhs / select(rhs, 1, bool((v_2 | uint(v_1)))));
 }
 
 void foo(tint_module_vars_struct tint_module_vars) {