writer/hlsl: Emit more helpers for intrinsic calls

And call these helpers instead of inlining complex statements.
Cleans up output, and helps prevent for-loops decaying to while loops.

Change-Id: I6ac31b18ce6c5fac0e54e982f7db3bb298f7edb2
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/58060
Auto-Submit: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index b983b3f..dbaed5a 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -1275,219 +1275,200 @@
                                   const sem::Intrinsic* intrinsic) {
   // Exponent is an integer in WGSL, but HLSL wants a float.
   // We need to make the call with a temporary float, and then cast.
+  return CallIntrinsicHelper(
+      out, expr, intrinsic,
+      [&](TextBuffer* b, const std::vector<std::string>& params) {
+        auto* significand_ty = intrinsic->Parameters()[0].type;
+        auto significand = params[0];
+        auto* exponent_ty = intrinsic->Parameters()[1].type;
+        auto exponent = params[1];
 
-  auto signficand = intrinsic->Parameters()[0];
-  auto exponent = intrinsic->Parameters()[1];
+        std::string width;
+        if (auto* vec = significand_ty->As<sem::Vector>()) {
+          width = std::to_string(vec->size());
+        }
 
-  std::string width;
-  if (auto* vec = signficand.type->As<sem::Vector>()) {
-    width = std::to_string(vec->size());
-  }
-
-  // Exponent is an integer, which HLSL does not have an overload for.
-  // We need to cast from a float.
-  auto float_exp = UniqueIdentifier(kTempNamePrefix);
-  auto significand = UniqueIdentifier(kTempNamePrefix);
-  line() << "float" << width << " " << float_exp << ";";
-  {
-    auto pre = line();
-    pre << "float" << width << " " << significand << " = frexp(";
-    if (!EmitExpression(pre, expr->params()[0])) {
-      return false;
-    }
-    pre << ", " << float_exp << ");";
-  }
-  {
-    auto pre = line();
-    if (!EmitExpression(pre, expr->params()[1])) {
-      return false;
-    }
-    pre << " = ";
-    if (!EmitType(pre, exponent.type->UnwrapPtr(), ast::StorageClass::kNone,
-                  ast::Access::kUndefined, "")) {
-      return false;
-    }
-    pre << "(" << float_exp << ");";
-  }
-
-  out << significand;
-  return true;
+        // Exponent is an integer, which HLSL does not have an overload for.
+        // We need to cast from a float.
+        line(b) << "float" << width << " float_exp;";
+        line(b) << "float" << width << " significand = frexp(" << significand
+                << ", float_exp);";
+        {
+          auto l = line(b);
+          l << exponent << " = ";
+          if (!EmitType(l, exponent_ty->UnwrapPtr(), ast::StorageClass::kNone,
+                        ast::Access::kUndefined, "")) {
+            return false;
+          }
+          l << "(float_exp);";
+        }
+        line(b) << "return significand;";
+        return true;
+      });
 }
 
 bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
                                      ast::CallExpression* expr,
                                      const sem::Intrinsic* intrinsic) {
   // HLSL doesn't have a isNormal intrinsic, we need to emulate
-  auto input = intrinsic->Parameters()[0];
+  return CallIntrinsicHelper(
+      out, expr, intrinsic,
+      [&](TextBuffer* b, const std::vector<std::string>& params) {
+        auto* input_ty = intrinsic->Parameters()[0].type;
 
-  std::string width;
-  if (auto* vec = input.type->As<sem::Vector>()) {
-    width = std::to_string(vec->size());
-  }
+        std::string width;
+        if (auto* vec = input_ty->As<sem::Vector>()) {
+          width = std::to_string(vec->size());
+        }
 
-  constexpr auto* kExponentMask = "0x7f80000";
-  constexpr auto* kMinNormalExponent = "0x0080000";
-  constexpr auto* kMaxNormalExponent = "0x7f00000";
+        constexpr auto* kExponentMask = "0x7f80000";
+        constexpr auto* kMinNormalExponent = "0x0080000";
+        constexpr auto* kMaxNormalExponent = "0x7f00000";
 
-  auto exponent = UniqueIdentifier("tint_isnormal_exponent");
-  auto clamped = UniqueIdentifier("tint_isnormal_clamped");
-
-  {
-    auto pre = line();
-    pre << "uint" << width << " " << exponent << " = asuint(";
-    if (!EmitExpression(pre, expr->params()[0])) {
-      return false;
-    }
-    pre << ") & " << kExponentMask << ";";
-  }
-  line() << "uint" << width << " " << clamped << " = "
-         << "clamp(" << exponent << ", " << kMinNormalExponent << ", "
-         << kMaxNormalExponent << ");";
-
-  out << "(" << clamped << " == " << exponent << ")";
-  return true;
+        line(b) << "uint" << width << " exponent = asuint(" << params[0]
+                << ") & " << kExponentMask << ";";
+        line(b) << "uint" << width << " clamped = "
+                << "clamp(exponent, " << kMinNormalExponent << ", "
+                << kMaxNormalExponent << ");";
+        line(b) << "return clamped == exponent;";
+        return true;
+      });
 }
 
 bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
                                         ast::CallExpression* expr,
                                         const sem::Intrinsic* intrinsic) {
-  auto* param = expr->params()[0];
-  auto tmp_name = UniqueIdentifier(kTempNamePrefix);
-  std::ostringstream expr_out;
-  if (!EmitExpression(expr_out, param)) {
-    return false;
-  }
-  uint32_t dims = 2;
-  bool is_signed = false;
-  uint32_t scale = 65535;
-  if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm ||
-      intrinsic->Type() == sem::IntrinsicType::kPack4x8unorm) {
-    dims = 4;
-    scale = 255;
-  }
-  if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm ||
-      intrinsic->Type() == sem::IntrinsicType::kPack2x16snorm) {
-    is_signed = true;
-    scale = (scale - 1) / 2;
-  }
-  switch (intrinsic->Type()) {
-    case sem::IntrinsicType::kPack4x8snorm:
-    case sem::IntrinsicType::kPack4x8unorm:
-    case sem::IntrinsicType::kPack2x16snorm:
-    case sem::IntrinsicType::kPack2x16unorm: {
-      {
-        auto pre = line();
-        pre << (is_signed ? "" : "u") << "int" << dims << " " << tmp_name
-            << " = " << (is_signed ? "" : "u") << "int" << dims
-            << "(round(clamp(" << expr_out.str() << ", "
-            << (is_signed ? "-1.0" : "0.0") << ", 1.0) * " << scale << ".0))";
-        if (is_signed) {
-          pre << " & " << (dims == 4 ? "0xff" : "0xffff");
+  return CallIntrinsicHelper(
+      out, expr, intrinsic,
+      [&](TextBuffer* b, const std::vector<std::string>& params) {
+        uint32_t dims = 2;
+        bool is_signed = false;
+        uint32_t scale = 65535;
+        if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm ||
+            intrinsic->Type() == sem::IntrinsicType::kPack4x8unorm) {
+          dims = 4;
+          scale = 255;
         }
-        pre << ";";
-      }
-      if (is_signed) {
-        out << "asuint";
-      }
-      out << "(";
-      out << tmp_name << ".x | " << tmp_name << ".y << " << (32 / dims);
-      if (dims == 4) {
-        out << " | " << tmp_name << ".z << 16 | " << tmp_name << ".w << 24";
-      }
-      out << ")";
-      break;
-    }
-    case sem::IntrinsicType::kPack2x16float: {
-      line() << "uint2 " << tmp_name << " = f32tof16(" << expr_out.str()
-             << ");";
-      out << "(" << tmp_name << ".x | " << tmp_name << ".y << 16)";
-      break;
-    }
-    default:
-      diagnostics_.add_error(
-          diag::System::Writer,
-          "Internal error: unhandled data packing intrinsic");
-      return false;
-  }
+        if (intrinsic->Type() == sem::IntrinsicType::kPack4x8snorm ||
+            intrinsic->Type() == sem::IntrinsicType::kPack2x16snorm) {
+          is_signed = true;
+          scale = (scale - 1) / 2;
+        }
+        switch (intrinsic->Type()) {
+          case sem::IntrinsicType::kPack4x8snorm:
+          case sem::IntrinsicType::kPack4x8unorm:
+          case sem::IntrinsicType::kPack2x16snorm:
+          case sem::IntrinsicType::kPack2x16unorm: {
+            {
+              auto l = line(b);
+              l << (is_signed ? "" : "u") << "int" << dims
+                << " i = " << (is_signed ? "" : "u") << "int" << dims
+                << "(round(clamp(" << params[0] << ", "
+                << (is_signed ? "-1.0" : "0.0") << ", 1.0) * " << scale
+                << ".0))";
+              if (is_signed) {
+                l << " & " << (dims == 4 ? "0xff" : "0xffff");
+              }
+              l << ";";
+            }
+            {
+              auto l = line(b);
+              l << "return ";
+              if (is_signed) {
+                l << "asuint";
+              }
+              l << "(i.x | i.y << " << (32 / dims);
+              if (dims == 4) {
+                l << " | i.z << 16 | i.w << 24";
+              }
+              l << ");";
+            }
+            break;
+          }
+          case sem::IntrinsicType::kPack2x16float: {
+            line(b) << "uint2 i = f32tof16(" << params[0] << ");";
+            line(b) << "return i.x | (i.y << 16);";
+            break;
+          }
+          default:
+            diagnostics_.add_error(
+                diag::System::Writer,
+                "Internal error: unhandled data packing intrinsic");
+            return false;
+        }
 
-  return true;
+        return true;
+      });
 }
 
 bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
                                           ast::CallExpression* expr,
                                           const sem::Intrinsic* intrinsic) {
-  auto* param = expr->params()[0];
-  auto tmp_name = UniqueIdentifier(kTempNamePrefix);
-  std::ostringstream expr_out;
-  if (!EmitExpression(expr_out, param)) {
-    return false;
-  }
-  uint32_t dims = 2;
-  bool is_signed = false;
-  uint32_t scale = 65535;
-  if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm ||
-      intrinsic->Type() == sem::IntrinsicType::kUnpack4x8unorm) {
-    dims = 4;
-    scale = 255;
-  }
-  if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm ||
-      intrinsic->Type() == sem::IntrinsicType::kUnpack2x16snorm) {
-    is_signed = true;
-    scale = (scale - 1) / 2;
-  }
-  switch (intrinsic->Type()) {
-    case sem::IntrinsicType::kUnpack4x8snorm:
-    case sem::IntrinsicType::kUnpack2x16snorm: {
-      auto tmp_name2 = UniqueIdentifier(kTempNamePrefix);
-      line() << "int " << tmp_name2 << " = int(" << expr_out.str() << ");";
-      {  // Perform sign extension on the converted values.
-        auto pre = line();
-        pre << "int" << dims << " " << tmp_name << " = int" << dims << "(";
-        if (dims == 2) {
-          pre << tmp_name2 << " << 16, " << tmp_name2 << ") >> 16";
-        } else {
-          pre << tmp_name2 << " << 24, " << tmp_name2 << " << 16, " << tmp_name2
-              << " << 8, " << tmp_name2 << ") >> 24";
+  return CallIntrinsicHelper(
+      out, expr, intrinsic,
+      [&](TextBuffer* b, const std::vector<std::string>& params) {
+        uint32_t dims = 2;
+        bool is_signed = false;
+        uint32_t scale = 65535;
+        if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm ||
+            intrinsic->Type() == sem::IntrinsicType::kUnpack4x8unorm) {
+          dims = 4;
+          scale = 255;
         }
-        pre << ";";
-      }
-
-      out << "clamp(float" << dims << "(" << tmp_name << ") / " << scale
-          << ".0, " << (is_signed ? "-1.0" : "0.0") << ", 1.0)";
-      break;
-    }
-    case sem::IntrinsicType::kUnpack4x8unorm:
-    case sem::IntrinsicType::kUnpack2x16unorm: {
-      auto tmp_name2 = UniqueIdentifier(kTempNamePrefix);
-      line() << "uint " << tmp_name2 << " = " << expr_out.str() << ";";
-      {
-        auto pre = line();
-        pre << "uint" << dims << " " << tmp_name << " = uint" << dims << "(";
-        pre << tmp_name2 << " & " << (dims == 2 ? "0xffff" : "0xff") << ", ";
-        if (dims == 4) {
-          pre << "(" << tmp_name2 << " >> " << (32 / dims) << ") & 0xff, ("
-              << tmp_name2 << " >> 16) & 0xff, " << tmp_name2 << " >> 24";
-        } else {
-          pre << tmp_name2 << " >> " << (32 / dims);
+        if (intrinsic->Type() == sem::IntrinsicType::kUnpack4x8snorm ||
+            intrinsic->Type() == sem::IntrinsicType::kUnpack2x16snorm) {
+          is_signed = true;
+          scale = (scale - 1) / 2;
         }
-        pre << ");";
-      }
-      out << "float" << dims << "(" << tmp_name << ") / " << scale << ".0";
-      break;
-    }
-    case sem::IntrinsicType::kUnpack2x16float:
-      line() << "uint " << tmp_name << " = " << expr_out.str() << ";";
-      out << "f16tof32(uint2(" << tmp_name << " & 0xffff, " << tmp_name
-          << " >> 16))";
-      break;
-    default:
-      diagnostics_.add_error(
-          diag::System::Writer,
-          "Internal error: unhandled data packing intrinsic");
-      return false;
-  }
+        switch (intrinsic->Type()) {
+          case sem::IntrinsicType::kUnpack4x8snorm:
+          case sem::IntrinsicType::kUnpack2x16snorm: {
+            line(b) << "int j = int(" << params[0] << ");";
+            {  // Perform sign extension on the converted values.
+              auto l = line(b);
+              l << "int" << dims << " i = int" << dims << "(";
+              if (dims == 2) {
+                l << "j << 16, j) >> 16";
+              } else {
+                l << "j << 24, j << 16, j << 8, j) >> 24";
+              }
+              l << ";";
+            }
+            line(b) << "return clamp(float" << dims << "(i) / " << scale
+                    << ".0, " << (is_signed ? "-1.0" : "0.0") << ", 1.0);";
+            break;
+          }
+          case sem::IntrinsicType::kUnpack4x8unorm:
+          case sem::IntrinsicType::kUnpack2x16unorm: {
+            line(b) << "uint j = " << params[0] << ";";
+            {
+              auto l = line(b);
+              l << "uint" << dims << " i = uint" << dims << "(";
+              l << "j & " << (dims == 2 ? "0xffff" : "0xff") << ", ";
+              if (dims == 4) {
+                l << "(j >> " << (32 / dims)
+                  << ") & 0xff, (j >> 16) & 0xff, j >> 24";
+              } else {
+                l << "j >> " << (32 / dims);
+              }
+              l << ");";
+            }
+            line(b) << "return float" << dims << "(i) / " << scale << ".0;";
+            break;
+          }
+          case sem::IntrinsicType::kUnpack2x16float:
+            line(b) << "uint i = " << params[0] << ";";
+            line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));";
+            break;
+          default:
+            diagnostics_.add_error(
+                diag::System::Writer,
+                "Internal error: unhandled data packing intrinsic");
+            return false;
+        }
 
-  return true;
+        return true;
+      });
 }
 
 bool GeneratorImpl::EmitBarrierCall(std::ostream& out,
@@ -3247,19 +3228,75 @@
   return true;
 }
 
