[tint][msl][ir] Use ValueToLet IR transform

Change-Id: I325375fcc496789acc24a3d168afbcad0b0ffe56
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/162700
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/msl/writer/printer/binary_test.cc b/src/tint/lang/msl/writer/printer/binary_test.cc
index acc59b1..74808bf 100644
--- a/src/tint/lang/msl/writer/printer/binary_test.cc
+++ b/src/tint/lang/msl/writer/printer/binary_test.cc
@@ -121,7 +121,8 @@
   uint const val = tint_mod_u32(left, right);
 }
 uint tint_mod_u32(uint lhs, uint rhs) {
-  return (lhs - ((lhs / select(rhs, 1u, (rhs == 0u))) * select(rhs, 1u, (rhs == 0u))));
+  uint const v = select(rhs, 1u, (rhs == 0u));
+  return (lhs - ((lhs / v) * v));
 }
 )");
 }
diff --git a/src/tint/lang/msl/writer/printer/printer.cc b/src/tint/lang/msl/writer/printer/printer.cc
index 29ccd88..2ededba 100644
--- a/src/tint/lang/msl/writer/printer/printer.cc
+++ b/src/tint/lang/msl/writer/printer/printer.cc
@@ -41,6 +41,7 @@
 #include "src/tint/lang/core/ir/constant.h"
 #include "src/tint/lang/core/ir/construct.h"
 #include "src/tint/lang/core/ir/continue.h"
+#include "src/tint/lang/core/ir/convert.h"
 #include "src/tint/lang/core/ir/core_builtin_call.h"
 #include "src/tint/lang/core/ir/discard.h"
 #include "src/tint/lang/core/ir/exit_if.h"
@@ -133,6 +134,9 @@
 
     core::ir::Module& ir_;
 
+    /// A hashmap of value to name
+    Hashmap<const core::ir::Value*, std::string, 32> names_;
+
     /// The buffer holding preamble text
     TextBuffer preamble_buffer_;
 
@@ -240,7 +244,7 @@
             // TODO(dsinclair): Handle return type attributes
 
             EmitType(out, func->ReturnType());
-            out << " " << ir_.NameOf(func).Name() << "(";
+            out << " " << NameOf(func) << "(";
 
             size_t i = 0;
             for (auto* param : func->Params()) {
@@ -259,7 +263,7 @@
                     out << "const ";
                 }
 