-std::string GeneratorImpl::get_buffer_name(ast::Expression* expr) {
-  for (;;) {
-    if (auto* ident = expr->As<ast::IdentifierExpression>()) {
-      return builder_.Symbols().NameFor(ident->symbol());
-    } else if (auto* member = expr->As<ast::MemberAccessorExpression>()) {
-      expr = member->structure();
-    } else if (auto* array = expr->As<ast::ArrayAccessorExpression>()) {
-      expr = array->array();
-    } else {
-      break;
+template <typename F>
+bool GeneratorImpl::CallIntrinsicHelper(std::ostream& out,
+                                        ast::CallExpression* call,
+                                        const sem::Intrinsic* intrinsic,
+                                        F&& build) {
+  // Generate the helper function if it hasn't been created already
+  auto fn = utils::GetOrCreate(intrinsics_, intrinsic, [&]() -> std::string {
+    auto fn_name =
+        UniqueIdentifier(std::string("tint_") + sem::str(intrinsic->Type()));
+    std::vector<std::string> parameter_names;
+    {
+      auto decl = line(&helpers_);
+      if (!EmitTypeAndName(decl, intrinsic->ReturnType(),
+                           ast::StorageClass::kNone, ast::Access::kUndefined,
+                           fn_name)) {
+        return "";
+      }
+      {
+        ScopedParen sp(decl);
+        for (auto param : intrinsic->Parameters()) {
+          if (!parameter_names.empty()) {
+            decl << ", ";
+          }
+          auto param_name = "param_" + std::to_string(parameter_names.size());
+          const auto* ty = param.type;
+          if (auto* ptr = ty->As<sem::Pointer>()) {
+            decl << "inout ";
+            ty = ptr->StoreType();
+          }
+          if (!EmitTypeAndName(decl, ty, ast::StorageClass::kNone,
+                               ast::Access::kUndefined, param_name)) {
+            return "";
+          }
+          parameter_names.emplace_back(std::move(param_name));
+        }
+      }
+      decl << " {";
+    }
+    {
+      ScopedIndent si(&helpers_);
+      if (!build(&helpers_, parameter_names)) {
+        return "";
+      }
+    }
+    line(&helpers_) << "}";
+    line(&helpers_);
+    return fn_name;
+  });
+
+  if (fn.empty()) {
+    return false;
+  }
+
+  // Call the helper
+  out << fn;
+  {
+    ScopedParen sp(out);
+    bool first = true;
+    for (auto* arg : call->params()) {
+      if (!first) {
+        out << ", ";
+      }
+      first = false;
+      if (!EmitExpression(out, arg)) {
+        return false;
+      }
     }
   }
-  return "";
+  return true;
 }
 
 }  // namespace hlsl
diff --git a/src/writer/hlsl/generator_impl.h b/src/writer/hlsl/generator_impl.h
index 2a39a5a..1fdd404 100644
--- a/src/writer/hlsl/generator_impl.h
+++ b/src/writer/hlsl/generator_impl.h
@@ -400,12 +400,31 @@
     };
   };
 