-                EmitFunctionParam(out, param);
+                out << NameOf(param);
 
                 if (param->Builtin().has_value()) {
                     out << " [[";
@@ -320,86 +324,52 @@
 
         for (auto* inst : *block) {
             Switch(
-                inst,                                                                 //
-                [&](core::ir::ExitIf* e) { EmitExitIf(e); },                          //
-                [&](core::ir::If* if_) { EmitIf(if_); },                              //
-                [&](core::ir::Loop* l) { EmitLoop(l); },                              //
-                [&](core::ir::Return* r) { EmitReturn(r); },                          //
-                [&](core::ir::Unreachable*) { EmitUnreachable(); },                   //
-                [&](core::ir::Var* v) { EmitVar(v); },                                //
-                [&](core::ir::TerminateInvocation*) { EmitDiscard(); },               //
-                [&](core::ir::Store* s) { EmitStore(s); },                            //
-                [&](core::ir::Continue*) { EmitContinue(); },                         //
-                [&](core::ir::NextIteration*) { /* do nothing */ },                   //
-                [&](core::ir::BreakIf* b) { EmitBreakIf(b); },                        //
-                [&](core::ir::ExitLoop*) { EmitExitLoop(); },                         //
-                [&](core::ir::ExitSwitch*) { EmitExitSwitch(); },                     //
-                [&](core::ir::Switch* s) { EmitSwitch(s); },                          //
-                                                                                      //
-                [&](core::ir::LoadVectorElement* e) { MaybeEmitInstruction(e); },     //
-                [&](core::ir::StoreVectorElement* e) { EmitStoreVectorElement(e); },  //
-                [&](core::ir::Swizzle* s) { MaybeEmitInstruction(s); },               //
-                [&](core::ir::Bitcast*) { MaybeEmitInstruction(inst); },              //
-                [&](core::ir::Unary*) { MaybeEmitInstruction(inst); },                //
-                [&](core::ir::Binary*) { MaybeEmitInstruction(inst); },               //
-                [&](core::ir::Let* l) { EmitLet(l); },                                //
-                [&](core::ir::Load*) { MaybeEmitInstruction(inst); },                 //
-                [&](core::ir::Construct*) { MaybeEmitInstruction(inst); },            //
-                [&](core::ir::Access*) { MaybeEmitInstruction(inst); },               //
-                [&](core::ir::CoreBuiltinCall* c) {
-                    if (c->Result(0)->Type()->Is<core::type::Void>()) {
-                        auto out = Line();
-                        EmitValue(out, c->Result(0));
-                        out << ";";
-                    } else {
-                        MaybeEmitInstruction(inst);
-                    }
-                },                            //
-                [&](core::ir::UserCall* c) {  //
-                    if (c->Result(0)->Type()->Is<core::type::Void>()) {
-                        auto out = Line();
-                        EmitValue(out, c->Result(0));
-                        out << ";";
-                    } else {
-                        MaybeEmitInstruction(inst);
-                    }
-                },  //
+                inst,                                                //
+                [&](core::ir::BreakIf* i) { EmitBreakIf(i); },       //
+                [&](core::ir::Continue*) { EmitContinue(); },        //
+                [&](core::ir::Discard*) { EmitDiscard(); },          //
+                [&](core::ir::ExitIf* i) { EmitExitIf(i); },         //
+                [&](core::ir::ExitLoop*) { EmitExitLoop(); },        //
+                [&](core::ir::ExitSwitch*) { EmitExitSwitch(); },    //
+                [&](core::ir::If* i) { EmitIf(i); },                 //
+                [&](core::ir::Let* i) { EmitLet(i); },               //
+                [&](core::ir::Loop* i) { EmitLoop(i); },             //
+                [&](core::ir::NextIteration*) { /* do nothing */ },  //
+                [&](core::ir::Return* i) { EmitReturn(i); },         //
+                [&](core::ir::Store* i) { EmitStore(i); },           //
+                [&](core::ir::Switch* i) { EmitSwitch(i); },         //
+                [&](core::ir::Unreachable*) { EmitUnreachable(); },  //
+                [&](core::ir::Call* i) { EmitCallStmt(i); },         //
+                [&](core::ir::Var* i) { EmitVar(i); },               //
+                [&](core::ir::StoreVectorElement* e) { EmitStoreVectorElement(e); },
+                [&](core::ir::TerminateInvocation*) { EmitDiscard(); },  //
+
+                [&](core::ir::LoadVectorElement*) { /* inlined */ },  //
+                [&](core::ir::Swizzle*) { /* inlined */ },            //
+                [&](core::ir::Bitcast*) { /* inlined */ },            //
+                [&](core::ir::Unary*) { /* inlined */ },              //
+                [&](core::ir::Binary*) { /* inlined */ },             //
+                [&](core::ir::Load*) { /* inlined */ },               //
+                [&](core::ir::Construct*) { /* inlined */ },          //
+                [&](core::ir::Access*) { /* inlined */ },             //
                 TINT_ICE_ON_NO_MATCH);
         }
     }
 
-    // If the instruction is named, we need to emit it. If it is un-named, then we'll use it
-    // and inline it later.
-    void MaybeEmitInstruction(const core::ir::Instruction* inst) {
-        auto name = ir_.NameOf(inst->Result(0));
-        if (!name.IsValid()) {
-            return;
-        }
-
-        auto out = Line();
-        EmitType(out, inst->Result(0)->Type());
-        out << " const " << name.Name() << " = ";
-        EmitValue(out, inst->Result(0));
-        out << ";";
-    }
-
     void EmitValue(StringStream& out, const core::ir::Value* v) {
         Switch(
             v,                                                           //
             [&](const core::ir::Constant* c) { EmitConstant(out, c); },  //
             [&](const core::ir::InstructionResult* r) {
                 Switch(
-                    r->Instruction(),                                        //
-                    [&](const core::ir::Unary* u) { EmitUnary(out, u); },    //
-                    [&](const core::ir::Binary* b) { EmitBinary(out, b); },  //
-                    [&](const core::ir::Let* l) {
-                        auto name = ir_.NameOf(l->Result(0));
-                        TINT_ASSERT(name.IsValid());
-                        out << name.Name();
-                    },                                                                         //
+                    r->Instruction(),                                                          //
+                    [&](const core::ir::Unary* u) { EmitUnary(out, u); },                      //
+                    [&](const core::ir::Binary* b) { EmitBinary(out, b); },                    //
+                    [&](const core::ir::Convert* b) { EmitConvert(out, b); },                  //
+                    [&](const core::ir::Let* l) { out << NameOf(l->Result(0)); },              //
                     [&](const core::ir::Load* l) { EmitValue(out, l->From()); },               //
                     [&](const core::ir::Construct* c) { EmitConstruct(out, c); },              //
-                    [&](const core::ir::Var* var) { EmitVarName(out, var); },                  //
+                    [&](const core::ir::Var* var) { out << NameOf(var->Result(0)); },          //
                     [&](const core::ir::Bitcast* b) { EmitBitcast(out, b); },                  //
                     [&](const core::ir::Access* a) { EmitAccess(out, a); },                    //
                     [&](const core::ir::CoreBuiltinCall* c) { EmitCoreBuiltinCall(out, c); },  //
@@ -409,8 +379,8 @@
                     },                                                         //
                     [&](const core::ir::Swizzle* s) { EmitSwizzle(out, s); },  //
                     TINT_ICE_ON_NO_MATCH);
-            },                                                                     //
-            [&](const core::ir::FunctionParam* p) { EmitFunctionParam(out, p); },  //
+            },                                                            //
+            [&](const core::ir::FunctionParam* p) { out << NameOf(p); },  //
             TINT_ICE_ON_NO_MATCH);
     }
 
@@ -488,7 +458,14 @@
         out << ")";
     }
 
-    void EmitVarName(StringStream& out, const core::ir::Var* v) { out << ir_.NameOf(v).Name(); }
+    /// Emit a convert instruction
+    /// @param c the convert instruction
+    void EmitConvert(StringStream& out, const core::ir::Convert* c) {
+        EmitType(out, c->Result(0)->Type());
+        out << "(";
+        EmitValue(out, c->Operand(0));
+        out << ")";
+    }
 
     /// Emit a var instruction
     /// @param v the var instruction
@@ -514,10 +491,8 @@
                 return;
         }
 
-        auto name = ir_.NameOf(v);
-
         EmitType(out, ptr->UnwrapPtr());
-        out << " " << name.Name();
+        out << " " << NameOf(v->Result(0));
 
         if (v->Initializer()) {
             out << " = ";
@@ -534,12 +509,9 @@
     /// Emit a let instruction
     /// @param l the let instruction
     void EmitLet(core::ir::Let* l) {
-        auto name = ir_.NameOf(l->Result(0));
-        TINT_ASSERT(name.IsValid());
-
         auto out = Line();
         EmitType(out, l->Result(0)->Type());
-        out << " const " << name.Name() << " = ";
+        out << " const " << NameOf(l->Result(0)) << " = ";
         EmitValue(out, l->Value());
         out << ";";
     }
@@ -698,7 +670,7 @@
             auto* val = args[i];
 
             auto out = Line();
-            out << ir_.NameOf(phi).Name() << " = ";
+            out << NameOf(phi) << " = ";
             EmitValue(out, val);
             out << ";";
         }
@@ -773,6 +745,14 @@
         }
     }
 