-  std::string get_buffer_name(ast::Expression* expr);
+  /// CallIntrinsicHelper will call the intrinsic helper function, creating it
+  /// if it hasn't been built already. If the intrinsic needs to be built then
+  /// CallIntrinsicHelper will generate the function signature and will call
+  /// `build` to emit the body of the function.
+  /// @param out the output of the expression stream
+  /// @param call the call expression
+  /// @param intrinsic the semantic information for the intrinsic
+  /// @param build a function with the signature:
+  ///        `bool(TextBuffer* buffer, const std::vector<std::string>& params)`
+  ///        Where:
+  ///          `buffer` is the body of the generated function
+  ///          `params` is the name of all the generated function parameters
+  /// @returns true if the call expression is emitted
+
+  template <typename F>
+  bool CallIntrinsicHelper(std::ostream& out,
+                           ast::CallExpression* call,
+                           const sem::Intrinsic* intrinsic,
+                           F&& build);
 
   TextBuffer helpers_;  // Helper functions emitted at the top of the output
   std::function<bool()> emit_continuing_;
   std::unordered_map<DMAIntrinsic, std::string, DMAIntrinsic::Hasher>
       dma_intrinsics_;
+  std::unordered_map<const sem::Intrinsic*, std::string> intrinsics_;
   std::unordered_map<const sem::Struct*, std::string> structure_builders_;
   std::unordered_map<const sem::Vector*, std::string> dynamic_vector_write_;
 };