+    void EmitCallStmt(const core::ir::Call* c) {
+        if (!c->Result(0)->IsUsed()) {
+            auto out = Line();
+            EmitValue(out, c->Result(0));
+            out << ";";
+        }
+    }
+
     void EmitCoreBuiltinCall(StringStream& out, const core::ir::CoreBuiltinCall* c) {
         EmitCoreBuiltinName(out, c->Func());
         out << "(";
@@ -908,7 +888,7 @@
 
     /// Emits a user call instruction
     void EmitUserCall(StringStream& out, const core::ir::UserCall* c) {
-        out << ir_.NameOf(c->Target()).Name() << "(";
+        out << NameOf(c->Target()) << "(";
         size_t i = 0;
         for (const auto* arg : c->Args()) {
             if (i > 0) {
@@ -921,11 +901,6 @@
         out << ")";
     }
 
-    /// Emit a function parameter
-    void EmitFunctionParam(StringStream& out, const core::ir::FunctionParam* p) {
-        out << ir_.NameOf(p).Name();
-    }
-
     /// Emit a constructor
     void EmitConstruct(StringStream& out, const core::ir::Construct* c) {
         Switch(
@@ -1421,6 +1396,18 @@
         return name;
     }
 
+    /// @param value the value to get the name of
+    /// @returns the name of the given value, creating a new unique name if the value is unnamed in
+    /// the module.
+    std::string NameOf(const core::ir::Value* value) {
+        return names_.GetOrCreate(value, [&] {
+            if (auto sym = ir_.NameOf(value); sym.IsValid()) {
+                return sym.Name();
+            }
+            return UniqueIdentifier("v");
+        });
+    }
+
     /// @return a new, unique identifier with the given prefix.
     /// @param prefix optional prefix to apply to the generated identifier. If empty
     /// "tint_symbol" will be used.
diff --git a/src/tint/lang/msl/writer/raise/raise.cc b/src/tint/lang/msl/writer/raise/raise.cc
index b0cfe52..da70216 100644
--- a/src/tint/lang/msl/writer/raise/raise.cc
+++ b/src/tint/lang/msl/writer/raise/raise.cc
@@ -37,6 +37,7 @@
 #include "src/tint/lang/core/ir/transform/multiplanar_external_texture.h"
 #include "src/tint/lang/core/ir/transform/preserve_padding.h"
 #include "src/tint/lang/core/ir/transform/robustness.h"
+#include "src/tint/lang/core/ir/transform/value_to_let.h"
 #include "src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.h"
 #include "src/tint/lang/core/ir/transform/zero_init_workgroup_memory.h"
 #include "src/tint/lang/msl/writer/common/option_helpers.h"
@@ -101,6 +102,8 @@
     // DemoteToHelper must come before any transform that introduces non-core instructions.
     RUN_TRANSFORM(core::ir::transform::DemoteToHelper);
 
+    RUN_TRANSFORM(core::ir::transform::ValueToLet);
+
     return Success;
 }
 
diff --git a/test/tint/access/let/matrix.wgsl.expected.ir.msl b/test/tint/access/let/matrix.wgsl.expected.ir.msl
index 01ffbb0..9a5bc98 100644
--- a/test/tint/access/let/matrix.wgsl.expected.ir.msl
+++ b/test/tint/access/let/matrix.wgsl.expected.ir.msl
@@ -4,5 +4,5 @@
 kernel void tint_symbol() {
   float3x3 const m = float3x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f));
   float3 const v = m[1];
-  float const f = m[1][1];
+  float const f = v[1];
 }
diff --git a/test/tint/access/var/matrix.wgsl.expected.ir.msl b/test/tint/access/var/matrix.wgsl.expected.ir.msl
index 3e8f0f7..bd6323f 100644
--- a/test/tint/access/var/matrix.wgsl.expected.ir.msl
+++ b/test/tint/access/var/matrix.wgsl.expected.ir.msl
@@ -4,5 +4,5 @@
 kernel void tint_symbol() {
   float3x3 m = float3x3(0.0f);
   float3 const v = m[1];
-  float const f = m[1][1];
+  float const f = v[1];
 }
diff --git a/test/tint/array/function_return_type.wgsl.expected.ir.msl b/test/tint/array/function_return_type.wgsl.expected.ir.msl
index 2942935..440724d 100644
--- a/test/tint/array/function_return_type.wgsl.expected.ir.msl
+++ b/test/tint/array/function_return_type.wgsl.expected.ir.msl
@@ -17,10 +17,13 @@
   return tint_array<float, 4>{};
 }
 tint_array<tint_array<float, 4>, 3> f2() {
-  return tint_array<tint_array<float, 4>, 3>{f1(), f1(), f1()};
+  tint_array<float, 4> const v = f1();
+  tint_array<float, 4> const v_1 = f1();
+  return tint_array<tint_array<float, 4>, 3>{v, v_1, f1()};
 }
 tint_array<tint_array<tint_array<float, 4>, 3>, 2> f3() {
-  return tint_array<tint_array<tint_array<float, 4>, 3>, 2>{f2(), f2()};
+  tint_array<tint_array<float, 4>, 3> const v_2 = f2();
+  return tint_array<tint_array<tint_array<float, 4>, 3>, 2>{v_2, f2()};
 }
 kernel void tint_symbol() {
   tint_array<float, 4> const a1 = f1();
diff --git a/test/tint/array/type_initializer.wgsl.expected.ir.msl b/test/tint/array/type_initializer.wgsl.expected.ir.msl
index 89cc56e..8b89e3d 100644
--- a/test/tint/array/type_initializer.wgsl.expected.ir.msl
+++ b/test/tint/array/type_initializer.wgsl.expected.ir.msl
@@ -20,7 +20,8 @@
   tint_array<int, 4> const nonempty_with_expr = tint_array<int, 4>{1, x, (x + 1), nonempty[3]};
   tint_array<tint_array<tint_array<int, 4>, 3>, 2> const nested_empty = tint_array<tint_array<tint_array<int, 4>, 3>, 2>{};
   tint_array<tint_array<tint_array<int, 4>, 3>, 2> const nested_nonempty = tint_array<tint_array<tint_array<int, 4>, 3>, 2>{tint_array<tint_array<int, 4>, 3>{tint_array<int, 4>{1, 2, 3, 4}, tint_array<int, 4>{5, 6, 7, 8}, tint_array<int, 4>{9, 10, 11, 12}}, tint_array<tint_array<int, 4>, 3>{tint_array<int, 4>{13, 14, 15, 16}, tint_array<int, 4>{17, 18, 19, 20}, tint_array<int, 4>{21, 22, 23, 24}}};
-  tint_array<tint_array<tint_array<int, 4>, 3>, 2> const nested_nonempty_with_expr = tint_array<tint_array<tint_array<int, 4>, 3>, 2>{tint_array<tint_array<int, 4>, 3>{tint_array<int, 4>{1, 2, x, (x + 1)}, tint_array<int, 4>{5, 6, nonempty[2], (nonempty[3] + 1)}, nonempty}, nested_nonempty[1]};
+  tint_array<int, 4> const v = tint_array<int, 4>{1, 2, x, (x + 1)};
+  tint_array<tint_array<tint_array<int, 4>, 3>, 2> const nested_nonempty_with_expr = tint_array<tint_array<tint_array<int, 4>, 3>, 2>{tint_array<tint_array<int, 4>, 3>{v, tint_array<int, 4>{5, 6, nonempty[2], (nonempty[3] + 1)}, nonempty}, nested_nonempty[1]};
   int const subexpr_empty = 0;
   int const subexpr_nonempty = 3;
   int const subexpr_nonempty_with_expr = tint_array<int, 4>{1, x, (x + 1), nonempty[3]}[2];
diff --git a/test/tint/bug/chromium/1372963.wgsl.expected.ir.msl b/test/tint/bug/chromium/1372963.wgsl.expected.ir.msl
index 31c2e5a..16bddd9 100644
--- a/test/tint/bug/chromium/1372963.wgsl.expected.ir.msl
+++ b/test/tint/bug/chromium/1372963.wgsl.expected.ir.msl
@@ -5,4 +5,5 @@
   return int4(0);
 }
 fragment void tint_symbol() {
+  g();
 }
diff --git a/test/tint/bug/tint/1563.wgsl.expected.ir.msl b/test/tint/bug/tint/1563.wgsl.expected.ir.msl
index 3245973..6d165d3 100644
--- a/test/tint/bug/tint/1563.wgsl.expected.ir.msl
+++ b/test/tint/bug/tint/1563.wgsl.expected.ir.msl
@@ -5,6 +5,6 @@
   int const oob = 99;
   float const b = float4(0.0f)[oob];
   float4 v = 0.0f;
-  v[oob] = float4(0.0f)[oob];
-  return float4(0.0f)[oob];
+  v[oob] = b;
+  return b;
 }
diff --git a/test/tint/bug/tint/1670.spvasm.expected.ir.msl b/test/tint/bug/tint/1670.spvasm.expected.ir.msl
index 6a77df4..20cc98d 100644
--- a/test/tint/bug/tint/1670.spvasm.expected.ir.msl
+++ b/test/tint/bug/tint/1670.spvasm.expected.ir.msl
@@ -9,9 +9,17 @@
   float4x4 m4i = float4x4(0.0f);
   float4x4 m4 = float4x4(0.0f);
   float const s = (1.0f / determinant(m2));
-  m2i = float2x2(float2(((1.0f / determinant(m2)) * m2[1u][1u]), (-((1.0f / determinant(m2))) * m2[0u][1u])), float2((-((1.0f / determinant(m2))) * m2[1u][0u]), ((1.0f / determinant(m2)) * m2[0u][0u])));
-  m3i = ((1.0f / determinant(m3)) * float3x3(float3(((m3[1u][1u] * m3[2u][2u]) - (m3[1u][2u] * m3[2u][1u])), ((m3[0u][2u] * m3[2u][1u]) - (m3[0u][1u] * m3[2u][2u])), ((m3[0u][1u] * m3[1u][2u]) - (m3[0u][2u] * m3[1u][1u]))), float3(((m3[1u][2u] * m3[2u][0u]) - (m3[1u][0u] * m3[2u][2u])), ((m3[0u][0u] * m3[2u][2u]) - (m3[0u][2u] * m3[2u][0u])), ((m3[0u][2u] * m3[1u][0u]) - (m3[0u][0u] * m3[1u][2u]))), float3(((m3[1u][0u] * m3[2u][1u]) - (m3[1u][1u] * m3[2u][0u])), ((m3[0u][1u] * m3[2u][0u]) - (m3[0u][0u] * m3[2u][1u])), ((m3[0u][0u] * m3[1u][1u]) - (m3[0u][1u] * m3[1u][0u])))));
-  m4i = ((1.0f / determinant(m4)) * float4x4(float4((((m4[1u][1u] * ((m4[2u][2u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][2u]))) - (m4[1u][2u] * ((m4[2u][1u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][1u])))) + (m4[1u][3u] * ((m4[2u][1u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][1u])))), (((-(m4[0u][1u]) * ((m4[2u][2u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][2u]))) + (m4[0u][2u] * ((m4[2u][1u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][1u])))) - (m4[0u][3u] * ((m4[2u][1u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][1u])))), (((m4[0u][1u] * ((m4[1u][2u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][2u]))) - (m4[0u][2u] * ((m4[1u][1u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][1u])))) + (m4[0u][3u] * ((m4[1u][1u] * m4[3u][2u]) - (m4[1u][2u] * m4[3u][1u])))), (((-(m4[0u][1u]) * ((m4[1u][2u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][2u]))) + (m4[0u][2u] * ((m4[1u][1u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][1u])))) - (m4[0u][3u] * ((m4[1u][1u] * m4[2u][2u]) - (m4[1u][2u] * m4[2u][1u]))))), float4((((-(m4[1u][0u]) * ((m4[2u][2u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][2u]))) + (m4[1u][2u] * ((m4[2u][0u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][0u])))) - (m4[1u][3u] * ((m4[2u][0u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][0u])))), (((m4[0u][0u] * ((m4[2u][2u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][2u]))) - (m4[0u][2u] * ((m4[2u][0u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][0u])))) + (m4[0u][3u] * ((m4[2u][0u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][0u])))), (((-(m4[0u][0u]) * ((m4[1u][2u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][2u]))) + (m4[0u][2u] * ((m4[1u][0u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][0u])))) - (m4[0u][3u] * ((m4[1u][0u] * m4[3u][2u]) - (m4[1u][2u] * m4[3u][0u])))), (((m4[0u][0u] * ((m4[1u][2u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][2u]))) - (m4[0u][2u] * ((m4[1u][0u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][0u])))) + (m4[0u][3u] * ((m4[1u][0u] * m4[2u][2u]) - (m4[1u][2u] * m4[2u][0u]))))), float4((((m4[1u][0u] * ((m4[2u][1u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][1u]))) - (m4[1u][1u] * ((m4[2u][0u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][0u])))) + (m4[1u][3u] * ((m4[2u][0u] * m4[3u][1u]) - (m4[2u][1u] * m4[3u][0u])))), (((-(m4[0u][0u]) * ((m4[2u][1u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][1u]))) + (m4[0u][1u] * ((m4[2u][0u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][0u])))) - (m4[0u][3u] * ((m4[2u][0u] * m4[3u][1u]) - (m4[2u][1u] * m4[3u][0u])))), (((m4[0u][0u] * ((m4[1u][1u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][1u]))) - (m4[0u][1u] * ((m4[1u][0u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][0u])))) + (m4[0u][3u] * ((m4[1u][0u] * m4[3u][1u]) - (m4[1u][1u] * m4[3u][0u])))), (((-(m4[0u][0u]) * ((m4[1u][1u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][1u]))) + (m4[0u][1u] * ((m4[1u][0u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][0u])))) - (m4[0u][3u] * ((m4[1u][0u] * m4[2u][1u]) - (m4[1u][1u] * m4[2u][0u]))))), float4((((-(m4[1u][0u]) * ((m4[2u][1u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][1u]))) + (m4[1u][1u] * ((m4[2u][0u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][0u])))) - (m4[1u][2u] * ((m4[2u][0u] * m4[3u][1u]) - (m4[2u][1u] * m4[3u][0u])))), (((m4[0u][0u] * ((m4[2u][1u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][1u]))) - (m4[0u][1u] * ((m4[2u][0u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][0u])))) + (m4[0u][2u] * ((m4[2u][0u] * m4[3u][1u]) - (m4[2u][1u] * m4[3u][0u])))), (((-(m4[0u][0u]) * ((m4[1u][1u] * m4[3u][2u]) - (m4[1u][2u] * m4[3u][1u]))) + (m4[0u][1u] * ((m4[1u][0u] * m4[3u][2u]) - (m4[1u][2u] * m4[3u][0u])))) - (m4[0u][2u] * ((m4[1u][0u] * m4[3u][1u]) - (m4[1u][1u] * m4[3u][0u])))), (((m4[0u][0u] * ((m4[1u][1u] * m4[2u][2u]) - (m4[1u][2u] * m4[2u][1u]))) - (m4[0u][1u] * ((m4[1u][0u] * m4[2u][2u]) - (m4[1u][2u] * m4[2u][0u])))) + (m4[0u][2u] * ((m4[1u][0u] * m4[2u][1u]) - (m4[1u][1u] * m4[2u][0u])))))));
+  float2 const v = float2((s * m2[1u][1u]), (-(s) * m2[0u][1u]));
+  m2i = float2x2(v, float2((-(s) * m2[1u][0u]), (s * m2[0u][0u])));
+  float const v_1 = (1.0f / determinant(m3));
+  float3 const v_2 = float3(((m3[1u][1u] * m3[2u][2u]) - (m3[1u][2u] * m3[2u][1u])), ((m3[0u][2u] * m3[2u][1u]) - (m3[0u][1u] * m3[2u][2u])), ((m3[0u][1u] * m3[1u][2u]) - (m3[0u][2u] * m3[1u][1u])));
+  float3 const v_3 = float3(((m3[1u][2u] * m3[2u][0u]) - (m3[1u][0u] * m3[2u][2u])), ((m3[0u][0u] * m3[2u][2u]) - (m3[0u][2u] * m3[2u][0u])), ((m3[0u][2u] * m3[1u][0u]) - (m3[0u][0u] * m3[1u][2u])));
+  m3i = (v_1 * float3x3(v_2, v_3, float3(((m3[1u][0u] * m3[2u][1u]) - (m3[1u][1u] * m3[2u][0u])), ((m3[0u][1u] * m3[2u][0u]) - (m3[0u][0u] * m3[2u][1u])), ((m3[0u][0u] * m3[1u][1u]) - (m3[0u][1u] * m3[1u][0u])))));
+  float const v_4 = (1.0f / determinant(m4));
+  float4 const v_5 = float4((((m4[1u][1u] * ((m4[2u][2u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][2u]))) - (m4[1u][2u] * ((m4[2u][1u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][1u])))) + (m4[1u][3u] * ((m4[2u][1u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][1u])))), (((-(m4[0u][1u]) * ((m4[2u][2u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][2u]))) + (m4[0u][2u] * ((m4[2u][1u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][1u])))) - (m4[0u][3u] * ((m4[2u][1u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][1u])))), (((m4[0u][1u] * ((m4[1u][2u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][2u]))) - (m4[0u][2u] * ((m4[1u][1u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][1u])))) + (m4[0u][3u] * ((m4[1u][1u] * m4[3u][2u]) - (m4[1u][2u] * m4[3u][1u])))), (((-(m4[0u][1u]) * ((m4[1u][2u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][2u]))) + (m4[0u][2u] * ((m4[1u][1u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][1u])))) - (m4[0u][3u] * ((m4[1u][1u] * m4[2u][2u]) - (m4[1u][2u] * m4[2u][1u])))));
+  float4 const v_6 = float4((((-(m4[1u][0u]) * ((m4[2u][2u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][2u]))) + (m4[1u][2u] * ((m4[2u][0u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][0u])))) - (m4[1u][3u] * ((m4[2u][0u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][0u])))), (((m4[0u][0u] * ((m4[2u][2u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][2u]))) - (m4[0u][2u] * ((m4[2u][0u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][0u])))) + (m4[0u][3u] * ((m4[2u][0u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][0u])))), (((-(m4[0u][0u]) * ((m4[1u][2u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][2u]))) + (m4[0u][2u] * ((m4[1u][0u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][0u])))) - (m4[0u][3u] * ((m4[1u][0u] * m4[3u][2u]) - (m4[1u][2u] * m4[3u][0u])))), (((m4[0u][0u] * ((m4[1u][2u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][2u]))) - (m4[0u][2u] * ((m4[1u][0u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][0u])))) + (m4[0u][3u] * ((m4[1u][0u] * m4[2u][2u]) - (m4[1u][2u] * m4[2u][0u])))));
+  float4 const v_7 = float4((((m4[1u][0u] * ((m4[2u][1u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][1u]))) - (m4[1u][1u] * ((m4[2u][0u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][0u])))) + (m4[1u][3u] * ((m4[2u][0u] * m4[3u][1u]) - (m4[2u][1u] * m4[3u][0u])))), (((-(m4[0u][0u]) * ((m4[2u][1u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][1u]))) + (m4[0u][1u] * ((m4[2u][0u] * m4[3u][3u]) - (m4[2u][3u] * m4[3u][0u])))) - (m4[0u][3u] * ((m4[2u][0u] * m4[3u][1u]) - (m4[2u][1u] * m4[3u][0u])))), (((m4[0u][0u] * ((m4[1u][1u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][1u]))) - (m4[0u][1u] * ((m4[1u][0u] * m4[3u][3u]) - (m4[1u][3u] * m4[3u][0u])))) + (m4[0u][3u] * ((m4[1u][0u] * m4[3u][1u]) - (m4[1u][1u] * m4[3u][0u])))), (((-(m4[0u][0u]) * ((m4[1u][1u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][1u]))) + (m4[0u][1u] * ((m4[1u][0u] * m4[2u][3u]) - (m4[1u][3u] * m4[2u][0u])))) - (m4[0u][3u] * ((m4[1u][0u] * m4[2u][1u]) - (m4[1u][1u] * m4[2u][0u])))));
+  m4i = (v_4 * float4x4(v_5, v_6, v_7, float4((((-(m4[1u][0u]) * ((m4[2u][1u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][1u]))) + (m4[1u][1u] * ((m4[2u][0u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][0u])))) - (m4[1u][2u] * ((m4[2u][0u] * m4[3u][1u]) - (m4[2u][1u] * m4[3u][0u])))), (((m4[0u][0u] * ((m4[2u][1u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][1u]))) - (m4[0u][1u] * ((m4[2u][0u] * m4[3u][2u]) - (m4[2u][2u] * m4[3u][0u])))) + (m4[0u][2u] * ((m4[2u][0u] * m4[3u][1u]) - (m4[2u][1u] * m4[3u][0u])))), (((-(m4[0u][0u]) * ((m4[1u][1u] * m4[3u][2u]) - (m4[1u][2u] * m4[3u][1u]))) + (m4[0u][1u] * ((m4[1u][0u] * m4[3u][2u]) - (m4[1u][2u] * m4[3u][0u])))) - (m4[0u][2u] * ((m4[1u][0u] * m4[3u][1u]) - (m4[1u][1u] * m4[3u][0u])))), (((m4[0u][0u] * ((m4[1u][1u] * m4[2u][2u]) - (m4[1u][2u] * m4[2u][1u]))) - (m4[0u][1u] * ((m4[1u][0u] * m4[2u][2u]) - (m4[1u][2u] * m4[2u][0u])))) + (m4[0u][2u] * ((m4[1u][0u] * m4[2u][1u]) - (m4[1u][1u] * m4[2u][0u])))))));
 }
 fragment void tint_symbol() {
   main_1();
diff --git a/test/tint/bug/tint/764.wgsl.expected.ir.msl b/test/tint/bug/tint/764.wgsl.expected.ir.msl
index ac3c498..7a3cc67 100644
--- a/test/tint/bug/tint/764.wgsl.expected.ir.msl
+++ b/test/tint/bug/tint/764.wgsl.expected.ir.msl
@@ -4,5 +4,5 @@
 void f() {
   float4x4 const m = float4x4(float4(1.0f), float4(1.0f), float4(1.0f), float4(1.0f));
   float4 const v1 = m[0];
-  float const a = m[0][0];
+  float const a = v1[0];
 }
diff --git a/test/tint/statements/assign/phony/call.wgsl.expected.ir.msl b/test/tint/statements/assign/phony/call.wgsl.expected.ir.msl
index 3990430..dc9031e 100644
--- a/test/tint/statements/assign/phony/call.wgsl.expected.ir.msl
+++ b/test/tint/statements/assign/phony/call.wgsl.expected.ir.msl
@@ -5,4 +5,5 @@
   return ((a * b) + c);
 }
 kernel void tint_symbol() {
+  f(1, 2, 3);
 }