diff --git a/src/writer/hlsl/generator_impl_intrinsic_test.cc b/src/writer/hlsl/generator_impl_intrinsic_test.cc
index 4527db7..1d5407a 100644
--- a/src/writer/hlsl/generator_impl_intrinsic_test.cc
+++ b/src/writer/hlsl/generator_impl_intrinsic_test.cc
@@ -326,12 +326,21 @@
   GeneratorImpl& gen = SanitizeAndBuild();
 
   ASSERT_TRUE(gen.Generate()) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr(R"(
-  float tint_tmp;
-  float tint_tmp_1 = frexp(1.0f, tint_tmp);
-  exp = int(tint_tmp);
-  tint_tmp_1;
-)"));
+  EXPECT_EQ(gen.result(),
+            R"(float tint_frexp(float param_0, inout int param_1) {
+  float float_exp;
+  float significand = frexp(param_0, float_exp);
+  param_1 = int(float_exp);
+  return significand;
+}
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  int exp = 0;
+  tint_frexp(1.0f, exp);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) {
@@ -342,12 +351,21 @@
   GeneratorImpl& gen = SanitizeAndBuild();
 
   ASSERT_TRUE(gen.Generate()) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr(R"(
-  float3 tint_tmp;
-  float3 tint_tmp_1 = frexp(float3(0.0f, 0.0f, 0.0f), tint_tmp);
-  res = int3(tint_tmp);
-  tint_tmp_1;
-)"));
+  EXPECT_EQ(gen.result(),
+            R"(float3 tint_frexp(float3 param_0, inout int3 param_1) {
+  float3 float_exp;
+  float3 significand = frexp(param_0, float_exp);
+  param_1 = int3(float_exp);
+  return significand;
+}
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  int3 res = int3(0, 0, 0);
+  tint_frexp(float3(0.0f, 0.0f, 0.0f), res);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, IsNormal_Scalar) {
@@ -358,11 +376,19 @@
   GeneratorImpl& gen = SanitizeAndBuild();
 
   ASSERT_TRUE(gen.Generate()) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr(R"(
-  uint tint_isnormal_exponent = asuint(val) & 0x7f80000;
-  uint tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
-  (tint_isnormal_clamped == tint_isnormal_exponent);
-)"));
+  EXPECT_EQ(gen.result(), R"(bool tint_isNormal(float param_0) {
+  uint exponent = asuint(param_0) & 0x7f80000;
+  uint clamped = clamp(exponent, 0x0080000, 0x7f00000);
+  return clamped == exponent;
+}
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  float val = 0.0f;
+  tint_isNormal(val);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, IsNormal_Vector) {
@@ -373,11 +399,19 @@
   GeneratorImpl& gen = SanitizeAndBuild();
 
   ASSERT_TRUE(gen.Generate()) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr(R"(
-  uint3 tint_isnormal_exponent = asuint(val) & 0x7f80000;
-  uint3 tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
-  (tint_isnormal_clamped == tint_isnormal_exponent);
-)"));
+  EXPECT_EQ(gen.result(), R"(bool3 tint_isNormal(float3 param_0) {
+  uint3 exponent = asuint(param_0) & 0x7f80000;
+  uint3 clamped = clamp(exponent, 0x0080000, 0x7f00000);
+  return clamped == exponent;
+}
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  float3 val = float3(0.0f, 0.0f, 0.0f);
+  tint_isNormal(val);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Snorm) {
@@ -386,13 +420,20 @@
   WrapInFunction(call);
   GeneratorImpl& gen = Build();
 
-  gen.increment_indent();
-  std::stringstream out;
-  ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr("int4 tint_tmp = int4(round(clamp(p1, "
-                                      "-1.0, 1.0) * 127.0)) & 0xff;"));
-  EXPECT_THAT(out.str(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 8 | "
-                                   "tint_tmp.z << 16 | tint_tmp.w << 24)"));
+  ASSERT_TRUE(gen.Generate()) << gen.error();
+  EXPECT_EQ(gen.result(), R"(uint tint_pack4x8snorm(float4 param_0) {
+  int4 i = int4(round(clamp(param_0, -1.0, 1.0) * 127.0)) & 0xff;
+  return asuint(i.x | i.y << 8 | i.z << 16 | i.w << 24);
+}
+
+static float4 p1 = float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  tint_pack4x8snorm(p1);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Unorm) {
@@ -401,13 +442,20 @@
   WrapInFunction(call);
   GeneratorImpl& gen = Build();
 
-  gen.increment_indent();
-  std::stringstream out;
-  ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr("uint4 tint_tmp = uint4(round(clamp(p1, "
-                                      "0.0, 1.0) * 255.0));"));
-  EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 8 | "
-                                   "tint_tmp.z << 16 | tint_tmp.w << 24)"));
+  ASSERT_TRUE(gen.Generate()) << gen.error();
+  EXPECT_EQ(gen.result(), R"(uint tint_pack4x8unorm(float4 param_0) {
+  uint4 i = uint4(round(clamp(param_0, 0.0, 1.0) * 255.0));
+  return (i.x | i.y << 8 | i.z << 16 | i.w << 24);
+}
+
+static float4 p1 = float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  tint_pack4x8unorm(p1);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Snorm) {
@@ -416,12 +464,20 @@
   WrapInFunction(call);
   GeneratorImpl& gen = Build();
 
-  gen.increment_indent();
-  std::stringstream out;
-  ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr("int2 tint_tmp = int2(round(clamp(p1, "
-                                      "-1.0, 1.0) * 32767.0)) & 0xffff;"));
-  EXPECT_THAT(out.str(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 16)"));
+  ASSERT_TRUE(gen.Generate()) << gen.error();
+  EXPECT_EQ(gen.result(), R"(uint tint_pack2x16snorm(float2 param_0) {
+  int2 i = int2(round(clamp(param_0, -1.0, 1.0) * 32767.0)) & 0xffff;
+  return asuint(i.x | i.y << 16);
+}
+
+static float2 p1 = float2(0.0f, 0.0f);
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  tint_pack2x16snorm(p1);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Unorm) {
@@ -430,12 +486,20 @@
   WrapInFunction(call);
   GeneratorImpl& gen = Build();
 
-  gen.increment_indent();
-  std::stringstream out;
-  ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr("uint2 tint_tmp = uint2(round(clamp(p1, "
-                                      "0.0, 1.0) * 65535.0));"));
-  EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)"));
+  ASSERT_TRUE(gen.Generate()) << gen.error();
+  EXPECT_EQ(gen.result(), R"(uint tint_pack2x16unorm(float2 param_0) {
+  uint2 i = uint2(round(clamp(param_0, 0.0, 1.0) * 65535.0));
+  return (i.x | i.y << 16);
+}
+
+static float2 p1 = float2(0.0f, 0.0f);
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  tint_pack2x16unorm(p1);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Float) {
@@ -444,11 +508,20 @@
   WrapInFunction(call);
   GeneratorImpl& gen = Build();
 
-  gen.increment_indent();
-  std::stringstream out;
-  ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr("uint2 tint_tmp = f32tof16(p1);"));
-  EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)"));
+  ASSERT_TRUE(gen.Generate()) << gen.error();
+  EXPECT_EQ(gen.result(), R"(uint tint_pack2x16float(float2 param_0) {
+  uint2 i = f32tof16(param_0);
+  return i.x | (i.y << 16);
+}
+
+static float2 p1 = float2(0.0f, 0.0f);
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  tint_pack2x16float(p1);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack4x8Snorm) {
@@ -457,15 +530,21 @@
   WrapInFunction(call);
   GeneratorImpl& gen = Build();
 
-  gen.increment_indent();
-  std::stringstream out;
-  ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr("int tint_tmp_1 = int(p1);"));
-  EXPECT_THAT(gen.result(),
-              HasSubstr("int4 tint_tmp = int4(tint_tmp_1 << 24, tint_tmp_1 "
-                        "<< 16, tint_tmp_1 << 8, tint_tmp_1) >> 24;"));
-  EXPECT_THAT(out.str(),
-              HasSubstr("clamp(float4(tint_tmp) / 127.0, -1.0, 1.0)"));
+  ASSERT_TRUE(gen.Generate()) << gen.error();
+  EXPECT_EQ(gen.result(), R"(float4 tint_unpack4x8snorm(uint param_0) {
+  int j = int(param_0);
+  int4 i = int4(j << 24, j << 16, j << 8, j) >> 24;
+  return clamp(float4(i) / 127.0, -1.0, 1.0);
+}
+
+static uint p1 = 0u;
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  tint_unpack4x8snorm(p1);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack4x8Unorm) {
@@ -474,15 +553,21 @@
   WrapInFunction(call);
   GeneratorImpl& gen = Build();
 
-  gen.increment_indent();
-  std::stringstream out;
-  ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr("uint tint_tmp_1 = p1;"));
-  EXPECT_THAT(
-      gen.result(),
-      HasSubstr("uint4 tint_tmp = uint4(tint_tmp_1 & 0xff, (tint_tmp_1 >> "
-                "8) & 0xff, (tint_tmp_1 >> 16) & 0xff, tint_tmp_1 >> 24);"));
-  EXPECT_THAT(out.str(), HasSubstr("float4(tint_tmp) / 255.0"));
+  ASSERT_TRUE(gen.Generate()) << gen.error();
+  EXPECT_EQ(gen.result(), R"(float4 tint_unpack4x8unorm(uint param_0) {
+  uint j = param_0;
+  uint4 i = uint4(j & 0xff, (j >> 8) & 0xff, (j >> 16) & 0xff, j >> 24);
+  return float4(i) / 255.0;
+}
+
+static uint p1 = 0u;
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  tint_unpack4x8unorm(p1);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Snorm) {
@@ -491,15 +576,21 @@
   WrapInFunction(call);
   GeneratorImpl& gen = Build();
 
-  gen.increment_indent();
-  std::stringstream out;
-  ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr("int tint_tmp_1 = int(p1);"));
-  EXPECT_THAT(
-      gen.result(),
-      HasSubstr("int2 tint_tmp = int2(tint_tmp_1 << 16, tint_tmp_1) >> 16;"));
-  EXPECT_THAT(out.str(),
-              HasSubstr("clamp(float2(tint_tmp) / 32767.0, -1.0, 1.0)"));
+  ASSERT_TRUE(gen.Generate()) << gen.error();
+  EXPECT_EQ(gen.result(), R"(float2 tint_unpack2x16snorm(uint param_0) {
+  int j = int(param_0);
+  int2 i = int2(j << 16, j) >> 16;
+  return clamp(float2(i) / 32767.0, -1.0, 1.0);
+}
+
+static uint p1 = 0u;
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  tint_unpack2x16snorm(p1);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Unorm) {
@@ -508,14 +599,21 @@
   WrapInFunction(call);
   GeneratorImpl& gen = Build();
 
-  gen.increment_indent();
-  std::stringstream out;
-  ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr("uint tint_tmp_1 = p1;"));
-  EXPECT_THAT(gen.result(),
-              HasSubstr("uint2 tint_tmp = uint2(tint_tmp_1 & 0xffff, "
-                        "tint_tmp_1 >> 16);"));
-  EXPECT_THAT(out.str(), HasSubstr("float2(tint_tmp) / 65535.0"));
+  ASSERT_TRUE(gen.Generate()) << gen.error();
+  EXPECT_EQ(gen.result(), R"(float2 tint_unpack2x16unorm(uint param_0) {
+  uint j = param_0;
+  uint2 i = uint2(j & 0xffff, j >> 16);
+  return float2(i) / 65535.0;
+}
+
+static uint p1 = 0u;
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  tint_unpack2x16unorm(p1);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Float) {
@@ -524,12 +622,20 @@
   WrapInFunction(call);
   GeneratorImpl& gen = Build();
 
-  gen.increment_indent();
-  std::stringstream out;
-  ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
-  EXPECT_THAT(gen.result(), HasSubstr("uint tint_tmp = p1;"));
-  EXPECT_THAT(out.str(),
-              HasSubstr("f16tof32(uint2(tint_tmp & 0xffff, tint_tmp >> 16))"));
+  ASSERT_TRUE(gen.Generate()) << gen.error();
+  EXPECT_EQ(gen.result(), R"(float2 tint_unpack2x16float(uint param_0) {
+  uint i = param_0;
+  return f16tof32(uint2(i & 0xffff, i >> 16));
+}
+
+static uint p1 = 0u;
+
+[numthreads(1, 1, 1)]
+void test_function() {
+  tint_unpack2x16float(p1);
+  return;
+}
+)");
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, StorageBarrier) {
diff --git a/src/writer/text_generator.h b/src/writer/text_generator.h
index 1e75a52..90e92b6 100644
--- a/src/writer/text_generator.h
+++ b/src/writer/text_generator.h
@@ -209,7 +209,7 @@
   /// @param buffer the TextBuffer to write the line to
   /// @returns a new LineWriter, used for buffering and writing a line to
   /// the end of `buffer`.
-  LineWriter line(TextBuffer* buffer) { return LineWriter(buffer); }
+  static LineWriter line(TextBuffer* buffer) { return LineWriter(buffer); }
 
   /// The program
   Program const* const program_;
diff --git a/test/intrinsics/frexp.wgsl.expected.hlsl b/test/intrinsics/frexp.wgsl.expected.hlsl
index dce5489..e35149a 100644
--- a/test/intrinsics/frexp.wgsl.expected.hlsl
+++ b/test/intrinsics/frexp.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float tint_frexp(float param_0, inout int param_1) {
+  float float_exp;
+  float significand = frexp(param_0, float_exp);
+  param_1 = int(float_exp);
+  return significand;
+}
+
 [numthreads(1, 1, 1)]
 void main() {
   int exponent = 0;
-  float tint_tmp;
-  float tint_tmp_1 = frexp(1.230000019f, tint_tmp);
-  exponent = int(tint_tmp);
-  const float significand = tint_tmp_1;
+  const float significand = tint_frexp(1.230000019f, exponent);
   return;
 }
diff --git a/test/intrinsics/gen/frexp/013caa.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/013caa.wgsl.expected.hlsl
index 4e6691c..9e077f5 100644
--- a/test/intrinsics/gen/frexp/013caa.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/013caa.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float4 tint_frexp(float4 param_0, inout int4 param_1) {
+  float4 float_exp;
+  float4 significand = frexp(param_0, float_exp);
+  param_1 = int4(float_exp);
+  return significand;
+}
+
 void frexp_013caa() {
   int4 arg_1 = int4(0, 0, 0, 0);
-  float4 tint_tmp;
-  float4 tint_tmp_1 = frexp(float4(0.0f, 0.0f, 0.0f, 0.0f), tint_tmp);
-  arg_1 = int4(tint_tmp);
-  float4 res = tint_tmp_1;
+  float4 res = tint_frexp(float4(0.0f, 0.0f, 0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/0da285.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/0da285.wgsl.expected.hlsl
index b841839..06c20aa 100644
--- a/test/intrinsics/gen/frexp/0da285.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/0da285.wgsl.expected.hlsl
@@ -1,10 +1,14 @@
+float tint_frexp(float param_0, inout int param_1) {
+  float float_exp;
+  float significand = frexp(param_0, float_exp);
+  param_1 = int(float_exp);
+  return significand;
+}
+
 groupshared int arg_1;
 
 void frexp_0da285() {
-  float tint_tmp;
-  float tint_tmp_1 = frexp(1.0f, tint_tmp);
-  arg_1 = int(tint_tmp);
-  float res = tint_tmp_1;
+  float res = tint_frexp(1.0f, arg_1);
 }
 
 struct tint_symbol_1 {
diff --git a/test/intrinsics/gen/frexp/15edf3.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/15edf3.wgsl.expected.hlsl
index b972bbc..cd65967 100644
--- a/test/intrinsics/gen/frexp/15edf3.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/15edf3.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float2 tint_frexp(float2 param_0, inout int2 param_1) {
+  float2 float_exp;
+  float2 significand = frexp(param_0, float_exp);
+  param_1 = int2(float_exp);
+  return significand;
+}
+
 void frexp_15edf3() {
   int2 arg_1 = int2(0, 0);
-  float2 tint_tmp;
-  float2 tint_tmp_1 = frexp(float2(0.0f, 0.0f), tint_tmp);
-  arg_1 = int2(tint_tmp);
-  float2 res = tint_tmp_1;
+  float2 res = tint_frexp(float2(0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/19ab15.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/19ab15.wgsl.expected.hlsl
index 84d1a23..e35f419 100644
--- a/test/intrinsics/gen/frexp/19ab15.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/19ab15.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float4 tint_frexp(float4 param_0, inout int4 param_1) {
+  float4 float_exp;
+  float4 significand = frexp(param_0, float_exp);
+  param_1 = int4(float_exp);
+  return significand;
+}
+
 void frexp_19ab15() {
   int4 arg_1 = int4(0, 0, 0, 0);
-  float4 tint_tmp;
-  float4 tint_tmp_1 = frexp(float4(0.0f, 0.0f, 0.0f, 0.0f), tint_tmp);
-  arg_1 = int4(tint_tmp);
-  float4 res = tint_tmp_1;
+  float4 res = tint_frexp(float4(0.0f, 0.0f, 0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/2052e9.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/2052e9.wgsl.expected.hlsl
index 21325b5..bddd0e2 100644
--- a/test/intrinsics/gen/frexp/2052e9.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/2052e9.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float4 tint_frexp(float4 param_0, inout int4 param_1) {
+  float4 float_exp;
+  float4 significand = frexp(param_0, float_exp);
+  param_1 = int4(float_exp);
+  return significand;
+}
+
 void frexp_2052e9() {
   int4 arg_1 = int4(0, 0, 0, 0);
-  float4 tint_tmp;
-  float4 tint_tmp_1 = frexp(float4(0.0f, 0.0f, 0.0f, 0.0f), tint_tmp);
-  arg_1 = int4(tint_tmp);
-  float4 res = tint_tmp_1;
+  float4 res = tint_frexp(float4(0.0f, 0.0f, 0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/40fc9b.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/40fc9b.wgsl.expected.hlsl
index f7f2ecd..c7452b4 100644
--- a/test/intrinsics/gen/frexp/40fc9b.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/40fc9b.wgsl.expected.hlsl
@@ -1,10 +1,14 @@
+float3 tint_frexp(float3 param_0, inout int3 param_1) {
+  float3 float_exp;
+  float3 significand = frexp(param_0, float_exp);
+  param_1 = int3(float_exp);
+  return significand;
+}
+
 groupshared int3 arg_1;
 
 void frexp_40fc9b() {
-  float3 tint_tmp;
-  float3 tint_tmp_1 = frexp(float3(0.0f, 0.0f, 0.0f), tint_tmp);
-  arg_1 = int3(tint_tmp);
-  float3 res = tint_tmp_1;
+  float3 res = tint_frexp(float3(0.0f, 0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol_1 {
diff --git a/test/intrinsics/gen/frexp/41e931.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/41e931.wgsl.expected.hlsl
index e8abbac..080b770 100644
--- a/test/intrinsics/gen/frexp/41e931.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/41e931.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float tint_frexp(float param_0, inout int param_1) {
+  float float_exp;
+  float significand = frexp(param_0, float_exp);
+  param_1 = int(float_exp);
+  return significand;
+}
+
 void frexp_41e931() {
   int arg_1 = 0;
-  float tint_tmp;
-  float tint_tmp_1 = frexp(1.0f, tint_tmp);
-  arg_1 = int(tint_tmp);
-  float res = tint_tmp_1;
+  float res = tint_frexp(1.0f, arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/481e59.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/481e59.wgsl.expected.hlsl
index 1c44a01..668bc6e 100644
--- a/test/intrinsics/gen/frexp/481e59.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/481e59.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float tint_frexp(float param_0, inout int param_1) {
+  float float_exp;
+  float significand = frexp(param_0, float_exp);
+  param_1 = int(float_exp);
+  return significand;
+}
+
 void frexp_481e59() {
   int arg_1 = 0;
-  float tint_tmp;
-  float tint_tmp_1 = frexp(1.0f, tint_tmp);
-  arg_1 = int(tint_tmp);
-  float res = tint_tmp_1;
+  float res = tint_frexp(1.0f, arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/5a141e.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/5a141e.wgsl.expected.hlsl
index 04f9a19..53500da 100644
--- a/test/intrinsics/gen/frexp/5a141e.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/5a141e.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float3 tint_frexp(float3 param_0, inout int3 param_1) {
+  float3 float_exp;
+  float3 significand = frexp(param_0, float_exp);
+  param_1 = int3(float_exp);
+  return significand;
+}
+
 void frexp_5a141e() {
   int3 arg_1 = int3(0, 0, 0);
-  float3 tint_tmp;
-  float3 tint_tmp_1 = frexp(float3(0.0f, 0.0f, 0.0f), tint_tmp);
-  arg_1 = int3(tint_tmp);
-  float3 res = tint_tmp_1;
+  float3 res = tint_frexp(float3(0.0f, 0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/6d0058.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/6d0058.wgsl.expected.hlsl
index 2692f2a..10803d1 100644
--- a/test/intrinsics/gen/frexp/6d0058.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/6d0058.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float3 tint_frexp(float3 param_0, inout int3 param_1) {
+  float3 float_exp;
+  float3 significand = frexp(param_0, float_exp);
+  param_1 = int3(float_exp);
+  return significand;
+}
+
 void frexp_6d0058() {
   int3 arg_1 = int3(0, 0, 0);
-  float3 tint_tmp;
-  float3 tint_tmp_1 = frexp(float3(0.0f, 0.0f, 0.0f), tint_tmp);
-  arg_1 = int3(tint_tmp);
-  float3 res = tint_tmp_1;
+  float3 res = tint_frexp(float3(0.0f, 0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/6efa09.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/6efa09.wgsl.expected.hlsl
index 81162a1..7960528 100644
--- a/test/intrinsics/gen/frexp/6efa09.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/6efa09.wgsl.expected.hlsl
@@ -1,10 +1,14 @@
+float3 tint_frexp(float3 param_0, inout int3 param_1) {
+  float3 float_exp;
+  float3 significand = frexp(param_0, float_exp);
+  param_1 = int3(float_exp);
+  return significand;
+}
+
 static int3 arg_1 = int3(0, 0, 0);
 
 void frexp_6efa09() {
-  float3 tint_tmp;
-  float3 tint_tmp_1 = frexp(float3(0.0f, 0.0f, 0.0f), tint_tmp);
-  arg_1 = int3(tint_tmp);
-  float3 res = tint_tmp_1;
+  float3 res = tint_frexp(float3(0.0f, 0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/a2a617.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/a2a617.wgsl.expected.hlsl
index d6c787d..68180a7 100644
--- a/test/intrinsics/gen/frexp/a2a617.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/a2a617.wgsl.expected.hlsl
@@ -1,10 +1,14 @@
+float tint_frexp(float param_0, inout int param_1) {
+  float float_exp;
+  float significand = frexp(param_0, float_exp);
+  param_1 = int(float_exp);
+  return significand;
+}
+
 static int arg_1 = 0;
 
 void frexp_a2a617() {
-  float tint_tmp;
-  float tint_tmp_1 = frexp(1.0f, tint_tmp);
-  arg_1 = int(tint_tmp);
-  float res = tint_tmp_1;
+  float res = tint_frexp(1.0f, arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/a3f940.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/a3f940.wgsl.expected.hlsl
index 5f1a007..f540a08 100644
--- a/test/intrinsics/gen/frexp/a3f940.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/a3f940.wgsl.expected.hlsl
@@ -1,10 +1,14 @@
+float2 tint_frexp(float2 param_0, inout int2 param_1) {
+  float2 float_exp;
+  float2 significand = frexp(param_0, float_exp);
+  param_1 = int2(float_exp);
+  return significand;
+}
+
 groupshared int2 arg_1;
 
 void frexp_a3f940() {
-  float2 tint_tmp;
-  float2 tint_tmp_1 = frexp(float2(0.0f, 0.0f), tint_tmp);
-  arg_1 = int2(tint_tmp);
-  float2 res = tint_tmp_1;
+  float2 res = tint_frexp(float2(0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol_1 {
diff --git a/test/intrinsics/gen/frexp/a951b5.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/a951b5.wgsl.expected.hlsl
index ae632ce..f88516c 100644
--- a/test/intrinsics/gen/frexp/a951b5.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/a951b5.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float2 tint_frexp(float2 param_0, inout int2 param_1) {
+  float2 float_exp;
+  float2 significand = frexp(param_0, float_exp);
+  param_1 = int2(float_exp);
+  return significand;
+}
+
 void frexp_a951b5() {
   int2 arg_1 = int2(0, 0);
-  float2 tint_tmp;
-  float2 tint_tmp_1 = frexp(float2(0.0f, 0.0f), tint_tmp);
-  arg_1 = int2(tint_tmp);
-  float2 res = tint_tmp_1;
+  float2 res = tint_frexp(float2(0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/b45525.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/b45525.wgsl.expected.hlsl
index e0b30ab..f9e83b8 100644
--- a/test/intrinsics/gen/frexp/b45525.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/b45525.wgsl.expected.hlsl
@@ -1,10 +1,14 @@
+float4 tint_frexp(float4 param_0, inout int4 param_1) {
+  float4 float_exp;
+  float4 significand = frexp(param_0, float_exp);
+  param_1 = int4(float_exp);
+  return significand;
+}
+
 static int4 arg_1 = int4(0, 0, 0, 0);
 
 void frexp_b45525() {
-  float4 tint_tmp;
-  float4 tint_tmp_1 = frexp(float4(0.0f, 0.0f, 0.0f, 0.0f), tint_tmp);
-  arg_1 = int4(tint_tmp);
-  float4 res = tint_tmp_1;
+  float4 res = tint_frexp(float4(0.0f, 0.0f, 0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/b87f4e.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/b87f4e.wgsl.expected.hlsl
index a1abbeb..ddb2f5f 100644
--- a/test/intrinsics/gen/frexp/b87f4e.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/b87f4e.wgsl.expected.hlsl
@@ -1,10 +1,14 @@
+float4 tint_frexp(float4 param_0, inout int4 param_1) {
+  float4 float_exp;
+  float4 significand = frexp(param_0, float_exp);
+  param_1 = int4(float_exp);
+  return significand;
+}
+
 groupshared int4 arg_1;
 
 void frexp_b87f4e() {
-  float4 tint_tmp;
-  float4 tint_tmp_1 = frexp(float4(0.0f, 0.0f, 0.0f, 0.0f), tint_tmp);
-  arg_1 = int4(tint_tmp);
-  float4 res = tint_tmp_1;
+  float4 res = tint_frexp(float4(0.0f, 0.0f, 0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol_1 {
diff --git a/test/intrinsics/gen/frexp/b9e4de.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/b9e4de.wgsl.expected.hlsl
index 64fa0e1..1b06a32 100644
--- a/test/intrinsics/gen/frexp/b9e4de.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/b9e4de.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float3 tint_frexp(float3 param_0, inout int3 param_1) {
+  float3 float_exp;
+  float3 significand = frexp(param_0, float_exp);
+  param_1 = int3(float_exp);
+  return significand;
+}
+
 void frexp_b9e4de() {
   int3 arg_1 = int3(0, 0, 0);
-  float3 tint_tmp;
-  float3 tint_tmp_1 = frexp(float3(0.0f, 0.0f, 0.0f), tint_tmp);
-  arg_1 = int3(tint_tmp);
-  float3 res = tint_tmp_1;
+  float3 res = tint_frexp(float3(0.0f, 0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/c084e3.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/c084e3.wgsl.expected.hlsl
index 803ea55..7db21c8 100644
--- a/test/intrinsics/gen/frexp/c084e3.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/c084e3.wgsl.expected.hlsl
@@ -1,10 +1,14 @@
+float2 tint_frexp(float2 param_0, inout int2 param_1) {
+  float2 float_exp;
+  float2 significand = frexp(param_0, float_exp);
+  param_1 = int2(float_exp);
+  return significand;
+}
+
 static int2 arg_1 = int2(0, 0);
 
 void frexp_c084e3() {
-  float2 tint_tmp;
-  float2 tint_tmp_1 = frexp(float2(0.0f, 0.0f), tint_tmp);
-  arg_1 = int2(tint_tmp);
-  float2 res = tint_tmp_1;
+  float2 res = tint_frexp(float2(0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/d06c2c.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/d06c2c.wgsl.expected.hlsl
index 608f5ce..b806072 100644
--- a/test/intrinsics/gen/frexp/d06c2c.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/d06c2c.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float2 tint_frexp(float2 param_0, inout int2 param_1) {
+  float2 float_exp;
+  float2 significand = frexp(param_0, float_exp);
+  param_1 = int2(float_exp);
+  return significand;
+}
+
 void frexp_d06c2c() {
   int2 arg_1 = int2(0, 0);
-  float2 tint_tmp;
-  float2 tint_tmp_1 = frexp(float2(0.0f, 0.0f), tint_tmp);
-  arg_1 = int2(tint_tmp);
-  float2 res = tint_tmp_1;
+  float2 res = tint_frexp(float2(0.0f, 0.0f), arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/frexp/e061dd.wgsl.expected.hlsl b/test/intrinsics/gen/frexp/e061dd.wgsl.expected.hlsl
index 6d6d7a8..8aa4d20 100644
--- a/test/intrinsics/gen/frexp/e061dd.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/frexp/e061dd.wgsl.expected.hlsl
@@ -1,9 +1,13 @@
+float tint_frexp(float param_0, inout int param_1) {
+  float float_exp;
+  float significand = frexp(param_0, float_exp);
+  param_1 = int(float_exp);
+  return significand;
+}
+
 void frexp_e061dd() {
   int arg_1 = 0;
-  float tint_tmp;
-  float tint_tmp_1 = frexp(1.0f, tint_tmp);
-  arg_1 = int(tint_tmp);
-  float res = tint_tmp_1;
+  float res = tint_frexp(1.0f, arg_1);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/isNormal/863dcd.wgsl.expected.hlsl b/test/intrinsics/gen/isNormal/863dcd.wgsl.expected.hlsl
index ff32e3b..cd32654 100644
--- a/test/intrinsics/gen/isNormal/863dcd.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/isNormal/863dcd.wgsl.expected.hlsl
@@ -1,7 +1,11 @@
+bool4 tint_isNormal(float4 param_0) {
+  uint4 exponent = asuint(param_0) & 0x7f80000;
+  uint4 clamped = clamp(exponent, 0x0080000, 0x7f00000);
+  return clamped == exponent;
+}
+
 void isNormal_863dcd() {
-  uint4 tint_isnormal_exponent = asuint(float4(0.0f, 0.0f, 0.0f, 0.0f)) & 0x7f80000;
-  uint4 tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
-  bool4 res = (tint_isnormal_clamped == tint_isnormal_exponent);
+  bool4 res = tint_isNormal(float4(0.0f, 0.0f, 0.0f, 0.0f));
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/isNormal/b00ab1.wgsl.expected.hlsl b/test/intrinsics/gen/isNormal/b00ab1.wgsl.expected.hlsl
index 7a5f623..dbf1580 100644
--- a/test/intrinsics/gen/isNormal/b00ab1.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/isNormal/b00ab1.wgsl.expected.hlsl
@@ -1,7 +1,11 @@
+bool2 tint_isNormal(float2 param_0) {
+  uint2 exponent = asuint(param_0) & 0x7f80000;
+  uint2 clamped = clamp(exponent, 0x0080000, 0x7f00000);
+  return clamped == exponent;
+}
+
 void isNormal_b00ab1() {
-  uint2 tint_isnormal_exponent = asuint(float2(0.0f, 0.0f)) & 0x7f80000;
-  uint2 tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
-  bool2 res = (tint_isnormal_clamped == tint_isnormal_exponent);
+  bool2 res = tint_isNormal(float2(0.0f, 0.0f));
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/isNormal/c286b7.wgsl.expected.hlsl b/test/intrinsics/gen/isNormal/c286b7.wgsl.expected.hlsl
index bfc5d8b..8f3ddd5 100644
--- a/test/intrinsics/gen/isNormal/c286b7.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/isNormal/c286b7.wgsl.expected.hlsl
@@ -1,7 +1,11 @@
+bool3 tint_isNormal(float3 param_0) {
+  uint3 exponent = asuint(param_0) & 0x7f80000;
+  uint3 clamped = clamp(exponent, 0x0080000, 0x7f00000);
+  return clamped == exponent;
+}
+
 void isNormal_c286b7() {
-  uint3 tint_isnormal_exponent = asuint(float3(0.0f, 0.0f, 0.0f)) & 0x7f80000;
-  uint3 tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
-  bool3 res = (tint_isnormal_clamped == tint_isnormal_exponent);
+  bool3 res = tint_isNormal(float3(0.0f, 0.0f, 0.0f));
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/isNormal/c6e880.wgsl.expected.hlsl b/test/intrinsics/gen/isNormal/c6e880.wgsl.expected.hlsl
index da6faf7..475e918 100644
--- a/test/intrinsics/gen/isNormal/c6e880.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/isNormal/c6e880.wgsl.expected.hlsl
@@ -1,7 +1,11 @@
+bool tint_isNormal(float param_0) {
+  uint exponent = asuint(param_0) & 0x7f80000;
+  uint clamped = clamp(exponent, 0x0080000, 0x7f00000);
+  return clamped == exponent;
+}
+
 void isNormal_c6e880() {
-  uint tint_isnormal_exponent = asuint(1.0f) & 0x7f80000;
-  uint tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
-  bool res = (tint_isnormal_clamped == tint_isnormal_exponent);
+  bool res = tint_isNormal(1.0f);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/pack2x16float/0e97b3.wgsl.expected.hlsl b/test/intrinsics/gen/pack2x16float/0e97b3.wgsl.expected.hlsl
index c06e032..f18593b 100644
--- a/test/intrinsics/gen/pack2x16float/0e97b3.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/pack2x16float/0e97b3.wgsl.expected.hlsl
@@ -1,6 +1,10 @@
+uint tint_pack2x16float(float2 param_0) {
+  uint2 i = f32tof16(param_0);
+  return i.x | (i.y << 16);
+}
+
 void pack2x16float_0e97b3() {
-  uint2 tint_tmp = f32tof16(float2(0.0f, 0.0f));
-  uint res = (tint_tmp.x | tint_tmp.y << 16);
+  uint res = tint_pack2x16float(float2(0.0f, 0.0f));
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/pack2x16snorm/6c169b.wgsl.expected.hlsl b/test/intrinsics/gen/pack2x16snorm/6c169b.wgsl.expected.hlsl
index cccbc2d..8a50c57 100644
--- a/test/intrinsics/gen/pack2x16snorm/6c169b.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/pack2x16snorm/6c169b.wgsl.expected.hlsl
@@ -1,6 +1,10 @@
+uint tint_pack2x16snorm(float2 param_0) {
+  int2 i = int2(round(clamp(param_0, -1.0, 1.0) * 32767.0)) & 0xffff;
+  return asuint(i.x | i.y << 16);
+}
+
 void pack2x16snorm_6c169b() {
-  int2 tint_tmp = int2(round(clamp(float2(0.0f, 0.0f), -1.0, 1.0) * 32767.0)) & 0xffff;
-  uint res = asuint(tint_tmp.x | tint_tmp.y << 16);
+  uint res = tint_pack2x16snorm(float2(0.0f, 0.0f));
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/pack2x16unorm/0f08e4.wgsl.expected.hlsl b/test/intrinsics/gen/pack2x16unorm/0f08e4.wgsl.expected.hlsl
index 3495457..3426817 100644
--- a/test/intrinsics/gen/pack2x16unorm/0f08e4.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/pack2x16unorm/0f08e4.wgsl.expected.hlsl
@@ -1,6 +1,10 @@
+uint tint_pack2x16unorm(float2 param_0) {
+  uint2 i = uint2(round(clamp(param_0, 0.0, 1.0) * 65535.0));
+  return (i.x | i.y << 16);
+}
+
 void pack2x16unorm_0f08e4() {
-  uint2 tint_tmp = uint2(round(clamp(float2(0.0f, 0.0f), 0.0, 1.0) * 65535.0));
-  uint res = (tint_tmp.x | tint_tmp.y << 16);
+  uint res = tint_pack2x16unorm(float2(0.0f, 0.0f));
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/pack4x8snorm/4d22e7.wgsl.expected.hlsl b/test/intrinsics/gen/pack4x8snorm/4d22e7.wgsl.expected.hlsl
index 93c5fcf..8d96abf 100644
--- a/test/intrinsics/gen/pack4x8snorm/4d22e7.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/pack4x8snorm/4d22e7.wgsl.expected.hlsl
@@ -1,6 +1,10 @@
+uint tint_pack4x8snorm(float4 param_0) {
+  int4 i = int4(round(clamp(param_0, -1.0, 1.0) * 127.0)) & 0xff;
+  return asuint(i.x | i.y << 8 | i.z << 16 | i.w << 24);
+}
+
 void pack4x8snorm_4d22e7() {
-  int4 tint_tmp = int4(round(clamp(float4(0.0f, 0.0f, 0.0f, 0.0f), -1.0, 1.0) * 127.0)) & 0xff;
-  uint res = asuint(tint_tmp.x | tint_tmp.y << 8 | tint_tmp.z << 16 | tint_tmp.w << 24);
+  uint res = tint_pack4x8snorm(float4(0.0f, 0.0f, 0.0f, 0.0f));
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/pack4x8unorm/95c456.wgsl.expected.hlsl b/test/intrinsics/gen/pack4x8unorm/95c456.wgsl.expected.hlsl
index f22557c..3ed399c 100644
--- a/test/intrinsics/gen/pack4x8unorm/95c456.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/pack4x8unorm/95c456.wgsl.expected.hlsl
@@ -1,6 +1,10 @@
+uint tint_pack4x8unorm(float4 param_0) {
+  uint4 i = uint4(round(clamp(param_0, 0.0, 1.0) * 255.0));
+  return (i.x | i.y << 8 | i.z << 16 | i.w << 24);
+}
+
 void pack4x8unorm_95c456() {
-  uint4 tint_tmp = uint4(round(clamp(float4(0.0f, 0.0f, 0.0f, 0.0f), 0.0, 1.0) * 255.0));
-  uint res = (tint_tmp.x | tint_tmp.y << 8 | tint_tmp.z << 16 | tint_tmp.w << 24);
+  uint res = tint_pack4x8unorm(float4(0.0f, 0.0f, 0.0f, 0.0f));
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/unpack2x16float/32a5cf.wgsl.expected.hlsl b/test/intrinsics/gen/unpack2x16float/32a5cf.wgsl.expected.hlsl
index 7107517..b828aaa 100644
--- a/test/intrinsics/gen/unpack2x16float/32a5cf.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/unpack2x16float/32a5cf.wgsl.expected.hlsl
@@ -1,6 +1,10 @@
+float2 tint_unpack2x16float(uint param_0) {
+  uint i = param_0;
+  return f16tof32(uint2(i & 0xffff, i >> 16));
+}
+
 void unpack2x16float_32a5cf() {
-  uint tint_tmp = 1u;
-  float2 res = f16tof32(uint2(tint_tmp & 0xffff, tint_tmp >> 16));
+  float2 res = tint_unpack2x16float(1u);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/unpack2x16snorm/b4aea6.wgsl.expected.hlsl b/test/intrinsics/gen/unpack2x16snorm/b4aea6.wgsl.expected.hlsl
index ad0d7b3..75ed01c 100644
--- a/test/intrinsics/gen/unpack2x16snorm/b4aea6.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/unpack2x16snorm/b4aea6.wgsl.expected.hlsl
@@ -1,7 +1,11 @@
+float2 tint_unpack2x16snorm(uint param_0) {
+  int j = int(param_0);
+  int2 i = int2(j << 16, j) >> 16;
+  return clamp(float2(i) / 32767.0, -1.0, 1.0);
+}
+
 void unpack2x16snorm_b4aea6() {
-  int tint_tmp_1 = int(1u);
-  int2 tint_tmp = int2(tint_tmp_1 << 16, tint_tmp_1) >> 16;
-  float2 res = clamp(float2(tint_tmp) / 32767.0, -1.0, 1.0);
+  float2 res = tint_unpack2x16snorm(1u);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/unpack2x16unorm/7699c0.wgsl.expected.hlsl b/test/intrinsics/gen/unpack2x16unorm/7699c0.wgsl.expected.hlsl
index 1afbba3..3481fbb 100644
--- a/test/intrinsics/gen/unpack2x16unorm/7699c0.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/unpack2x16unorm/7699c0.wgsl.expected.hlsl
@@ -1,7 +1,11 @@
+float2 tint_unpack2x16unorm(uint param_0) {
+  uint j = param_0;
+  uint2 i = uint2(j & 0xffff, j >> 16);
+  return float2(i) / 65535.0;
+}
+
 void unpack2x16unorm_7699c0() {
-  uint tint_tmp_1 = 1u;
-  uint2 tint_tmp = uint2(tint_tmp_1 & 0xffff, tint_tmp_1 >> 16);
-  float2 res = float2(tint_tmp) / 65535.0;
+  float2 res = tint_unpack2x16unorm(1u);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/unpack4x8snorm/523fb3.wgsl.expected.hlsl b/test/intrinsics/gen/unpack4x8snorm/523fb3.wgsl.expected.hlsl
index 721a798..849087d 100644
--- a/test/intrinsics/gen/unpack4x8snorm/523fb3.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/unpack4x8snorm/523fb3.wgsl.expected.hlsl
@@ -1,7 +1,11 @@
+float4 tint_unpack4x8snorm(uint param_0) {
+  int j = int(param_0);
+  int4 i = int4(j << 24, j << 16, j << 8, j) >> 24;
+  return clamp(float4(i) / 127.0, -1.0, 1.0);
+}
+
 void unpack4x8snorm_523fb3() {
-  int tint_tmp_1 = int(1u);
-  int4 tint_tmp = int4(tint_tmp_1 << 24, tint_tmp_1 << 16, tint_tmp_1 << 8, tint_tmp_1) >> 24;
-  float4 res = clamp(float4(tint_tmp) / 127.0, -1.0, 1.0);
+  float4 res = tint_unpack4x8snorm(1u);
 }
 
 struct tint_symbol {
diff --git a/test/intrinsics/gen/unpack4x8unorm/750c74.wgsl.expected.hlsl b/test/intrinsics/gen/unpack4x8unorm/750c74.wgsl.expected.hlsl
index e3a10fe..6e04842 100644
--- a/test/intrinsics/gen/unpack4x8unorm/750c74.wgsl.expected.hlsl
+++ b/test/intrinsics/gen/unpack4x8unorm/750c74.wgsl.expected.hlsl
@@ -1,7 +1,11 @@
+float4 tint_unpack4x8unorm(uint param_0) {
+  uint j = param_0;
+  uint4 i = uint4(j & 0xff, (j >> 8) & 0xff, (j >> 16) & 0xff, j >> 24);
+  return float4(i) / 255.0;
+}
+
 void unpack4x8unorm_750c74() {
-  uint tint_tmp_1 = 1u;
-  uint4 tint_tmp = uint4(tint_tmp_1 & 0xff, (tint_tmp_1 >> 8) & 0xff, (tint_tmp_1 >> 16) & 0xff, tint_tmp_1 >> 24);
-  float4 res = float4(tint_tmp) / 255.0;
+  float4 res = tint_unpack4x8unorm(1u);
 }
 
 struct tint_symbol {