diff --git a/test/tint/statements/assign/phony/multiple_side_effects.wgsl.expected.ir.msl b/test/tint/statements/assign/phony/multiple_side_effects.wgsl.expected.ir.msl
index 3990430..28120e4 100644
--- a/test/tint/statements/assign/phony/multiple_side_effects.wgsl.expected.ir.msl
+++ b/test/tint/statements/assign/phony/multiple_side_effects.wgsl.expected.ir.msl
@@ -5,4 +5,6 @@
   return ((a * b) + c);
 }
 kernel void tint_symbol() {
+  int const v = f(1, 2, 3);
+  int const v_1 = f(4, 5, 6);
 }
diff --git a/test/tint/unicode/identifiers.wgsl.expected.ir.msl b/test/tint/unicode/identifiers.wgsl.expected.ir.msl
index 47c8fbc..70a9af7 100644
--- a/test/tint/unicode/identifiers.wgsl.expected.ir.msl
+++ b/test/tint/unicode/identifiers.wgsl.expected.ir.msl
@@ -1,9 +1,10 @@
-SKIP: FAILED
+#include <metal_stdlib>
+using namespace metal;
 
-<dawn>/src/tint/lang/msl/writer/printer/printer.cc:247 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Convert
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
+float tint_symbol_2(int tint_symbol_3) {
+  return float(tint_symbol_3);
+}
+fragment void tint_symbol_4() {
+  int tint_symbol_5 = 0;
+  float const tint_symbol_6 = tint_symbol_2(tint_symbol_5);
+}