diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 9870ccd6ea..3207ebbe07 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -825,6 +825,7 @@ libtint_source_set("libtint_reader_src") {
 
 libtint_source_set("libtint_spv_reader_src") {
   sources = [
+    "reader/spirv/attributes.h",
     "reader/spirv/construct.cc",
     "reader/spirv/construct.h",
     "reader/spirv/entry_point_info.cc",
@@ -916,6 +917,7 @@ libtint_source_set("libtint_spv_writer_src") {
   deps = [
     ":libtint_ast_src",
     ":libtint_base_src",
+    ":libtint_builtins_src",
     ":libtint_constant_src",
     ":libtint_program_src",
     ":libtint_sem_src",
@@ -981,6 +983,7 @@ libtint_source_set("libtint_msl_writer_src") {
   deps = [
     ":libtint_ast_src",
     ":libtint_base_src",
+    ":libtint_builtins_src",
     ":libtint_constant_src",
     ":libtint_program_src",
     ":libtint_sem_src",
@@ -1001,6 +1004,7 @@ libtint_source_set("libtint_hlsl_writer_src") {
   deps = [
     ":libtint_ast_src",
     ":libtint_base_src",
+    ":libtint_builtins_src",
     ":libtint_constant_src",
     ":libtint_program_src",
     ":libtint_sem_src",
@@ -1740,6 +1744,7 @@ if (tint_build_unittests) {
 
     deps = [
       ":libtint_base_src",
+      ":libtint_builtins_src",
       ":libtint_unittests_ast_helper",
       ":libtint_wgsl_reader_src",
     ]
@@ -1781,6 +1786,7 @@ if (tint_build_unittests) {
     ]
 
     deps = [
+      ":libtint_builtins_src",
       ":libtint_wgsl_writer_src",
       ":tint_unittests_ast_src",
     ]
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 2fe2161217..79f19a4a25 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -575,6 +575,7 @@ endif()
 
 if(${TINT_BUILD_SPV_READER})
   list(APPEND TINT_LIB_SRCS
+    reader/spirv/attributes.h
     reader/spirv/construct.h
     reader/spirv/construct.cc
     reader/spirv/entry_point_info.h
diff --git a/src/tint/ast/builtin_attribute.cc b/src/tint/ast/builtin_attribute.cc
index e3f9d7b44f..44231c07d8 100644
--- a/src/tint/ast/builtin_attribute.cc
+++ b/src/tint/ast/builtin_attribute.cc
@@ -25,8 +25,10 @@ namespace tint::ast {
 BuiltinAttribute::BuiltinAttribute(ProgramID pid,
                                    NodeID nid,
                                    const Source& src,
-                                   builtin::BuiltinValue b)
-    : Base(pid, nid, src), builtin(b) {}
+                                   const Expression* b)
+    : Base(pid, nid, src), builtin(b) {
+    TINT_ASSERT_PROGRAM_IDS_EQUAL(AST, b, program_id);
+}
 
 BuiltinAttribute::~BuiltinAttribute() = default;
 
@@ -37,7 +39,8 @@ std::string BuiltinAttribute::Name() const {
 const BuiltinAttribute* BuiltinAttribute::Clone(CloneContext* ctx) const {
     // Clone arguments outside of create() call to have deterministic ordering
     auto src = ctx->Clone(source);
-    return ctx->dst->create<BuiltinAttribute>(src, builtin);
+    auto b = ctx->Clone(builtin);
+    return ctx->dst->create<BuiltinAttribute>(src, b);
 }
 
 }  // namespace tint::ast
diff --git a/src/tint/ast/builtin_attribute.h b/src/tint/ast/builtin_attribute.h
index 6f9b1563ce..2ed6a2d577 100644
--- a/src/tint/ast/builtin_attribute.h
+++ b/src/tint/ast/builtin_attribute.h
@@ -18,7 +18,11 @@
 #include <string>
 
 #include "src/tint/ast/attribute.h"
-#include "src/tint/builtin/builtin_value.h"
+
+// Forward declarations
+namespace tint::ast {
+class Expression;
+}
 
 namespace tint::ast {
 
@@ -30,7 +34,7 @@ class BuiltinAttribute final : public Castable<BuiltinAttribute, Attribute> {
     /// @param nid the unique node identifier
     /// @param src the source of this node
     /// @param builtin the builtin value
-    BuiltinAttribute(ProgramID pid, NodeID nid, const Source& src, builtin::BuiltinValue builtin);
+    BuiltinAttribute(ProgramID pid, NodeID nid, const Source& src, const Expression* builtin);
     ~BuiltinAttribute() override;
 
     /// @returns the WGSL name for the attribute
@@ -43,7 +47,7 @@ class BuiltinAttribute final : public Castable<BuiltinAttribute, Attribute> {
     const BuiltinAttribute* Clone(CloneContext* ctx) const override;
 
     /// The builtin value
-    const builtin::BuiltinValue builtin;
+    const Expression* const builtin;
 };
 
 }  // namespace tint::ast
diff --git a/src/tint/ast/builtin_attribute_test.cc b/src/tint/ast/builtin_attribute_test.cc
index 3421e0fe20..00192b8e3b 100644
--- a/src/tint/ast/builtin_attribute_test.cc
+++ b/src/tint/ast/builtin_attribute_test.cc
@@ -12,7 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "gtest/gtest-spi.h"
+
 #include "src/tint/ast/test_helper.h"
+#include "src/tint/builtin/builtin_value.h"
 
 namespace tint::ast {
 namespace {
@@ -20,8 +23,27 @@ namespace {
 using BuiltinAttributeTest = TestHelper;
 
 TEST_F(BuiltinAttributeTest, Creation) {
-    auto* d = create<BuiltinAttribute>(builtin::BuiltinValue::kFragDepth);
-    EXPECT_EQ(builtin::BuiltinValue::kFragDepth, d->builtin);
+    auto* d = Builtin(builtin::BuiltinValue::kFragDepth);
+    CheckIdentifier(Symbols(), d->builtin, "frag_depth");
+}
+
+TEST_F(BuiltinAttributeTest, Assert_Null_Builtin) {
+    EXPECT_FATAL_FAILURE(
+        {
+            ProgramBuilder b;
+            b.Builtin(nullptr);
+        },
+        "internal compiler error");
+}
+
+TEST_F(BuiltinAttributeTest, Assert_DifferentProgramID_Builtin) {
+    EXPECT_FATAL_FAILURE(
+        {
+            ProgramBuilder b1;
+            ProgramBuilder b2;
+            b1.Builtin(b2.Expr("bang"));
+        },
+        "internal compiler error");
 }
 
 }  // namespace
diff --git a/src/tint/ast/variable_test.cc b/src/tint/ast/variable_test.cc
index 35fca4ac53..0b4602611c 100644
--- a/src/tint/ast/variable_test.cc
+++ b/src/tint/ast/variable_test.cc
@@ -16,6 +16,7 @@
 
 #include "src/tint/ast/id_attribute.h"
 #include "src/tint/ast/test_helper.h"
+#include "src/tint/builtin/builtin_value.h"
 
 using namespace tint::number_suffixes;  // NOLINT
 
diff --git a/src/tint/builtin/builtin_value.cc b/src/tint/builtin/builtin_value.cc
index 740ebcc9b8..150ac7ba4e 100644
--- a/src/tint/builtin/builtin_value.cc
+++ b/src/tint/builtin/builtin_value.cc
@@ -28,6 +28,9 @@ namespace tint::builtin {
 /// @param str the string to parse
 /// @returns the parsed enum, or BuiltinValue::kUndefined if the string could not be parsed.
 BuiltinValue ParseBuiltinValue(std::string_view str) {
+    if (str == "__point_size") {
+        return BuiltinValue::kPointSize;
+    }
     if (str == "frag_depth") {
         return BuiltinValue::kFragDepth;
     }
@@ -71,6 +74,8 @@ std::ostream& operator<<(std::ostream& out, BuiltinValue value) {
     switch (value) {
         case BuiltinValue::kUndefined:
             return out << "undefined";
+        case BuiltinValue::kPointSize:
+            return out << "__point_size";
         case BuiltinValue::kFragDepth:
             return out << "frag_depth";
         case BuiltinValue::kFrontFacing:
@@ -85,8 +90,6 @@ std::ostream& operator<<(std::ostream& out, BuiltinValue value) {
             return out << "local_invocation_index";
         case BuiltinValue::kNumWorkgroups:
             return out << "num_workgroups";
-        case BuiltinValue::kPointSize:
-            return out << "point_size";
         case BuiltinValue::kPosition:
             return out << "position";
         case BuiltinValue::kSampleIndex:
diff --git a/src/tint/builtin/builtin_value.h b/src/tint/builtin/builtin_value.h
index 1d5b4d4137..4f8753ff2e 100644
--- a/src/tint/builtin/builtin_value.h
+++ b/src/tint/builtin/builtin_value.h
@@ -30,6 +30,7 @@ namespace tint::builtin {
 /// Builtin value defined with `@builtin(<name>)`.
 enum class BuiltinValue {
     kUndefined,
+    kPointSize,
     kFragDepth,
     kFrontFacing,
     kGlobalInvocationId,
@@ -37,7 +38,6 @@ enum class BuiltinValue {
     kLocalInvocationId,
     kLocalInvocationIndex,
     kNumWorkgroups,
-    kPointSize,  // Tint-internal enum entry - not parsed
     kPosition,
     kSampleIndex,
     kSampleMask,
@@ -56,12 +56,11 @@ std::ostream& operator<<(std::ostream& out, BuiltinValue value);
 BuiltinValue ParseBuiltinValue(std::string_view str);
 
 constexpr const char* kBuiltinValueStrings[] = {
-    "frag_depth",           "front_facing",
-    "global_invocation_id", "instance_index",
-    "local_invocation_id",  "local_invocation_index",
-    "num_workgroups",       "position",
-    "sample_index",         "sample_mask",
-    "vertex_index",         "workgroup_id",
+    "__point_size",           "frag_depth",     "front_facing",
+    "global_invocation_id",   "instance_index", "local_invocation_id",
+    "local_invocation_index", "num_workgroups", "position",
+    "sample_index",           "sample_mask",    "vertex_index",
+    "workgroup_id",
 };
 
 }  // namespace tint::builtin
diff --git a/src/tint/builtin/builtin_value_bench.cc b/src/tint/builtin/builtin_value_bench.cc
index 50d677e66b..4d2e562308 100644
--- a/src/tint/builtin/builtin_value_bench.cc
+++ b/src/tint/builtin/builtin_value_bench.cc
@@ -31,90 +31,97 @@ namespace {
 
 void BuiltinValueParser(::benchmark::State& state) {
     const char* kStrings[] = {
-        "fragdeccth",
-        "flaget3",
-        "fVag_depth",
+        "_ccpoint_siz",
+        "_3poi_ile",
+        "__poiVt_size",
+        "__point_size",
+        "1_point_size",
+        "__pointJsqze",
+        "__lloint_siz77",
+        "frqqgppepHHh",
+        "fv_dcpt",
+        "frabGdeth",
         "frag_depth",
-        "frag1depth",
-        "fraJqqepth",
-        "fra7ll_depth",
-        "fonHHpp_facing",
-        "fron_facg",
-        "frGnt_fbcin",
+        "frag_veiith",
+        "fr8g_depWWh",
+        "Mragxxepth",
+        "ggroXtfacing",
+        "Vot_fuciXg",
+        "front_fac3ng",
         "front_facing",
-        "front_facvnii",
-        "frWWnt_faci8g",
-        "fxxonM_facig",
-        "gXobalgginvocationid",
-        "goVal_uvocatioX_id",
-        "global_in3ocation_id",
+        "front_fEcing",
+        "fronPPfaTTing",
+        "ddroxxtfacing",
+        "global_invocatio44_id",
+        "global_invocaSSioVV_id",
+        "22loRal_invoRtion_id",
         "global_invocation_id",
-        "global_invocation_iE",
-        "TTobal_invocationPPid",
-        "globdd_invocatioxx_id",
-        "instance44index",
-        "instaVVce_SSndex",
-        "Rnstane_ind2Rx",
+        "globalFinvoction_id",
+        "gloal_invocation_id",
+        "RRlHOOaV_invoction_id",
+        "instance_ydex",
+        "instGlr77cnn_index",
+        "instan04e_index",
         "instance_index",
-        "inFtanceind9x",
-        "insance_index",
-        "inRRancV_OOHdex",
-        "local_nvocytion_id",
-        "llGcnnl_inv77catirrn_id",
-        "local_invoca4i00n_id",
+        "insacoo_inex",
+        "izstane_index",
+        "nippance_in11ex",
+        "local_invXXcation_id",
+        "lIIcal_i5599ocation_inn",
+        "HHrrcal_inSSocation_Yaa",
         "local_invocation_id",
-        "loool_nvocaton_id",
-        "local_inozztion_id",
-        "p11cal_invocatiiin_i",
-        "local_invocation_iXXdex",
-        "local_invnnIIati99n55index",
-        "localYirrHHocaationSSindex",
+        "lokkal_invocatini",
+        "jocal_invocRRongid",
+        "local_inocatbon_i",
+        "local_injocation_index",
+        "local_invocatio_index",
+        "locl_invocqtion_ndex",
         "local_invocation_index",
-        "lkkal_invHcation_idx",
-        "gRcal_invocatioj_inex",
-        "lcal_invcbtion_index",
+        "localNNinvocaton_index",
+        "local_invocatin_ivvdx",
+        "locl_invocatioQQ_index",
+        "num_workgffus",
         "num_workgroujs",
-        "num_worgroups",
-        "nuq_orkgoups",
+        "num_wrkgNNwoup8",
         "num_workgroups",
-        "nm_workgroNNps",
-        "um_workgrovps",
-        "nQQm_orkgroups",
-        "posftrn",
-        "pojition",
-        "poswNN82n",
+        "numworkgroups",
+        "num_workrrroups",
+        "num_worGgroups",
+        "pFFsition",
+        "pEiio",
+        "prrsitio",
         "position",
-        "positon",
-        "porrition",
-        "pGsition",
-        "sample_inFFex",
-        "samleinex",
-        "sample_indrr",
+        "sition",
+        "poJJDtin",
+        "poi8i",
+        "smpke11nde",
+        "samle_index",
+        "saple_Jndex",
         "sample_index",
-        "sample_iex",
-        "DaplX_JJndex",
-        "8amleinde",
-        "saplekmak",
-        "samle_mask",
-        "saJple_mak",
+        "cample_index",
+        "sample_indOx",
+        "savvKKl___inttex",
+        "sam8le_xx5k",
+        "sampqq__msk",
+        "sampleqmask",
         "sample_mask",
-        "sample_cask",
-        "sample_maOk",
-        "__attpvve_KKask",
-        "vrtex5inxxe8",
-        "v__rex_qFdex",
-        "veqqtex_idex",
+        "33amOe_mas66",
+        "samoott6QQmask",
+        "66mple_mask",
+        "verzzx_in6Oxx",
+        "vertex_yyndex",
+        "vetxHHZnZex",
         "vertex_index",
-        "veOtx_33nde66",
-        "v6ootex_indttQx",
-        "ver66ex_inex",
-        "worzzroup6Oxd",
-        "workgroyyp_id",
-        "wokrHHZpZid",
+        "vWWteq_in44ex",
+        "vrtex_OOndex",
+        "hrteYooindx",
+        "wogroup_i",
+        "wokgrouF_id",
+        "worgrwup_id",
         "workgroup_id",
-        "wWWkgqoup44id",
-        "wrkgroOOp_id",
-        "hrkgYooup_d",
+        "workGKou_if",
+        "worKKgrouq_id",
+        "w3rkgrommp_id",
     };
     for (auto _ : state) {
         for (auto* str : kStrings) {
diff --git a/src/tint/builtin/builtin_value_test.cc b/src/tint/builtin/builtin_value_test.cc
index b245250f79..ae615bcc5a 100644
--- a/src/tint/builtin/builtin_value_test.cc
+++ b/src/tint/builtin/builtin_value_test.cc
@@ -43,6 +43,7 @@ inline std::ostream& operator<<(std::ostream& out, Case c) {
 }
 
 static constexpr Case kValidCases[] = {
+    {"__point_size", BuiltinValue::kPointSize},
     {"frag_depth", BuiltinValue::kFragDepth},
     {"front_facing", BuiltinValue::kFrontFacing},
     {"global_invocation_id", BuiltinValue::kGlobalInvocationId},
@@ -58,42 +59,45 @@ static constexpr Case kValidCases[] = {
 };
 
 static constexpr Case kInvalidCases[] = {
-    {"fragdeccth", BuiltinValue::kUndefined},
-    {"flaget3", BuiltinValue::kUndefined},
-    {"fVag_depth", BuiltinValue::kUndefined},
-    {"1ront_facing", BuiltinValue::kUndefined},
-    {"front_fJcqng", BuiltinValue::kUndefined},
-    {"frllnt_facin77", BuiltinValue::kUndefined},
-    {"global_invoqqtionppHid", BuiltinValue::kUndefined},
-    {"clvbal_inocaionid", BuiltinValue::kUndefined},
-    {"global_Gvocation_id", BuiltinValue::kUndefined},
-    {"invtance_iniiex", BuiltinValue::kUndefined},
-    {"8nstanceWWindex", BuiltinValue::kUndefined},
-    {"insxxanceindex", BuiltinValue::kUndefined},
-    {"lXcal_invoation_igg", BuiltinValue::kUndefined},
-    {"Xocal_nvocatin_Vd", BuiltinValue::kUndefined},
-    {"local_invoca3ion_id", BuiltinValue::kUndefined},
-    {"local_invocation_indeE", BuiltinValue::kUndefined},
-    {"loTTal_invPPcatin_index", BuiltinValue::kUndefined},
-    {"loal_invocadxxion_index", BuiltinValue::kUndefined},
-    {"num_work44roups", BuiltinValue::kUndefined},
-    {"num_wVVrkgSSoups", BuiltinValue::kUndefined},
-    {"Rum_wokgrou2Rs", BuiltinValue::kUndefined},
-    {"oFi9ion", BuiltinValue::kUndefined},
-    {"postion", BuiltinValue::kUndefined},
-    {"ROOoHiiVn", BuiltinValue::kUndefined},
-    {"samply_inde", BuiltinValue::kUndefined},
-    {"snrrmpl77l_indGx", BuiltinValue::kUndefined},
-    {"00ample4index", BuiltinValue::kUndefined},
-    {"smoo_mask", BuiltinValue::kUndefined},
-    {"sampzemask", BuiltinValue::kUndefined},
-    {"ppaplii1_mas", BuiltinValue::kUndefined},
-    {"vertex_iXXdex", BuiltinValue::kUndefined},
-    {"5nnertex_99IIdex", BuiltinValue::kUndefined},
-    {"verYeaaHHrrndeSS", BuiltinValue::kUndefined},
-    {"workkgHo_i", BuiltinValue::kUndefined},
-    {"worRgoupjid", BuiltinValue::kUndefined},
-    {"wrkgrupbid", BuiltinValue::kUndefined},
+    {"_ccpoint_siz", BuiltinValue::kUndefined},
+    {"_3poi_ile", BuiltinValue::kUndefined},
+    {"__poiVt_size", BuiltinValue::kUndefined},
+    {"frag1depth", BuiltinValue::kUndefined},
+    {"fraJqqepth", BuiltinValue::kUndefined},
+    {"fra7ll_depth", BuiltinValue::kUndefined},
+    {"fonHHpp_facing", BuiltinValue::kUndefined},
+    {"fron_facg", BuiltinValue::kUndefined},
+    {"frGnt_fbcin", BuiltinValue::kUndefined},
+    {"glvbal_iinvocation_id", BuiltinValue::kUndefined},
+    {"gl8bal_invocation_WWd", BuiltinValue::kUndefined},
+    {"Mlobal_invocaton_xxd", BuiltinValue::kUndefined},
+    {"isXance_indegg", BuiltinValue::kUndefined},
+    {"insanc_iXVex", BuiltinValue::kUndefined},
+    {"instance_in3ex", BuiltinValue::kUndefined},
+    {"local_Envocation_id", BuiltinValue::kUndefined},
+    {"localiPPvocatioTT_id", BuiltinValue::kUndefined},
+    {"localxxnvocationddid", BuiltinValue::kUndefined},
+    {"loca44_invocation_index", BuiltinValue::kUndefined},
+    {"local_invocSStionVVindex", BuiltinValue::kUndefined},
+    {"locRR_invocat22n_index", BuiltinValue::kUndefined},
+    {"nuF_workrou9s", BuiltinValue::kUndefined},
+    {"numworkgroups", BuiltinValue::kUndefined},
+    {"nuRRworVgOOHups", BuiltinValue::kUndefined},
+    {"posytio", BuiltinValue::kUndefined},
+    {"77orritllnon", BuiltinValue::kUndefined},
+    {"04osition", BuiltinValue::kUndefined},
+    {"smpe_oonde", BuiltinValue::kUndefined},
+    {"smpl_inzzex", BuiltinValue::kUndefined},
+    {"saiip11eindep", BuiltinValue::kUndefined},
+    {"sample_XXask", BuiltinValue::kUndefined},
+    {"samII99l55_mask", BuiltinValue::kUndefined},
+    {"samaale_SSrHHYk", BuiltinValue::kUndefined},
+    {"verkkeH_de", BuiltinValue::kUndefined},
+    {"verRg_injex", BuiltinValue::kUndefined},
+    {"vrtexinbex", BuiltinValue::kUndefined},
+    {"workjroup_id", BuiltinValue::kUndefined},
+    {"wrkgroup_id", BuiltinValue::kUndefined},
+    {"qorkgro_id", BuiltinValue::kUndefined},
 };
 
 using BuiltinValueParseTest = testing::TestWithParam<Case>;
diff --git a/src/tint/inspector/inspector.cc b/src/tint/inspector/inspector.cc
index e3706cfa8c..b7455c7088 100644
--- a/src/tint/inspector/inspector.cc
+++ b/src/tint/inspector/inspector.cc
@@ -28,7 +28,9 @@
 #include "src/tint/ast/module.h"
 #include "src/tint/ast/override.h"
 #include "src/tint/ast/var.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/builtin/extension.h"
+#include "src/tint/sem/builtin_enum_expression.h"
 #include "src/tint/sem/call.h"
 #include "src/tint/sem/function.h"
 #include "src/tint/sem/module.h"
@@ -698,11 +700,10 @@ bool Inspector::ContainsBuiltin(builtin::BuiltinValue builtin,
 
     // Base case: check for builtin
     auto* builtin_declaration = ast::GetAttribute<ast::BuiltinAttribute>(attributes);
-    if (!builtin_declaration || builtin_declaration->builtin != builtin) {
+    if (!builtin_declaration) {
         return false;
     }
-
-    return true;
+    return program_->Sem().Get(builtin_declaration)->Value() == builtin;
 }
 
 std::vector<ResourceBinding> Inspector::GetStorageBufferResourceBindingsImpl(
diff --git a/src/tint/inspector/inspector.h b/src/tint/inspector/inspector.h
index 5854125644..baaf8aacd3 100644
--- a/src/tint/inspector/inspector.h
+++ b/src/tint/inspector/inspector.h
@@ -25,6 +25,7 @@
 
 #include "tint/override_id.h"
 
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/inspector/entry_point.h"
 #include "src/tint/inspector/resource_binding.h"
 #include "src/tint/inspector/scalar.h"
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index f55b12cd6e..933ae572eb 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -37,7 +37,7 @@ enum builtin_value {
   num_workgroups
   sample_index
   sample_mask
-  @internal point_size
+  __point_size
 }
 
 // https://gpuweb.github.io/gpuweb/wgsl/#filterable-triggering-rules
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index f13290033a..03cc3153c2 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -3445,15 +3445,17 @@ class ProgramBuilder {
     /// @param source the source information
     /// @param builtin the builtin value
     /// @returns the builtin attribute pointer
-    const ast::BuiltinAttribute* Builtin(const Source& source, builtin::BuiltinValue builtin) {
-        return create<ast::BuiltinAttribute>(source, builtin);
+    template <typename BUILTIN>
+    const ast::BuiltinAttribute* Builtin(const Source& source, BUILTIN&& builtin) {
+        return create<ast::BuiltinAttribute>(source, Expr(std::forward<BUILTIN>(builtin)));
     }
 
     /// Creates an ast::BuiltinAttribute
     /// @param builtin the builtin value
     /// @returns the builtin attribute pointer
-    const ast::BuiltinAttribute* Builtin(builtin::BuiltinValue builtin) {
-        return create<ast::BuiltinAttribute>(source_, builtin);
+    template <typename BUILTIN>
+    const ast::BuiltinAttribute* Builtin(BUILTIN&& builtin) {
+        return create<ast::BuiltinAttribute>(source_, Expr(std::forward<BUILTIN>(builtin)));
     }
 
     /// Creates an ast::InterpolateAttribute
diff --git a/src/tint/reader/spirv/attributes.h b/src/tint/reader/spirv/attributes.h
new file mode 100644
index 0000000000..9014332f52
--- /dev/null
+++ b/src/tint/reader/spirv/attributes.h
@@ -0,0 +1,81 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_READER_SPIRV_ATTRIBUTES_H_
+#define SRC_TINT_READER_SPIRV_ATTRIBUTES_H_
+
+#include "src/tint/ast/attribute.h"
+#include "src/tint/builtin/builtin_value.h"
+#include "src/tint/program_builder.h"
+#include "src/tint/utils/enum_set.h"
+#include "src/tint/utils/vector.h"
+
+namespace tint::reader::spirv {
+
+/// Attributes holds a vector of ast::Attribute pointers, and a enum-set of flags used to hold
+/// additional metadata.
+struct Attributes {
+    /// Flags used by #flags.
+    enum class Flags {
+        kHasBuiltinSampleMask,
+    };
+
+    /// Adds the attributes and flags of @p other to this.
+    /// @param other the other Attributes to combine into this
+    void Add(const Attributes& other) {
+        for (auto* attr : other.list) {
+            list.Push(attr);
+        }
+        for (auto flag : other.flags) {
+            flags.Add(flag);
+        }
+    }
+
+    /// Adds the attribute @p attr to the list of attributes
+    /// @param attr the attribute to add to this
+    void Add(const ast::Attribute* attr) { list.Push(attr); }
+
+    /// Adds the builtin to the attribute list, also marking any necessary flags
+    /// @param builder the program builder
+    /// @param source the source of the builtin attribute
+    /// @param builtin the builtin attribute to add
+    void Add(ProgramBuilder& builder, const Source& source, builtin::BuiltinValue builtin) {
+        Add(builder.Builtin(source, builtin));
+        if (builtin == builtin::BuiltinValue::kSampleMask) {
+            flags.Add(Flags::kHasBuiltinSampleMask);
+        }
+    }
+
+    /// @returns true if the attribute list contains an attribute with the type `T`.
+    template <typename T>
+    bool Has() const {
+        return ast::HasAttribute<T>(list);
+    }
+
+    /// @returns the attribute with type `T` in the list, or nullptr if no attribute of the given
+    /// type exists in list.
+    template <typename T>
+    const T* Get() const {
+        return ast::GetAttribute<T>(list);
+    }
+
+    /// The attributes
+    utils::Vector<const ast::Attribute*, 8> list;
+    /// The additional metadata flags
+    utils::EnumSet<Flags> flags;
+};
+
+}  // namespace tint::reader::spirv
+
+#endif  // SRC_TINT_READER_SPIRV_ATTRIBUTES_H_
diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc
index 12c46c1745..f94be977d0 100644
--- a/src/tint/reader/spirv/function.cc
+++ b/src/tint/reader/spirv/function.cc
@@ -756,15 +756,6 @@ struct LoopStatementBuilder final : public Castable<LoopStatementBuilder, Statem
     mutable const ast::BlockStatement* continuing = nullptr;
 };
 
-/// @param decos a list of parsed decorations
-/// @returns true if the decorations include a SampleMask builtin
-bool HasBuiltinSampleMask(utils::VectorRef<const ast::Attribute*> decos) {
-    if (auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(decos)) {
-        return builtin->builtin == builtin::BuiltinValue::kSampleMask;
-    }
-    return false;
-}
-
 }  // namespace
 
 BlockInfo::BlockInfo(const spvtools::opt::BasicBlock& bb) : basic_block(&bb), id(bb.id()) {}
@@ -956,7 +947,7 @@ bool FunctionEmitter::Emit() {
         }
 
         builder_.Func(decl.source, decl.name, std::move(decl.params),
-                      decl.return_type->Build(builder_), body, std::move(decl.attributes));
+                      decl.return_type->Build(builder_), body, std::move(decl.attributes.list));
     }
 
     if (ep_info_ && !ep_info_->inner_name.empty()) {
@@ -994,12 +985,12 @@ const ast::BlockStatement* FunctionEmitter::MakeFunctionBody() {
 
 bool FunctionEmitter::EmitPipelineInput(std::string var_name,
                                         const Type* var_type,
-                                        AttributeList* attrs,
                                         utils::Vector<int, 8> index_prefix,
                                         const Type* tip_type,
                                         const Type* forced_param_type,
-                                        ParameterList* params,
-                                        StatementList* statements) {
+                                        Attributes& attrs,
+                                        ParameterList& params,
+                                        StatementList& statements) {
     // TODO(dneto): Handle structs where the locations are annotated on members.
     tip_type = tip_type->UnwrapAlias();
     if (auto* ref_type = tip_type->As<Reference>()) {
@@ -1015,8 +1006,8 @@ bool FunctionEmitter::EmitPipelineInput(std::string var_name,
             const Type* vec_ty = ty_.Vector(matrix_type->type, matrix_type->rows);
             for (int col = 0; col < num_columns; col++) {
                 index_prefix.Back() = col;
-                if (!EmitPipelineInput(var_name, var_type, attrs, index_prefix, vec_ty,
-                                       forced_param_type, params, statements)) {
+                if (!EmitPipelineInput(var_name, var_type, index_prefix, vec_ty, forced_param_type,
+                                       attrs, params, statements)) {
                     return false;
                 }
             }
@@ -1030,8 +1021,8 @@ bool FunctionEmitter::EmitPipelineInput(std::string var_name,
             const Type* elem_ty = array_type->type;
             for (int i = 0; i < static_cast<int>(array_type->size); i++) {
                 index_prefix.Back() = i;
-                if (!EmitPipelineInput(var_name, var_type, attrs, index_prefix, elem_ty,
-                                       forced_param_type, params, statements)) {
+                if (!EmitPipelineInput(var_name, var_type, index_prefix, elem_ty, forced_param_type,
+                                       attrs, params, statements)) {
                     return false;
                 }
             }
@@ -1042,38 +1033,36 @@ bool FunctionEmitter::EmitPipelineInput(std::string var_name,
             index_prefix.Push(0);
             for (size_t i = 0; i < members.size(); ++i) {
                 index_prefix.Back() = static_cast<int>(i);
-                AttributeList member_attrs(*attrs);
+                Attributes member_attrs(attrs);
                 if (!parser_impl_.ConvertPipelineDecorations(
                         struct_type,
                         parser_impl_.GetMemberPipelineDecorations(*struct_type,
                                                                   static_cast<int>(i)),
-                        &member_attrs)) {
+                        member_attrs)) {
                     return false;
                 }
-                if (!EmitPipelineInput(var_name, var_type, &member_attrs, index_prefix, members[i],
-                                       forced_param_type, params, statements)) {
+                if (!EmitPipelineInput(var_name, var_type, index_prefix, members[i],
+                                       forced_param_type, member_attrs, params, statements)) {
                     return false;
                 }
                 // Copy the location as updated by nested expansion of the member.
-                parser_impl_.SetLocation(attrs,
-                                         ast::GetAttribute<ast::LocationAttribute>(member_attrs));
+                parser_impl_.SetLocation(attrs, member_attrs.Get<ast::LocationAttribute>());
             }
             return success();
         },
         [&](Default) {
-            const bool is_builtin = ast::HasAttribute<ast::BuiltinAttribute>(*attrs);
+            const bool is_builtin = attrs.Has<ast::BuiltinAttribute>();
 
             const Type* param_type = is_builtin ? forced_param_type : tip_type;
 
             const auto param_name = namer_.MakeDerivedName(var_name + "_param");
             // Create the parameter.
-            // TODO(dneto): Note: If the parameter has non-location decorations,
-            // then those decoration AST nodes will be reused between multiple
-            // elements of a matrix, array, or structure.  Normally that's
-            // disallowed but currently the SPIR-V reader will make duplicates when
-            // the entire AST is cloned at the top level of the SPIR-V reader flow.
+            // TODO(dneto): Note: If the parameter has non-location decorations, then those
+            // decoration AST nodes will be reused between multiple elements of a matrix, array, or
+            // structure.  Normally that's disallowed but currently the SPIR-V reader will make
+            // duplicates when the entire AST is cloned at the top level of the SPIR-V reader flow.
             // Consider rewriting this to avoid this node-sharing.
-            params->Push(builder_.Param(param_name, param_type->Build(builder_), *attrs));
+            params.Push(builder_.Param(param_name, param_type->Build(builder_), attrs.list));
 
             // Add a body statement to copy the parameter to the corresponding
             // private variable.
@@ -1101,27 +1090,25 @@ bool FunctionEmitter::EmitPipelineInput(std::string var_name,
             }
 
             if (is_builtin && (tip_type != forced_param_type)) {
-                // The parameter will have the WGSL type, but we need bitcast to
-                // the variable store type.
+                // The parameter will have the WGSL type, but we need bitcast to the variable store
+                // type.
                 param_value = builder_.Bitcast(tip_type->Build(builder_), param_value);
             }
 
-            statements->Push(builder_.Assign(store_dest, param_value));
+            statements.Push(builder_.Assign(store_dest, param_value));
 
-            // Increment the location attribute, in case more parameters will
-            // follow.
+            // Increment the location attribute, in case more parameters will follow.
             IncrementLocation(attrs);
 
             return success();
         });
 }
 
-void FunctionEmitter::IncrementLocation(AttributeList* attributes) {
-    for (auto*& attr : *attributes) {
+void FunctionEmitter::IncrementLocation(Attributes& attributes) {
+    for (auto*& attr : attributes.list) {
         if (auto* loc_attr = attr->As<ast::LocationAttribute>()) {
             // Replace this location attribute with a new one with one higher index.
-            // The old one doesn't leak because it's kept in the builder's AST node
-            // list.
+            // The old one doesn't leak because it's kept in the builder's AST node list.
             attr = builder_.Location(
                 loc_attr->source, AInt(loc_attr->expr->As<ast::IntLiteralExpression>()->value + 1));
         }
@@ -1130,12 +1117,12 @@ void FunctionEmitter::IncrementLocation(AttributeList* attributes) {
 
 bool FunctionEmitter::EmitPipelineOutput(std::string var_name,
                                          const Type* var_type,
-                                         AttributeList* decos,
                                          utils::Vector<int, 8> index_prefix,
                                          const Type* tip_type,
                                          const Type* forced_member_type,
-                                         StructMemberList* return_members,
-                                         ExpressionList* return_exprs) {
+                                         Attributes& attrs,
+                                         StructMemberList& return_members,
+                                         ExpressionList& return_exprs) {
     tip_type = tip_type->UnwrapAlias();
     if (auto* ref_type = tip_type->As<Reference>()) {
         tip_type = ref_type->type;
@@ -1150,8 +1137,8 @@ bool FunctionEmitter::EmitPipelineOutput(std::string var_name,
             const Type* vec_ty = ty_.Vector(matrix_type->type, matrix_type->rows);
             for (int col = 0; col < num_columns; col++) {
                 index_prefix.Back() = col;
-                if (!EmitPipelineOutput(var_name, var_type, std::move(decos), index_prefix, vec_ty,
-                                        forced_member_type, return_members, return_exprs)) {
+                if (!EmitPipelineOutput(var_name, var_type, index_prefix, vec_ty,
+                                        forced_member_type, attrs, return_members, return_exprs)) {
                     return false;
                 }
             }
@@ -1165,8 +1152,8 @@ bool FunctionEmitter::EmitPipelineOutput(std::string var_name,
             const Type* elem_ty = array_type->type;
             for (int i = 0; i < static_cast<int>(array_type->size); i++) {
                 index_prefix.Back() = i;
-                if (!EmitPipelineOutput(var_name, var_type, std::move(decos), index_prefix, elem_ty,
-                                        forced_member_type, return_members, return_exprs)) {
+                if (!EmitPipelineOutput(var_name, var_type, index_prefix, elem_ty,
+                                        forced_member_type, attrs, return_members, return_exprs)) {
                     return false;
                 }
             }
@@ -1177,39 +1164,37 @@ bool FunctionEmitter::EmitPipelineOutput(std::string var_name,
             index_prefix.Push(0);
             for (int i = 0; i < static_cast<int>(members.size()); ++i) {
                 index_prefix.Back() = i;
-                AttributeList member_attrs(*decos);
+                Attributes member_attrs(attrs);
                 if (!parser_impl_.ConvertPipelineDecorations(
                         struct_type, parser_impl_.GetMemberPipelineDecorations(*struct_type, i),
-                        &member_attrs)) {
+                        member_attrs)) {
                     return false;
                 }
-                if (!EmitPipelineOutput(var_name, var_type, &member_attrs, index_prefix,
+                if (!EmitPipelineOutput(var_name, var_type, index_prefix,
                                         members[static_cast<size_t>(i)], forced_member_type,
-                                        return_members, return_exprs)) {
+                                        member_attrs, return_members, return_exprs)) {
                     return false;
                 }
                 // Copy the location as updated by nested expansion of the member.
-                parser_impl_.SetLocation(decos,
-                                         ast::GetAttribute<ast::LocationAttribute>(member_attrs));
+                parser_impl_.SetLocation(attrs, member_attrs.Get<ast::LocationAttribute>());
             }
             return success();
         },
         [&](Default) {
-            const bool is_builtin = ast::HasAttribute<ast::BuiltinAttribute>(*decos);
+            const bool is_builtin = attrs.Has<ast::BuiltinAttribute>();
 
             const Type* member_type = is_builtin ? forced_member_type : tip_type;
             // Derive the member name directly from the variable name.  They can't
             // collide.
             const auto member_name = namer_.MakeDerivedName(var_name);
             // Create the member.
-            // TODO(dneto): Note: If the parameter has non-location decorations,
-            // then those decoration AST nodes  will be reused between multiple
-            // elements of a matrix, array, or structure.  Normally that's
-            // disallowed but currently the SPIR-V reader will make duplicates when
-            // the entire AST is cloned at the top level of the SPIR-V reader flow.
+            // TODO(dneto): Note: If the parameter has non-location decorations, then those
+            // decoration AST nodes  will be reused between multiple elements of a matrix, array, or
+            // structure.  Normally that's disallowed but currently the SPIR-V reader will make
+            // duplicates when the entire AST is cloned at the top level of the SPIR-V reader flow.
             // Consider rewriting this to avoid this node-sharing.
-            return_members->Push(
-                builder_.Member(member_name, member_type->Build(builder_), *decos));
+            return_members.Push(
+                builder_.Member(member_name, member_type->Build(builder_), attrs.list));
 
             // Create an expression to evaluate the part of the variable indexed by
             // the index_prefix.
@@ -1240,11 +1225,10 @@ bool FunctionEmitter::EmitPipelineOutput(std::string var_name,
                 // the variable store type.
                 load_source = builder_.Bitcast(forced_member_type->Build(builder_), load_source);
             }
-            return_exprs->Push(load_source);
+            return_exprs.Push(load_source);
 
-            // Increment the location attribute, in case more parameters will
-            // follow.
-            IncrementLocation(decos);
+            // Increment the location attribute, in case more parameters will follow.
+            IncrementLocation(attrs);
 
             return success();
         });
@@ -1270,8 +1254,8 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
         TINT_ASSERT(Reader, opcode(var) == spv::Op::OpVariable);
         auto* store_type = GetVariableStoreType(*var);
         auto* forced_param_type = store_type;
-        AttributeList param_decos;
-        if (!parser_impl_.ConvertDecorationsForVariable(var_id, &forced_param_type, &param_decos,
+        Attributes param_attrs;
+        if (!parser_impl_.ConvertDecorationsForVariable(var_id, &forced_param_type, param_attrs,
                                                         true)) {
             // This occurs, and is not an error, for the PointSize builtin.
             if (!success()) {
@@ -1287,18 +1271,17 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
         const auto var_name = namer_.GetName(var_id);
 
         bool ok = true;
-        if (HasBuiltinSampleMask(param_decos)) {
+        if (param_attrs.flags.Contains(Attributes::Flags::kHasBuiltinSampleMask)) {
             // In Vulkan SPIR-V, the sample mask is an array. In WGSL it's a scalar.
             // Use the first element only.
             auto* sample_mask_array_type = store_type->UnwrapRef()->UnwrapAlias()->As<Array>();
             TINT_ASSERT(Reader, sample_mask_array_type);
-            ok = EmitPipelineInput(var_name, store_type, &param_decos, {0},
-                                   sample_mask_array_type->type, forced_param_type, &decl.params,
-                                   &stmts);
+            ok = EmitPipelineInput(var_name, store_type, {0}, sample_mask_array_type->type,
+                                   forced_param_type, param_attrs, decl.params, stmts);
         } else {
             // The normal path.
-            ok = EmitPipelineInput(var_name, store_type, &param_decos, {}, store_type,
-                                   forced_param_type, &decl.params, &stmts);
+            ok = EmitPipelineInput(var_name, store_type, {}, store_type, forced_param_type,
+                                   param_attrs, decl.params, stmts);
         }
         if (!ok) {
             return false;
@@ -1330,12 +1313,12 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
                 // The SPIR-V gl_PerVertex variable has already been remapped to
                 // a gl_Position variable.  Substitute the type.
                 const Type* param_type = ty_.Vector(ty_.F32(), 4);
-                AttributeList out_decos{
-                    create<ast::BuiltinAttribute>(source, builtin::BuiltinValue::kPosition)};
-
                 const auto var_name = namer_.GetName(var_id);
                 return_members.Push(
-                    builder_.Member(var_name, param_type->Build(builder_), out_decos));
+                    builder_.Member(var_name, param_type->Build(builder_),
+                                    utils::Vector{
+                                        builder_.Builtin(source, builtin::BuiltinValue::kPosition),
+                                    }));
                 return_exprs.Push(builder_.Expr(var_name));
 
             } else {
@@ -1344,9 +1327,9 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
                 TINT_ASSERT(Reader, opcode(var) == spv::Op::OpVariable);
                 const Type* store_type = GetVariableStoreType(*var);
                 const Type* forced_member_type = store_type;
-                AttributeList out_decos;
+                Attributes out_attrs;
                 if (!parser_impl_.ConvertDecorationsForVariable(var_id, &forced_member_type,
-                                                                &out_decos, true)) {
+                                                                out_attrs, true)) {
                     // This occurs, and is not an error, for the PointSize builtin.
                     if (!success()) {
                         // But exit early if an error was logged.
@@ -1357,19 +1340,20 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
 
                 const auto var_name = namer_.GetName(var_id);
                 bool ok = true;
-                if (HasBuiltinSampleMask(out_decos)) {
+                if (out_attrs.flags.Contains(Attributes::Flags::kHasBuiltinSampleMask)) {
                     // In Vulkan SPIR-V, the sample mask is an array. In WGSL it's a
                     // scalar. Use the first element only.
                     auto* sample_mask_array_type =
                         store_type->UnwrapRef()->UnwrapAlias()->As<Array>();
                     TINT_ASSERT(Reader, sample_mask_array_type);
-                    ok = EmitPipelineOutput(var_name, store_type, &out_decos, {0},
-                                            sample_mask_array_type->type, forced_member_type,
-                                            &return_members, &return_exprs);
+                    ok = EmitPipelineOutput(var_name, store_type, {0}, sample_mask_array_type->type,
+                                            forced_member_type, out_attrs, return_members,
+                                            return_exprs);
                 } else {
                     // The normal path.
-                    ok = EmitPipelineOutput(var_name, store_type, &out_decos, {}, store_type,
-                                            forced_member_type, &return_members, &return_exprs);
+                    ok =
+                        EmitPipelineOutput(var_name, store_type, {}, store_type, forced_member_type,
+                                           out_attrs, return_members, return_exprs);
                 }
                 if (!ok) {
                     return false;
@@ -1384,7 +1368,7 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
         } else {
             // Create and register the result type.
             auto* str = create<ast::Struct>(Source{}, builder_.Ident(return_struct_sym),
-                                            return_members, AttributeList{});
+                                            return_members, utils::Empty);
             parser_impl_.AddTypeDecl(return_struct_sym, str);
             return_type = builder_.ty.Of(str);
 
@@ -1394,8 +1378,9 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
         }
     }
 
-    AttributeList fn_attrs;
-    fn_attrs.Push(create<ast::StageAttribute>(source, ep_info_->stage));
+    utils::Vector<const ast::Attribute*, 2> fn_attrs{
+        create<ast::StageAttribute>(source, ep_info_->stage),
+    };
 
     if (ep_info_->stage == ast::PipelineStage::kCompute) {
         auto& size = ep_info_->workgroup_size;
@@ -1442,7 +1427,7 @@ bool FunctionEmitter::ParseFunctionDeclaration(FunctionDeclaration* decl) {
                                      : parser_impl_.ConvertType(param->type_id());
 
         if (type != nullptr) {
-            auto* ast_param = parser_impl_.MakeParameter(param->result_id(), type, AttributeList{});
+            auto* ast_param = parser_impl_.MakeParameter(param->result_id(), type, Attributes{});
             // Parameters are treated as const declarations.
             ast_params.Push(ast_param);
             // The value is accessible by name.
@@ -1458,7 +1443,7 @@ bool FunctionEmitter::ParseFunctionDeclaration(FunctionDeclaration* decl) {
     decl->name = name;
     decl->params = std::move(ast_params);
     decl->return_type = ret_ty;
-    decl->attributes.Clear();
+    decl->attributes = {};
 
     return success();
 }
@@ -2523,7 +2508,7 @@ bool FunctionEmitter::EmitFunctionVariables() {
         }
         auto* var = parser_impl_.MakeVar(inst.result_id(), builtin::AddressSpace::kUndefined,
                                          builtin::Access::kUndefined, var_store_type, initializer,
-                                         AttributeList{});
+                                         Attributes{});
         auto* var_decl_stmt = create<ast::VariableDeclStatement>(Source{}, var);
         AddStatement(var_decl_stmt);
         auto* var_type = ty_.Reference(var_store_type, builtin::AddressSpace::kUndefined);
@@ -3370,7 +3355,7 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
         AddStatement(create<ast::VariableDeclStatement>(
             Source{},
             parser_impl_.MakeVar(id, builtin::AddressSpace::kUndefined, builtin::Access::kUndefined,
-                                 store_type, nullptr, AttributeList{})));
+                                 store_type, nullptr, Attributes{})));
         auto* type = ty_.Reference(store_type, builtin::AddressSpace::kUndefined);
         identifier_types_.emplace(id, type);
     }
diff --git a/src/tint/reader/spirv/function.h b/src/tint/reader/spirv/function.h
index 345896a2ea..a07309d8c4 100644
--- a/src/tint/reader/spirv/function.h
+++ b/src/tint/reader/spirv/function.h
@@ -25,6 +25,7 @@
 #include <vector>
 
 #include "src/tint/program_builder.h"
+#include "src/tint/reader/spirv/attributes.h"
 #include "src/tint/reader/spirv/construct.h"
 #include "src/tint/reader/spirv/parser_impl.h"
 
@@ -420,7 +421,6 @@ class StatementBuilder : public Castable<StatementBuilder, ast::Statement> {
 
 /// A FunctionEmitter emits a SPIR-V function onto a Tint AST module.
 class FunctionEmitter {
-    using AttributeList = utils::Vector<const ast::Attribute*, 8>;
     using StructMemberList = utils::Vector<const ast::StructMember*, 8>;
     using ExpressionList = utils::Vector<const ast::Expression*, 8>;
     using ParameterList = utils::Vector<const ast::Parameter*, 8>;
@@ -473,32 +473,31 @@ class FunctionEmitter {
     /// @returns false if emission failed.
     bool EmitEntryPointAsWrapper();
 
-    /// Creates one or more entry point input parameters corresponding to a
-    /// part of an input variable.  The part of the input variable is specfied
-    /// by the `index_prefix`, which successively indexes into the variable.
-    /// Also generates the assignment statements that copy the input parameter
-    /// to the corresponding part of the variable.  Assumes the variable
-    /// has already been created in the Private address space.
+    /// Creates one or more entry point input parameters corresponding to a part of an input
+    /// variable.  The part of the input variable is specfied by the `index_prefix`, which
+    /// successively indexes into the variable. Also generates the assignment statements that copy
+    /// the input parameter to the corresponding part of the variable.  Assumes the variable has
+    /// already been created in the Private address space.
     /// @param var_name The name of the variable
     /// @param var_type The store type of the variable
-    /// @param decos The variable's decorations
-    /// @param index_prefix Indices stepping into the variable, indicating
-    /// what part of the variable to populate.
-    /// @param tip_type The type of the component inside variable, after indexing
-    /// with the indices in `index_prefix`.
-    /// @param forced_param_type The type forced by WGSL, if the variable is a
-    /// builtin, otherwise the same as var_type.
+    /// @param attributes The variable's attributes
+    /// @param index_prefix Indices stepping into the variable, indicating what part of the variable
+    /// to populate.
+    /// @param tip_type The type of the component inside variable, after indexing with the indices
+    /// in `index_prefix`.
+    /// @param forced_param_type The type forced by WGSL, if the variable is a builtin, otherwise
+    /// the same as var_type.
     /// @param params The parameter list where the new parameter is appended.
     /// @param statements The statement list where the assignment is appended.
     /// @returns false if emission failed
     bool EmitPipelineInput(std::string var_name,
                            const Type* var_type,
-                           AttributeList* decos,
                            utils::Vector<int, 8> index_prefix,
                            const Type* tip_type,
                            const Type* forced_param_type,
-                           ParameterList* params,
-                           StatementList* statements);
+                           Attributes& attributes,
+                           ParameterList& params,
+                           StatementList& statements);
 
     /// Creates one or more struct members from an output variable, and the
     /// expressions that compute the value they contribute to the entry point
@@ -507,31 +506,31 @@ class FunctionEmitter {
     /// Assumes the variable has already been created in the Private address space
     /// @param var_name The name of the variable
     /// @param var_type The store type of the variable
-    /// @param decos The variable's decorations
     /// @param index_prefix Indices stepping into the variable, indicating what part of the variable
     /// to populate.
     /// @param tip_type The type of the component inside variable, after indexing with the indices
     /// in `index_prefix`.
     /// @param forced_member_type The type forced by WGSL, if the variable is a builtin, otherwise
     /// the same as var_type.
+    /// @param attributes The variable's attributes
     /// @param return_members The struct member list where the new member is added.
     /// @param return_exprs The expression list where the return expression is added.
     /// @returns false if emission failed
     bool EmitPipelineOutput(std::string var_name,
                             const Type* var_type,
-                            AttributeList* decos,
                             utils::Vector<int, 8> index_prefix,
                             const Type* tip_type,
                             const Type* forced_member_type,
-                            StructMemberList* return_members,
-                            ExpressionList* return_exprs);
+                            Attributes& attributes,
+                            StructMemberList& return_members,
+                            ExpressionList& return_exprs);
 
     /// Updates the attribute list, replacing an existing Location attribute
     /// with another having one higher location value. Does nothing if no
     /// location attribute exists.
     /// Assumes the list contains at most one Location attribute.
     /// @param attributes the attribute list to modify
-    void IncrementLocation(AttributeList* attributes);
+    void IncrementLocation(Attributes& attributes);
 
     /// Create an ast::BlockStatement representing the body of the function.
     /// This creates the statement stack, which is non-empty for the lifetime
@@ -976,7 +975,7 @@ class FunctionEmitter {
         /// Function return type
         const Type* return_type;
         /// Function attributes
-        AttributeList attributes;
+        Attributes attributes;
     };
 
     /// Parse the function declaration, which comprises the name, parameters, and
diff --git a/src/tint/reader/spirv/namer.cc b/src/tint/reader/spirv/namer.cc
index 1233157029..3e1f88029c 100644
--- a/src/tint/reader/spirv/namer.cc
+++ b/src/tint/reader/spirv/namer.cc
@@ -26,32 +26,146 @@ namespace {
 
 const char* kWGSLReservedWords[] = {
     // Please keep this list sorted
-    "array",      "as",          "asm",
-    "bf16",       "binding",     "block",
-    "bool",       "break",       "builtin",
-    "case",       "cast",        "compute",
-    "const",      "continue",    "default",
-    "discard",    "do",          "else",
-    "elseif",     "entry_point", "enum",
-    "f16",        "f32",         "fallthrough",
-    "false",      "fn",          "for",
-    "fragment",   "i16",         "i32",
-    "i64",        "i8",          "if",
-    "image",      "import",      "in",
-    "let",        "location",    "loop",
-    "mat2x2",     "mat2x3",      "mat2x4",
-    "mat3x2",     "mat3x3",      "mat3x4",
-    "mat4x2",     "mat4x3",      "mat4x4",
-    "offset",     "out",         "override",
-    "premerge",   "private",     "ptr",
-    "regardless", "return",      "set",
-    "storage",    "struct",      "switch",
-    "true",       "type",        "typedef",
-    "u16",        "u32",         "u64",
-    "u8",         "uniform",     "uniform_constant",
-    "unless",     "using",       "var",
-    "vec2",       "vec3",        "vec4",
-    "vertex",     "void",        "while",
+    "array",
+    "as",
+    "asm",
+    "atomic",
+    "bf16",
+    "binding",
+    "block",
+    "bool",
+    "break",
+    "builtin",
+    "case",
+    "cast",
+    "compute",
+    "const",
+    "continue",
+    "default",
+    "discard",
+    "do",
+    "else",
+    "elseif",
+    "entry_point",
+    "enum",
+    "f16",
+    "f32",
+    "fallthrough",
+    "false",
+    "fn",
+    "for",
+    "frag_depth",
+    "fragment",
+    "front_facing",
+    "global_invocation_id",
+    "i16",
+    "i32",
+    "i64",
+    "i8",
+    "if",
+    "image",
+    "import",
+    "in",
+    "instance_index",
+    "let",
+    "local_invocation_id",
+    "local_invocation_index",
+    "location",
+    "loop",
+    "mat2x2",
+    "mat2x2f",
+    "mat2x2h",
+    "mat2x3",
+    "mat2x3f",
+    "mat2x3h",
+    "mat2x4",
+    "mat2x4f",
+    "mat2x4h",
+    "mat3x2",
+    "mat3x2f",
+    "mat3x2h",
+    "mat3x3",
+    "mat3x3f",
+    "mat3x3h",
+    "mat3x4",
+    "mat3x4f",
+    "mat3x4h",
+    "mat4x2",
+    "mat4x2f",
+    "mat4x2h",
+    "mat4x3",
+    "mat4x3f",
+    "mat4x3h",
+    "mat4x4",
+    "mat4x4f",
+    "mat4x4h",
+    "num_workgroups",
+    "offset",
+    "out",
+    "override",
+    "position",
+    "premerge",
+    "private",
+    "ptr",
+    "regardless",
+    "return",
+    "sample_index",
+    "sample_mask",
+    "sampler_comparison",
+    "sampler",
+    "set",
+    "storage",
+    "struct",
+    "switch",
+    "texture_1d",
+    "texture_2d_array",
+    "texture_2d",
+    "texture_3d",
+    "texture_cube_array",
+    "texture_cube",
+    "texture_depth_2d_array",
+    "texture_depth_2d",
+    "texture_depth_cube_array",
+    "texture_depth_cube",
+    "texture_depth_multisampled_2d",
+    "texture_external",
+    "texture_multisampled_2d",
+    "texture_storage_1d",
+    "texture_storage_2d_array",
+    "texture_storage_2d",
+    "texture_storage_3d",
+    "true",
+    "type",
+    "typedef",
+    "u16",
+    "u32",
+    "u64",
+    "u8",
+    "uniform_constant",
+    "uniform",
+    "unless",
+    "using",
+    "var",
+    "vec2",
+    "vec2f",
+    "vec2h",
+    "vec2i",
+    "vec2u",
+    "vec3",
+    "vec3f",
+    "vec3h",
+    "vec3i",
+    "vec3u",
+    "vec4",
+    "vec4f",
+    "vec4h",
+    "vec4i",
+    "vec4u",
+    "vertex_index",
+    "vertex",
+    "void",
+    "while",
+    "workgroup_id",
     "workgroup",
 };
 
diff --git a/src/tint/reader/spirv/parser_impl.cc b/src/tint/reader/spirv/parser_impl.cc
index 35df78983c..e615e14796 100644
--- a/src/tint/reader/spirv/parser_impl.cc
+++ b/src/tint/reader/spirv/parser_impl.cc
@@ -461,49 +461,42 @@ std::string ParserImpl::ShowType(uint32_t type_id) {
     return "SPIR-V type " + std::to_string(type_id);
 }
 
-ParserImpl::AttributeList ParserImpl::ConvertMemberDecoration(uint32_t struct_type_id,
-                                                              uint32_t member_index,
-                                                              const Type* member_ty,
-                                                              const Decoration& decoration) {
+Attributes ParserImpl::ConvertMemberDecoration(uint32_t struct_type_id,
+                                               uint32_t member_index,
+                                               const Type* member_ty,
+                                               const Decoration& decoration) {
     if (decoration.empty()) {
         Fail() << "malformed SPIR-V decoration: it's empty";
         return {};
     }
+    Attributes out;
     switch (static_cast<spv::Decoration>(decoration[0])) {
-        case spv::Decoration::Offset:
+        case spv::Decoration::Offset: {
             if (decoration.size() != 2) {
                 Fail() << "malformed Offset decoration: expected 1 literal operand, has "
                        << decoration.size() - 1 << ": member " << member_index << " of "
                        << ShowType(struct_type_id);
                 return {};
             }
-            return {
-                builder_.MemberOffset(Source{}, AInt(decoration[1])),
-            };
-        case spv::Decoration::NonReadable:
-            // WGSL doesn't have a member decoration for this.  Silently drop it.
-            return {};
-        case spv::Decoration::NonWritable:
-            // WGSL doesn't have a member decoration for this.
-            return {};
-        case spv::Decoration::ColMajor:
-            // WGSL only supports column major matrices.
-            return {};
-        case spv::Decoration::RelaxedPrecision:
-            // WGSL doesn't support relaxed precision.
-            return {};
+            out.Add(builder_.MemberOffset(Source{}, AInt(decoration[1])));
+            break;
+        }
+        case spv::Decoration::NonReadable:       // WGSL doesn't have a member decoration for this.
+        case spv::Decoration::NonWritable:       // WGSL doesn't have a member decoration for this.
+        case spv::Decoration::ColMajor:          // WGSL only supports column major matrices.
+        case spv::Decoration::RelaxedPrecision:  // WGSL doesn't support relaxed precision.
+            break;
         case spv::Decoration::RowMajor:
             Fail() << "WGSL does not support row-major matrices: can't "
                       "translate member "
                    << member_index << " of " << ShowType(struct_type_id);
-            return {};
+            break;
         case spv::Decoration::MatrixStride: {
             if (decoration.size() != 2) {
-                Fail() << "malformed MatrixStride decoration: expected 1 literal "
-                          "operand, has "
+                Fail() << "malformed MatrixStride decoration: expected 1 literal operand, has "
                        << decoration.size() - 1 << ": member " << member_index << " of "
                        << ShowType(struct_type_id);
-                return {};
+                break;
             }
             uint32_t stride = decoration[1];
             auto* ty = member_ty->UnwrapAlias();
@@ -513,31 +506,30 @@ ParserImpl::AttributeList ParserImpl::ConvertMemberDecoration(uint32_t struct_ty
             auto* mat = ty->As<Matrix>();
             if (!mat) {
                 Fail() << "MatrixStride cannot be applied to type " << ty->String();
-                return {};
+                break;
             }
             uint32_t natural_stride = (mat->rows == 2) ? 8 : 16;
             if (stride == natural_stride) {
-                return {};  // Decoration matches the natural stride for the matrix
+                break;  // Decoration matches the natural stride for the matrix
             }
             if (!member_ty->Is<Matrix>()) {
-                Fail() << "custom matrix strides not currently supported on array of "
-                          "matrices";
-                return {};
+                Fail() << "custom matrix strides not currently supported on array of matrices";
+                break;
             }
-            return {
-                create<ast::StrideAttribute>(Source{}, decoration[1]),
-                builder_.ASTNodes().Create<ast::DisableValidationAttribute>(
-                    builder_.ID(), builder_.AllocateNodeID(),
-                    ast::DisabledValidation::kIgnoreStrideAttribute),
-            };
-        }
-        default:
-            // TODO(dneto): Support the remaining member decorations.
+            out.Add(create<ast::StrideAttribute>(Source{}, decoration[1]));
+            out.Add(builder_.ASTNodes().Create<ast::DisableValidationAttribute>(
+                builder_.ID(), builder_.AllocateNodeID(),
+                ast::DisabledValidation::kIgnoreStrideAttribute));
             break;
+        }
+        default: {
+            // TODO(dneto): Support the remaining member decorations.
+            Fail() << "unhandled member decoration: " << decoration[0] << " on member "
+                   << member_index << " of " << ShowType(struct_type_id);
+            break;
+        }
     }
-    Fail() << "unhandled member decoration: " << decoration[0] << " on member " << member_index
-           << " of " << ShowType(struct_type_id);
-    return {};
+    return out;
 }
 
 bool ParserImpl::BuildInternalModule() {
@@ -1138,7 +1130,7 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
         }
 
         bool is_non_writable = false;
-        AttributeList ast_member_decorations;
+        Attributes ast_member_decorations;
         for (auto& decoration : GetDecorationsForMember(type_id, member_index)) {
             if (IsPipelineDecoration(decoration)) {
                 // IO decorations are handled when emitting the entry point.
@@ -1149,11 +1141,9 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
                 // the members are non-writable.
                 is_non_writable = true;
             } else {
-                auto decos =
+                auto attrs =
                     ConvertMemberDecoration(type_id, member_index, ast_member_ty, decoration);
-                for (auto* deco : decos) {
-                    ast_member_decorations.Push(deco);
-                }
+                ast_member_decorations.Add(attrs);
                 if (!success_) {
                     return nullptr;
                 }
@@ -1168,7 +1158,7 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
         const auto member_name = namer_.GetMemberName(type_id, member_index);
         auto* ast_struct_member =
             builder_.Member(Source{}, member_name, ast_member_ty->Build(builder_),
-                            std::move(ast_member_decorations));
+                            std::move(ast_member_decorations.list));
         ast_members.Push(ast_struct_member);
     }
 
@@ -1368,7 +1358,7 @@ bool ParserImpl::EmitScalarSpecConstants() {
                 break;
         }
         if (ast_type && ast_expr) {
-            AttributeList spec_id_decos;
+            Attributes spec_id_attrs;
             for (const auto& deco : GetDecorationsFor(inst.result_id())) {
                 if ((deco.size() == 2) && (deco[0] == uint32_t(spv::Decoration::SpecId))) {
                     const uint32_t id = deco[1];
@@ -1378,12 +1368,12 @@ bool ParserImpl::EmitScalarSpecConstants() {
                                       << inst.result_id() << " has SpecId " << id;
                     }
                     auto* cid = builder_.Id(Source{}, AInt(id));
-                    spec_id_decos.Push(cid);
+                    spec_id_attrs.Add(cid);
                     break;
                 }
             }
             auto* ast_var =
-                MakeOverride(inst.result_id(), ast_type, ast_expr, std::move(spec_id_decos));
+                MakeOverride(inst.result_id(), ast_type, ast_expr, std::move(spec_id_attrs));
             if (ast_var) {
                 scalar_spec_constants_.insert(inst.result_id());
             }
@@ -1506,7 +1496,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
         }
         auto ast_access = VarAccess(ast_store_type, ast_address_space);
         auto* ast_var = MakeVar(var.result_id(), ast_address_space, ast_access, ast_store_type,
-                                ast_initializer, utils::Empty);
+                                ast_initializer, Attributes{});
         // TODO(dneto): initializers (a.k.a. initializer expression)
         if (ast_var) {
             builder_.AST().AddGlobalVariable(ast_var);
@@ -1596,7 +1586,7 @@ const ast::Var* ParserImpl::MakeVar(uint32_t id,
                                     builtin::Access access,
                                     const Type* storage_type,
                                     const ast::Expression* initializer,
-                                    AttributeList decorations) {
+                                    Attributes attrs) {
     if (storage_type == nullptr) {
         Fail() << "internal error: can't make ast::Variable for null type";
         return nullptr;
@@ -1608,14 +1598,14 @@ const ast::Var* ParserImpl::MakeVar(uint32_t id,
         address_space = builtin::AddressSpace::kUndefined;
     }
 
-    if (!ConvertDecorationsForVariable(id, &storage_type, &decorations,
+    if (!ConvertDecorationsForVariable(id, &storage_type, attrs,
                                        address_space != builtin::AddressSpace::kPrivate)) {
         return nullptr;
     }
 
     auto sym = builder_.Symbols().Register(namer_.Name(id));
     return builder_.Var(Source{}, sym, storage_type->Build(builder_), address_space, access,
-                        initializer, decorations);
+                        initializer, std::move(attrs.list));
 }
 
 const ast::Let* ParserImpl::MakeLet(uint32_t id,
@@ -1628,28 +1618,27 @@ const ast::Let* ParserImpl::MakeLet(uint32_t id,
 const ast::Override* ParserImpl::MakeOverride(uint32_t id,
                                               const Type* type,
                                               const ast::Expression* initializer,
-                                              AttributeList decorations) {
-    if (!ConvertDecorationsForVariable(id, &type, &decorations, false)) {
+                                              Attributes attrs) {
+    if (!ConvertDecorationsForVariable(id, &type, attrs, false)) {
         return nullptr;
     }
     auto sym = builder_.Symbols().Register(namer_.Name(id));
-    return builder_.Override(Source{}, sym, type->Build(builder_), initializer, decorations);
+    return builder_.Override(Source{}, sym, type->Build(builder_), initializer,
+                             std::move(attrs.list));
 }
 
-const ast::Parameter* ParserImpl::MakeParameter(uint32_t id,
-                                                const Type* type,
-                                                AttributeList decorations) {
-    if (!ConvertDecorationsForVariable(id, &type, &decorations, false)) {
+const ast::Parameter* ParserImpl::MakeParameter(uint32_t id, const Type* type, Attributes attrs) {
+    if (!ConvertDecorationsForVariable(id, &type, attrs, false)) {
         return nullptr;
     }
 
     auto sym = builder_.Symbols().Register(namer_.Name(id));
-    return builder_.Param(Source{}, sym, type->Build(builder_), decorations);
+    return builder_.Param(Source{}, sym, type->Build(builder_), attrs.list);
 }
 
 bool ParserImpl::ConvertDecorationsForVariable(uint32_t id,
                                                const Type** store_type,
-                                               AttributeList* decorations,
+                                               Attributes& attrs,
                                                bool transfer_pipeline_io) {
     DecorationList non_builtin_pipeline_decorations;
     for (auto& deco : GetDecorationsFor(id)) {
@@ -1709,7 +1698,7 @@ bool ParserImpl::ConvertDecorationsForVariable(uint32_t id,
                 return false;
             }
             if (transfer_pipeline_io) {
-                decorations->Push(create<ast::BuiltinAttribute>(Source{}, ast_builtin));
+                attrs.Add(builder_, Source{}, ast_builtin);
             }
         }
         if (transfer_pipeline_io && IsPipelineDecoration(deco)) {
@@ -1720,19 +1709,18 @@ bool ParserImpl::ConvertDecorationsForVariable(uint32_t id,
                 return Fail() << "malformed DescriptorSet decoration on ID " << id
                               << ": has no operand";
             }
-            decorations->Push(builder_.Group(Source{}, AInt(deco[1])));
+            attrs.Add(builder_.Group(Source{}, AInt(deco[1])));
         }
         if (deco[0] == uint32_t(spv::Decoration::Binding)) {
             if (deco.size() == 1) {
                 return Fail() << "malformed Binding decoration on ID " << id << ": has no operand";
             }
-            decorations->Push(builder_.Binding(Source{}, AInt(deco[1])));
+            attrs.Add(builder_.Binding(Source{}, AInt(deco[1])));
         }
     }
 
     if (transfer_pipeline_io) {
-        if (!ConvertPipelineDecorations(*store_type, non_builtin_pipeline_decorations,
-                                        decorations)) {
+        if (!ConvertPipelineDecorations(*store_type, non_builtin_pipeline_decorations, attrs)) {
             return false;
         }
     }
@@ -1753,11 +1741,11 @@ DecorationList ParserImpl::GetMemberPipelineDecorations(const Struct& struct_typ
     return result;
 }
 
-void ParserImpl::SetLocation(AttributeList* attributes, const ast::Attribute* replacement) {
+void ParserImpl::SetLocation(Attributes& attributes, const ast::Attribute* replacement) {
     if (!replacement) {
         return;
     }
-    for (auto*& attribute : *attributes) {
+    for (auto*& attribute : attributes.list) {
         if (attribute->Is<ast::LocationAttribute>()) {
             // Replace this location attribute with the replacement.
             // The old one doesn't leak because it's kept in the builder's AST node
@@ -1767,13 +1755,13 @@ void ParserImpl::SetLocation(AttributeList* attributes, const ast::Attribute* re
         }
     }
     // The list didn't have a location. Add it.
-    attributes->Push(replacement);
+    attributes.Add(replacement);
     return;
 }
 
 bool ParserImpl::ConvertPipelineDecorations(const Type* store_type,
                                             const DecorationList& decorations,
-                                            AttributeList* attributes) {
+                                            Attributes& attributes) {
     // Vulkan defaults to perspective-correct interpolation.
     builtin::InterpolationType type = builtin::InterpolationType::kPerspective;
     builtin::InterpolationSampling sampling = builtin::InterpolationSampling::kUndefined;
@@ -1783,8 +1771,8 @@ bool ParserImpl::ConvertPipelineDecorations(const Type* store_type,
         switch (static_cast<spv::Decoration>(deco[0])) {
             case spv::Decoration::Location:
                 if (deco.size() != 2) {
-                    return Fail() << "malformed Location decoration on ID requires one "
-                                     "literal operand";
+                    return Fail()
+                           << "malformed Location decoration on ID requires one literal operand";
                 }
                 SetLocation(attributes, builder_.Location(AInt(deco[1])));
                 if (store_type->IsIntegerScalarOrVector()) {
@@ -1821,8 +1809,7 @@ bool ParserImpl::ConvertPipelineDecorations(const Type* store_type,
         }
     }
 
-    if (type == builtin::InterpolationType::kFlat &&
-        !ast::HasAttribute<ast::LocationAttribute>(*attributes)) {
+    if (type == builtin::InterpolationType::kFlat && !attributes.Has<ast::LocationAttribute>()) {
         // WGSL requires that '@interpolate(flat)' needs to be paired with '@location', however
         // SPIR-V requires all fragment shader integer Inputs are 'flat'. If the decorations do not
         // contain a spv::Decoration::Location, then make this perspective.
@@ -1834,7 +1821,7 @@ bool ParserImpl::ConvertPipelineDecorations(const Type* store_type,
         sampling == builtin::InterpolationSampling::kUndefined) {
         // This is the default. Don't add a decoration.
     } else {
-        attributes->Push(create<ast::InterpolateAttribute>(type, sampling));
+        attributes.Add(create<ast::InterpolateAttribute>(type, sampling));
     }
 
     return success();
diff --git a/src/tint/reader/spirv/parser_impl.h b/src/tint/reader/spirv/parser_impl.h
index cd88b157d1..36c24de046 100644
--- a/src/tint/reader/spirv/parser_impl.h
+++ b/src/tint/reader/spirv/parser_impl.h
@@ -37,6 +37,7 @@ TINT_END_DISABLE_WARNING(NEWLINE_EOF);
 
 #include "src/tint/program_builder.h"
 #include "src/tint/reader/reader.h"
+#include "src/tint/reader/spirv/attributes.h"
 #include "src/tint/reader/spirv/entry_point_info.h"
 #include "src/tint/reader/spirv/enum_converter.h"
 #include "src/tint/reader/spirv/namer.h"
@@ -122,7 +123,6 @@ struct WorkgroupSizeInfo {
 
 /// Parser implementation for SPIR-V.
 class ParserImpl : Reader {
-    using AttributeList = utils::Vector<const ast::Attribute*, 8>;
     using ExpressionList = utils::Vector<const ast::Expression*, 8>;
 
   public:
@@ -261,7 +261,7 @@ class ParserImpl : Reader {
     /// @returns false when the variable should not be emitted as a variable
     bool ConvertDecorationsForVariable(uint32_t id,
                                        const Type** store_type,
-                                       AttributeList* attributes,
+                                       Attributes& attributes,
                                        bool transfer_pipeline_io);
 
     /// Converts SPIR-V decorations for pipeline IO into AST decorations.
@@ -271,15 +271,15 @@ class ParserImpl : Reader {
     /// @returns false if conversion fails
     bool ConvertPipelineDecorations(const Type* store_type,
                                     const DecorationList& decorations,
-                                    AttributeList* attributes);
+                                    Attributes& attributes);
 
     /// Updates the attribute list, placing a non-null location decoration into
     /// the list, replacing an existing one if it exists. Does nothing if the
     /// replacement is nullptr.
     /// Assumes the list contains at most one Location decoration.
-    /// @param decos the attribute list to modify
+    /// @param attributes the attribute list to modify
     /// @param replacement the location decoration to place into the list
-    void SetLocation(AttributeList* decos, const ast::Attribute* replacement);
+    void SetLocation(Attributes& attributes, const ast::Attribute* replacement);
 
     /// Converts a SPIR-V struct member decoration into a number of AST
     /// decorations. If the decoration is recognized but deliberately dropped,
@@ -290,10 +290,10 @@ class ParserImpl : Reader {
     /// @param member_ty the type of the member
     /// @param decoration an encoded SPIR-V Decoration
     /// @returns the AST decorations
-    AttributeList ConvertMemberDecoration(uint32_t struct_type_id,
-                                          uint32_t member_index,
-                                          const Type* member_ty,
-                                          const Decoration& decoration);
+    Attributes ConvertMemberDecoration(uint32_t struct_type_id,
+                                       uint32_t member_index,
+                                       const Type* member_ty,
+                                       const Decoration& decoration);
 
     /// Returns a string for the given type.  If the type ID is invalid,
     /// then the resulting string only names the type ID.
@@ -433,7 +433,7 @@ class ParserImpl : Reader {
     /// @param access the access
     /// @param storage_type the storage type of the variable
     /// @param initializer the variable initializer
-    /// @param decorations the variable decorations
+    /// @param attributes the variable attributes
     /// @returns a new Variable node, or null in the ignorable variable case and
     /// in the error case
     const ast::Var* MakeVar(uint32_t id,
@@ -441,7 +441,7 @@ class ParserImpl : Reader {
                             builtin::Access access,
                             const Type* storage_type,
                             const ast::Expression* initializer,
-                            AttributeList decorations);
+                            Attributes attributes);
 
     /// Creates an AST 'let' node for a SPIR-V ID, including any attached decorations,.
     /// @param id the SPIR-V result ID
@@ -454,20 +454,20 @@ class ParserImpl : Reader {
     /// @param id the SPIR-V result ID
     /// @param type the type of the variable
     /// @param initializer the variable initializer
-    /// @param decorations the variable decorations
+    /// @param attributes the variable attributes
     /// @returns the AST 'override' node
     const ast::Override* MakeOverride(uint32_t id,
                                       const Type* type,
                                       const ast::Expression* initializer,
-                                      AttributeList decorations);
+                                      Attributes attributes);
 
     /// Creates an AST parameter node for a SPIR-V ID, including any attached decorations, unless
     /// it's an ignorable builtin variable.
     /// @param id the SPIR-V result ID
     /// @param type the type of the parameter
-    /// @param decorations the parameter decorations
+    /// @param attributes the parameter attributes
     /// @returns the AST parameter node
-    const ast::Parameter* MakeParameter(uint32_t id, const Type* type, AttributeList decorations);
+    const ast::Parameter* MakeParameter(uint32_t id, const Type* type, Attributes attributes);
 
     /// Returns true if a constant expression can be generated.
     /// @param id the SPIR-V ID of the value
diff --git a/src/tint/reader/spirv/parser_impl_convert_member_decoration_test.cc b/src/tint/reader/spirv/parser_impl_convert_member_decoration_test.cc
index 402cc41e9a..d67ccf07d5 100644
--- a/src/tint/reader/spirv/parser_impl_convert_member_decoration_test.cc
+++ b/src/tint/reader/spirv/parser_impl_convert_member_decoration_test.cc
@@ -24,7 +24,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_IsEmpty) {
     auto p = parser(std::vector<uint32_t>{});
 
     auto result = p->ConvertMemberDecoration(1, 1, nullptr, {});
-    EXPECT_TRUE(result.IsEmpty());
+    EXPECT_TRUE(result.list.IsEmpty());
     EXPECT_THAT(p->error(), Eq("malformed SPIR-V decoration: it's empty"));
 }
 
@@ -32,7 +32,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_OffsetWithoutOperand) {
     auto p = parser(std::vector<uint32_t>{});
 
     auto result = p->ConvertMemberDecoration(12, 13, nullptr, {uint32_t(spv::Decoration::Offset)});
-    EXPECT_TRUE(result.IsEmpty());
+    EXPECT_TRUE(result.list.IsEmpty());
     EXPECT_THAT(p->error(), Eq("malformed Offset decoration: expected 1 literal "
                                "operand, has 0: member 13 of SPIR-V type 12"));
 }
@@ -42,7 +42,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_OffsetWithTooManyOperands) {
 
     auto result =
         p->ConvertMemberDecoration(12, 13, nullptr, {uint32_t(spv::Decoration::Offset), 3, 4});
-    EXPECT_TRUE(result.IsEmpty());
+    EXPECT_TRUE(result.list.IsEmpty());
     EXPECT_THAT(p->error(), Eq("malformed Offset decoration: expected 1 literal "
                                "operand, has 2: member 13 of SPIR-V type 12"));
 }
@@ -51,9 +51,9 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Offset) {
     auto p = parser(std::vector<uint32_t>{});
 
     auto result = p->ConvertMemberDecoration(1, 1, nullptr, {uint32_t(spv::Decoration::Offset), 8});
-    ASSERT_FALSE(result.IsEmpty());
-    EXPECT_TRUE(result[0]->Is<ast::StructMemberOffsetAttribute>());
-    auto* offset_deco = result[0]->As<ast::StructMemberOffsetAttribute>();
+    ASSERT_FALSE(result.list.IsEmpty());
+    EXPECT_TRUE(result.list[0]->Is<ast::StructMemberOffsetAttribute>());
+    auto* offset_deco = result.list[0]->As<ast::StructMemberOffsetAttribute>();
     ASSERT_NE(offset_deco, nullptr);
     ASSERT_TRUE(offset_deco->expr->Is<ast::IntLiteralExpression>());
     EXPECT_EQ(offset_deco->expr->As<ast::IntLiteralExpression>()->value, 8u);
@@ -67,7 +67,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Matrix2x2_Stride_Natural) {
     spirv::Matrix matrix(&f32, 2, 2);
     auto result =
         p->ConvertMemberDecoration(1, 1, &matrix, {uint32_t(spv::Decoration::MatrixStride), 8});
-    EXPECT_TRUE(result.IsEmpty());
+    EXPECT_TRUE(result.list.IsEmpty());
     EXPECT_TRUE(p->error().empty());
 }
 
@@ -78,9 +78,9 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Matrix2x2_Stride_Custom) {
     spirv::Matrix matrix(&f32, 2, 2);
     auto result =
         p->ConvertMemberDecoration(1, 1, &matrix, {uint32_t(spv::Decoration::MatrixStride), 16});
-    ASSERT_FALSE(result.IsEmpty());
-    EXPECT_TRUE(result[0]->Is<ast::StrideAttribute>());
-    auto* stride_deco = result[0]->As<ast::StrideAttribute>();
+    ASSERT_FALSE(result.list.IsEmpty());
+    EXPECT_TRUE(result.list[0]->Is<ast::StrideAttribute>());
+    auto* stride_deco = result.list[0]->As<ast::StrideAttribute>();
     ASSERT_NE(stride_deco, nullptr);
     EXPECT_EQ(stride_deco->stride, 16u);
     EXPECT_TRUE(p->error().empty());
@@ -93,7 +93,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Matrix2x4_Stride_Natural) {
     spirv::Matrix matrix(&f32, 2, 4);
     auto result =
         p->ConvertMemberDecoration(1, 1, &matrix, {uint32_t(spv::Decoration::MatrixStride), 16});
-    EXPECT_TRUE(result.IsEmpty());
+    EXPECT_TRUE(result.list.IsEmpty());
     EXPECT_TRUE(p->error().empty());
 }
 
@@ -104,9 +104,9 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Matrix2x4_Stride_Custom) {
     spirv::Matrix matrix(&f32, 2, 4);
     auto result =
         p->ConvertMemberDecoration(1, 1, &matrix, {uint32_t(spv::Decoration::MatrixStride), 64});
-    ASSERT_FALSE(result.IsEmpty());
-    EXPECT_TRUE(result[0]->Is<ast::StrideAttribute>());
-    auto* stride_deco = result[0]->As<ast::StrideAttribute>();
+    ASSERT_FALSE(result.list.IsEmpty());
+    EXPECT_TRUE(result.list[0]->Is<ast::StrideAttribute>());
+    auto* stride_deco = result.list[0]->As<ast::StrideAttribute>();
     ASSERT_NE(stride_deco, nullptr);
     EXPECT_EQ(stride_deco->stride, 64u);
     EXPECT_TRUE(p->error().empty());
@@ -119,9 +119,9 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_Matrix2x3_Stride_Custom) {
     spirv::Matrix matrix(&f32, 2, 3);
     auto result =
         p->ConvertMemberDecoration(1, 1, &matrix, {uint32_t(spv::Decoration::MatrixStride), 32});
-    ASSERT_FALSE(result.IsEmpty());
-    EXPECT_TRUE(result[0]->Is<ast::StrideAttribute>());
-    auto* stride_deco = result[0]->As<ast::StrideAttribute>();
+    ASSERT_FALSE(result.list.IsEmpty());
+    EXPECT_TRUE(result.list[0]->Is<ast::StrideAttribute>());
+    auto* stride_deco = result.list[0]->As<ast::StrideAttribute>();
     ASSERT_NE(stride_deco, nullptr);
     EXPECT_EQ(stride_deco->stride, 32u);
     EXPECT_TRUE(p->error().empty());
@@ -135,7 +135,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_RelaxedPrecision) {
 
     auto result =
         p->ConvertMemberDecoration(1, 1, nullptr, {uint32_t(spv::Decoration::RelaxedPrecision)});
-    EXPECT_TRUE(result.IsEmpty());
+    EXPECT_TRUE(result.list.IsEmpty());
     EXPECT_TRUE(p->error().empty());
 }
 
@@ -143,7 +143,7 @@ TEST_F(SpvParserTest, ConvertMemberDecoration_UnhandledDecoration) {
     auto p = parser(std::vector<uint32_t>{});
 
     auto result = p->ConvertMemberDecoration(12, 13, nullptr, {12345678});
-    EXPECT_TRUE(result.IsEmpty());
+    EXPECT_TRUE(result.list.IsEmpty());
     EXPECT_THAT(p->error(), Eq("unhandled member decoration: 12345678 on member "
                                "13 of SPIR-V type 12"));
 }
diff --git a/src/tint/reader/spirv/parser_impl_module_var_test.cc b/src/tint/reader/spirv/parser_impl_module_var_test.cc
index 5077a51963..c731fbfee4 100644
--- a/src/tint/reader/spirv/parser_impl_module_var_test.cc
+++ b/src/tint/reader/spirv/parser_impl_module_var_test.cc
@@ -2861,7 +2861,7 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_I32_Load_Direct) {
     const auto module_str = test::ToString(p->program());
     const std::string expected = R"(var<private> x_1 : i32;
 
-var<private> position : vec4<f32>;
+var<private> position_1 : vec4<f32>;
 
 fn main_1() {
   let x_2 : i32 = x_1;
@@ -2870,14 +2870,14 @@ fn main_1() {
 
 struct main_out {
   @builtin(position)
-  position_1 : vec4<f32>,
+  position_1_1 : vec4<f32>,
 }
 
 @vertex
 fn main(@builtin(instance_index) x_1_param : u32) -> main_out {
   x_1 = bitcast<i32>(x_1_param);
   main_1();
-  return main_out(position);
+  return main_out(position_1);
 }
 )";
     EXPECT_EQ(module_str, expected) << module_str;
@@ -2898,7 +2898,7 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_I32_Load_CopyObject) {
     const auto module_str = test::ToString(p->program());
     const std::string expected = R"(var<private> x_1 : i32;
 
-var<private> position : vec4<f32>;
+var<private> position_1 : vec4<f32>;
 
 fn main_1() {
   let x_14 : ptr<private, i32> = &(x_1);
@@ -2908,14 +2908,14 @@ fn main_1() {
 
 struct main_out {
   @builtin(position)
-  position_1 : vec4<f32>,
+  position_1_1 : vec4<f32>,
 }
 
 @vertex
 fn main(@builtin(instance_index) x_1_param : u32) -> main_out {
   x_1 = bitcast<i32>(x_1_param);
   main_1();
-  return main_out(position);
+  return main_out(position_1);
 }
 )";
     EXPECT_EQ(module_str, expected) << module_str;
@@ -2936,7 +2936,7 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_I32_Load_AccessChain) {
     const auto module_str = test::ToString(p->program());
     const std::string expected = R"(var<private> x_1 : i32;
 
-var<private> position : vec4<f32>;
+var<private> position_1 : vec4<f32>;
 
 fn main_1() {
   let x_2 : i32 = x_1;
@@ -2945,14 +2945,14 @@ fn main_1() {
 
 struct main_out {
   @builtin(position)
-  position_1 : vec4<f32>,
+  position_1_1 : vec4<f32>,
 }
 
 @vertex
 fn main(@builtin(instance_index) x_1_param : u32) -> main_out {
   x_1 = bitcast<i32>(x_1_param);
   main_1();
-  return main_out(position);
+  return main_out(position_1);
 }
 )";
     EXPECT_EQ(module_str, expected) << module_str;
@@ -2995,7 +2995,7 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_U32_Load_Direct) {
     const auto module_str = test::ToString(p->program());
     const std::string expected = R"(var<private> x_1 : u32;
 
-var<private> position : vec4<f32>;
+var<private> position_1 : vec4<f32>;
 
 fn main_1() {
   let x_2 : u32 = x_1;
@@ -3004,14 +3004,14 @@ fn main_1() {
 
 struct main_out {
   @builtin(position)
-  position_1 : vec4<f32>,
+  position_1_1 : vec4<f32>,
 }
 
 @vertex
 fn main(@builtin(instance_index) x_1_param : u32) -> main_out {
   x_1 = x_1_param;
   main_1();
-  return main_out(position);
+  return main_out(position_1);
 }
 )";
     EXPECT_EQ(module_str, expected);
@@ -3032,7 +3032,7 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_U32_Load_CopyObject) {
     const auto module_str = test::ToString(p->program());
     const std::string expected = R"(var<private> x_1 : u32;
 
-var<private> position : vec4<f32>;
+var<private> position_1 : vec4<f32>;
 
 fn main_1() {
   let x_14 : ptr<private, u32> = &(x_1);
@@ -3042,14 +3042,14 @@ fn main_1() {
 
 struct main_out {
   @builtin(position)
-  position_1 : vec4<f32>,
+  position_1_1 : vec4<f32>,
 }
 
 @vertex
 fn main(@builtin(instance_index) x_1_param : u32) -> main_out {
   x_1 = x_1_param;
   main_1();
-  return main_out(position);
+  return main_out(position_1);
 }
 )";
     EXPECT_EQ(module_str, expected);
@@ -3070,7 +3070,7 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_U32_Load_AccessChain) {
     const auto module_str = test::ToString(p->program());
     const std::string expected = R"(var<private> x_1 : u32;
 
-var<private> position : vec4<f32>;
+var<private> position_1 : vec4<f32>;
 
 fn main_1() {
   let x_2 : u32 = x_1;
@@ -3079,14 +3079,14 @@ fn main_1() {
 
 struct main_out {
   @builtin(position)
-  position_1 : vec4<f32>,
+  position_1_1 : vec4<f32>,
 }
 
 @vertex
 fn main(@builtin(instance_index) x_1_param : u32) -> main_out {
   x_1 = x_1_param;
   main_1();
-  return main_out(position);
+  return main_out(position_1);
 }
 )";
     EXPECT_EQ(module_str, expected);
diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc
index c4ae32e00c..c4c90ca2c8 100644
--- a/src/tint/reader/wgsl/parser_impl.cc
+++ b/src/tint/reader/wgsl/parser_impl.cc
@@ -1125,23 +1125,6 @@ Expect<builtin::InterpolationType> ParserImpl::expect_interpolation_type_name()
                        builtin::kInterpolationTypeStrings);
 }
 
-// builtin_value_name
-//   : frag_depth
-//   | front_facing
-//   | global_invocation_id
-//   | instance_index
-//   | local_invocation_id
-//   | local_invocation_index
-//   | num_workgroups
-//   | position
-//   | sample_index
-//   | sample_mask
-//   | vertex_index
-//   | workgroup_id
-Expect<builtin::BuiltinValue> ParserImpl::expect_builtin() {
-    return expect_enum("builtin", builtin::ParseBuiltinValue, builtin::kBuiltinValueStrings);
-}
-
 // compound_statement
 //   : attribute* BRACE_LEFT statement* BRACE_RIGHT
 Expect<ast::BlockStatement*> ParserImpl::expect_compound_statement(std::string_view use) {
@@ -3020,7 +3003,7 @@ Maybe<const ast::Attribute*> ParserImpl::attribute() {
 
     if (t == "builtin") {
         return expect_paren_block("builtin attribute", [&]() -> Result {
-            auto builtin = expect_builtin();
+            auto builtin = expect_expression("builtin name");
             if (builtin.errored) {
                 return Failure::kErrored;
             }
diff --git a/src/tint/reader/wgsl/parser_impl.h b/src/tint/reader/wgsl/parser_impl.h
index 759e88d01b..19502c4201 100644
--- a/src/tint/reader/wgsl/parser_impl.h
+++ b/src/tint/reader/wgsl/parser_impl.h
@@ -462,10 +462,6 @@ class ParserImpl {
     /// value type name.
     /// @returns the parsed type name
     Expect<builtin::InterpolationType> expect_interpolation_type_name();
-    /// Parses a builtin identifier, erroring if the next token does not match a
-    /// valid builtin name.
-    /// @returns the parsed builtin.
-    Expect<builtin::BuiltinValue> expect_builtin();
     /// Parses a `compound_statement` grammar element, erroring on parse failure.
     /// @param use a description of what was being parsed if an error was raised
     /// @returns the parsed statements
diff --git a/src/tint/reader/wgsl/parser_impl_error_msg_test.cc b/src/tint/reader/wgsl/parser_impl_error_msg_test.cc
index 6b92c3c9ff..472763592c 100644
--- a/src/tint/reader/wgsl/parser_impl_error_msg_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_error_msg_test.cc
@@ -969,25 +969,6 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBuiltinMissingRParen) {
 )");
 }
 
-TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBuiltinInvalidIdentifer) {
-    EXPECT("@builtin(1) var i : i32;",
-           R"(test.wgsl:1:10 error: expected builtin
-Possible values: 'frag_depth', 'front_facing', 'global_invocation_id', 'instance_index', 'local_invocation_id', 'local_invocation_index', 'num_workgroups', 'position', 'sample_index', 'sample_mask', 'vertex_index', 'workgroup_id'
-@builtin(1) var i : i32;
-         ^
-)");
-}
-
-TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBuiltinInvalidValue) {
-    EXPECT("@builtin(frag_d3pth) var i : i32;",
-           R"(test.wgsl:1:10 error: expected builtin
-Did you mean 'frag_depth'?
-Possible values: 'frag_depth', 'front_facing', 'global_invocation_id', 'instance_index', 'local_invocation_id', 'local_invocation_index', 'num_workgroups', 'position', 'sample_index', 'sample_mask', 'vertex_index', 'workgroup_id'
-@builtin(frag_d3pth) var i : i32;
-         ^^^^^^^^^^
-)");
-}
-
 TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBindingMissingLParen) {
     EXPECT("@binding 1) var i : i32;",
            R"(test.wgsl:1:10 error: expected '(' for binding attribute
diff --git a/src/tint/reader/wgsl/parser_impl_param_list_test.cc b/src/tint/reader/wgsl/parser_impl_param_list_test.cc
index 696d79184d..eb4db4570e 100644
--- a/src/tint/reader/wgsl/parser_impl_param_list_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_param_list_test.cc
@@ -102,7 +102,8 @@ TEST_F(ParserImplTest, ParamList_Attributes) {
     auto attrs_0 = e.value[0]->attributes;
     ASSERT_EQ(attrs_0.Length(), 1u);
     EXPECT_TRUE(attrs_0[0]->Is<ast::BuiltinAttribute>());
-    EXPECT_EQ(attrs_0[0]->As<ast::BuiltinAttribute>()->builtin, builtin::BuiltinValue::kPosition);
+    ast::CheckIdentifier(p->builder().Symbols(), attrs_0[0]->As<ast::BuiltinAttribute>()->builtin,
+                         "position");
 
     ASSERT_EQ(e.value[0]->source.range.begin.line, 1u);
     ASSERT_EQ(e.value[0]->source.range.begin.column, 20u);
diff --git a/src/tint/reader/wgsl/parser_impl_variable_attribute_list_test.cc b/src/tint/reader/wgsl/parser_impl_variable_attribute_list_test.cc
index 163396e05a..24ad0204c6 100644
--- a/src/tint/reader/wgsl/parser_impl_variable_attribute_list_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_variable_attribute_list_test.cc
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "src/tint/ast/test_helper.h"
 #include "src/tint/reader/wgsl/parser_impl_test_helper.h"
 
 namespace tint::reader::wgsl {
@@ -38,7 +39,8 @@ TEST_F(ParserImplTest, AttributeList_Parses) {
     EXPECT_EQ(exp->value, 4u);
 
     ASSERT_TRUE(attr_1->Is<ast::BuiltinAttribute>());
-    EXPECT_EQ(attr_1->As<ast::BuiltinAttribute>()->builtin, builtin::BuiltinValue::kPosition);
+    ast::CheckIdentifier(p->builder().Symbols(), attr_1->As<ast::BuiltinAttribute>()->builtin,
+                         "position");
 }
 
 TEST_F(ParserImplTest, AttributeList_Invalid) {
@@ -51,27 +53,5 @@ TEST_F(ParserImplTest, AttributeList_Invalid) {
     EXPECT_EQ(p->error(), R"(1:2: expected attribute)");
 }
 
-TEST_F(ParserImplTest, AttributeList_InvalidValue) {
-    auto p = parser("@builtin(invalid)");
-    auto attrs = p->attribute_list();
-    EXPECT_TRUE(p->has_error());
-    EXPECT_TRUE(attrs.errored);
-    EXPECT_FALSE(attrs.matched);
-    EXPECT_TRUE(attrs.value.IsEmpty());
-    EXPECT_EQ(p->error(), R"(1:10: expected builtin
-Possible values: 'frag_depth', 'front_facing', 'global_invocation_id', 'instance_index', 'local_invocation_id', 'local_invocation_index', 'num_workgroups', 'position', 'sample_index', 'sample_mask', 'vertex_index', 'workgroup_id')");
-}
-
-TEST_F(ParserImplTest, AttributeList_InvalidValueSuggest) {
-    auto p = parser("@builtin(instanceindex)");
-    auto attrs = p->attribute_list();
-    EXPECT_TRUE(p->has_error());
-    EXPECT_TRUE(attrs.errored);
-    EXPECT_FALSE(attrs.matched);
-    EXPECT_TRUE(attrs.value.IsEmpty());
-    EXPECT_EQ(p->error(), R"(1:10: expected builtin
-Did you mean 'instance_index'?
-Possible values: 'frag_depth', 'front_facing', 'global_invocation_id', 'instance_index', 'local_invocation_id', 'local_invocation_index', 'num_workgroups', 'position', 'sample_index', 'sample_mask', 'vertex_index', 'workgroup_id')");
-}
 }  // namespace
 }  // namespace tint::reader::wgsl
diff --git a/src/tint/reader/wgsl/parser_impl_variable_attribute_test.cc b/src/tint/reader/wgsl/parser_impl_variable_attribute_test.cc
index 9468d1c588..67df3b5a4b 100644
--- a/src/tint/reader/wgsl/parser_impl_variable_attribute_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_variable_attribute_test.cc
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "src/tint/ast/test_helper.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/reader/wgsl/parser_impl_test_helper.h"
 
 namespace tint::reader::wgsl {
@@ -215,20 +217,11 @@ TEST_F(ParserImplTest, Attribute_Location_MissingInvalid) {
     EXPECT_EQ(p->error(), "1:10: expected location expression");
 }
 
-struct BuiltinData {
-    const char* input;
-    builtin::BuiltinValue result;
-};
-inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
-    out << std::string(data.input);
-    return out;
-}
-
-class BuiltinTest : public ParserImplTestWithParam<BuiltinData> {};
+class BuiltinTest : public ParserImplTestWithParam<builtin::BuiltinValue> {};
 
 TEST_P(BuiltinTest, Attribute_Builtin) {
-    auto params = GetParam();
-    auto p = parser(std::string("builtin(") + params.input + ")");
+    auto str = utils::ToString(GetParam());
+    auto p = parser("builtin(" + str + ")");
 
     auto attr = p->attribute();
     EXPECT_TRUE(attr.matched);
@@ -240,11 +233,11 @@ TEST_P(BuiltinTest, Attribute_Builtin) {
     ASSERT_TRUE(var_attr->Is<ast::BuiltinAttribute>());
 
     auto* builtin = var_attr->As<ast::BuiltinAttribute>();
-    EXPECT_EQ(builtin->builtin, params.result);
+    ast::CheckIdentifier(p->builder().Symbols(), builtin->builtin, str);
 }
 TEST_P(BuiltinTest, Attribute_Builtin_TrailingComma) {
-    auto params = GetParam();
-    auto p = parser(std::string("builtin(") + params.input + ",)");
+    auto str = utils::ToString(GetParam());
+    auto p = parser("builtin(" + str + ",)");
 
     auto attr = p->attribute();
     EXPECT_TRUE(attr.matched);
@@ -256,24 +249,22 @@ TEST_P(BuiltinTest, Attribute_Builtin_TrailingComma) {
     ASSERT_TRUE(var_attr->Is<ast::BuiltinAttribute>());
 
     auto* builtin = var_attr->As<ast::BuiltinAttribute>();
-    EXPECT_EQ(builtin->builtin, params.result);
+    ast::CheckIdentifier(p->builder().Symbols(), builtin->builtin, str);
 }
-INSTANTIATE_TEST_SUITE_P(
-    ParserImplTest,
-    BuiltinTest,
-    testing::Values(BuiltinData{"position", builtin::BuiltinValue::kPosition},
-                    BuiltinData{"vertex_index", builtin::BuiltinValue::kVertexIndex},
-                    BuiltinData{"instance_index", builtin::BuiltinValue::kInstanceIndex},
-                    BuiltinData{"front_facing", builtin::BuiltinValue::kFrontFacing},
-                    BuiltinData{"frag_depth", builtin::BuiltinValue::kFragDepth},
-                    BuiltinData{"local_invocation_id", builtin::BuiltinValue::kLocalInvocationId},
-                    BuiltinData{"local_invocation_index",
-                                builtin::BuiltinValue::kLocalInvocationIndex},
-                    BuiltinData{"global_invocation_id", builtin::BuiltinValue::kGlobalInvocationId},
-                    BuiltinData{"workgroup_id", builtin::BuiltinValue::kWorkgroupId},
-                    BuiltinData{"num_workgroups", builtin::BuiltinValue::kNumWorkgroups},
-                    BuiltinData{"sample_index", builtin::BuiltinValue::kSampleIndex},
-                    BuiltinData{"sample_mask", builtin::BuiltinValue::kSampleMask}));
+INSTANTIATE_TEST_SUITE_P(ParserImplTest,
+                         BuiltinTest,
+                         testing::Values(builtin::BuiltinValue::kPosition,
+                                         builtin::BuiltinValue::kVertexIndex,
+                                         builtin::BuiltinValue::kInstanceIndex,
+                                         builtin::BuiltinValue::kFrontFacing,
+                                         builtin::BuiltinValue::kFragDepth,
+                                         builtin::BuiltinValue::kLocalInvocationId,
+                                         builtin::BuiltinValue::kLocalInvocationIndex,
+                                         builtin::BuiltinValue::kGlobalInvocationId,
+                                         builtin::BuiltinValue::kWorkgroupId,
+                                         builtin::BuiltinValue::kNumWorkgroups,
+                                         builtin::BuiltinValue::kSampleIndex,
+                                         builtin::BuiltinValue::kSampleMask));
 
 TEST_F(ParserImplTest, Attribute_Builtin_MissingLeftParen) {
     auto p = parser("builtin position)");
@@ -302,42 +293,7 @@ TEST_F(ParserImplTest, Attribute_Builtin_MissingValue) {
     EXPECT_TRUE(attr.errored);
     EXPECT_EQ(attr.value, nullptr);
     EXPECT_TRUE(p->has_error());
-    EXPECT_EQ(p->error(), R"(1:9: expected builtin
-Possible values: 'frag_depth', 'front_facing', 'global_invocation_id', 'instance_index', 'local_invocation_id', 'local_invocation_index', 'num_workgroups', 'position', 'sample_index', 'sample_mask', 'vertex_index', 'workgroup_id')");
-}
-
-TEST_F(ParserImplTest, Attribute_Builtin_InvalidValue) {
-    auto p = parser("builtin(other_thingy)");
-    auto attr = p->attribute();
-    EXPECT_FALSE(attr.matched);
-    EXPECT_TRUE(attr.errored);
-    EXPECT_EQ(attr.value, nullptr);
-    EXPECT_TRUE(p->has_error());
-    EXPECT_EQ(p->error(), R"(1:9: expected builtin
-Possible values: 'frag_depth', 'front_facing', 'global_invocation_id', 'instance_index', 'local_invocation_id', 'local_invocation_index', 'num_workgroups', 'position', 'sample_index', 'sample_mask', 'vertex_index', 'workgroup_id')");
-}
-
-TEST_F(ParserImplTest, Attribute_Builtin_InvalidValueSuggest) {
-    auto p = parser("builtin(front_face)");
-    auto attr = p->attribute();
-    EXPECT_FALSE(attr.matched);
-    EXPECT_TRUE(attr.errored);
-    EXPECT_EQ(attr.value, nullptr);
-    EXPECT_TRUE(p->has_error());
-    EXPECT_EQ(p->error(), R"(1:9: expected builtin
-Did you mean 'front_facing'?
-Possible values: 'frag_depth', 'front_facing', 'global_invocation_id', 'instance_index', 'local_invocation_id', 'local_invocation_index', 'num_workgroups', 'position', 'sample_index', 'sample_mask', 'vertex_index', 'workgroup_id')");
-}
-
-TEST_F(ParserImplTest, Attribute_Builtin_MissingInvalid) {
-    auto p = parser("builtin(3)");
-    auto attr = p->attribute();
-    EXPECT_FALSE(attr.matched);
-    EXPECT_TRUE(attr.errored);
-    EXPECT_EQ(attr.value, nullptr);
-    EXPECT_TRUE(p->has_error());
-    EXPECT_EQ(p->error(), R"(1:9: expected builtin
-Possible values: 'frag_depth', 'front_facing', 'global_invocation_id', 'instance_index', 'local_invocation_id', 'local_invocation_index', 'num_workgroups', 'position', 'sample_index', 'sample_mask', 'vertex_index', 'workgroup_id')");
+    EXPECT_EQ(p->error(), R"(1:9: expected expression for builtin name)");
 }
 
 TEST_F(ParserImplTest, Attribute_Interpolate_Flat) {
diff --git a/src/tint/resolver/attribute_validation_test.cc b/src/tint/resolver/attribute_validation_test.cc
index 3255c49576..100c239963 100644
--- a/src/tint/resolver/attribute_validation_test.cc
+++ b/src/tint/resolver/attribute_validation_test.cc
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "src/tint/ast/disable_validation_attribute.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/resolver/resolver.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 #include "src/tint/transform/add_block_attribute.h"
@@ -221,9 +222,9 @@ TEST_P(ComputeShaderParameterAttributeTest, IsValid) {
     } else {
         EXPECT_FALSE(r()->Resolve());
         if (params.kind == AttributeKind::kBuiltin) {
-            EXPECT_EQ(r()->error(),
-                      "12:34 error: builtin(position) cannot be used in input of "
-                      "compute pipeline stage");
+            EXPECT_EQ(
+                r()->error(),
+                R"(12:34 error: @builtin(position) cannot be used in input of compute pipeline stage)");
         } else if (params.kind == AttributeKind::kInterpolate ||
                    params.kind == AttributeKind::kLocation ||
                    params.kind == AttributeKind::kInvariant) {
@@ -314,9 +315,9 @@ TEST_P(VertexShaderParameterAttributeTest, IsValid) {
     } else {
         EXPECT_FALSE(r()->Resolve());
         if (params.kind == AttributeKind::kBuiltin) {
-            EXPECT_EQ(r()->error(),
-                      "12:34 error: builtin(position) cannot be used in input of "
-                      "vertex pipeline stage");
+            EXPECT_EQ(
+                r()->error(),
+                R"(12:34 error: @builtin(position) cannot be used in input of vertex pipeline stage)");
         } else if (params.kind == AttributeKind::kInvariant) {
             EXPECT_EQ(r()->error(),
                       "12:34 error: invariant attribute must only be applied to a "
@@ -362,9 +363,9 @@ TEST_P(ComputeShaderReturnTypeAttributeTest, IsValid) {
     } else {
         EXPECT_FALSE(r()->Resolve());
         if (params.kind == AttributeKind::kBuiltin) {
-            EXPECT_EQ(r()->error(),
-                      "12:34 error: builtin(position) cannot be used in output of "
-                      "compute pipeline stage");
+            EXPECT_EQ(
+                r()->error(),
+                R"(12:34 error: @builtin(position) cannot be used in output of compute pipeline stage)");
         } else if (params.kind == AttributeKind::kInterpolate ||
                    params.kind == AttributeKind::kLocation ||
                    params.kind == AttributeKind::kInvariant) {
@@ -411,21 +412,20 @@ TEST_P(FragmentShaderReturnTypeAttributeTest, IsValid) {
     } else {
         EXPECT_FALSE(r()->Resolve());
         if (params.kind == AttributeKind::kBuiltin) {
-            EXPECT_EQ(r()->error(),
-                      "12:34 error: builtin(position) cannot be used in output of "
-                      "fragment pipeline stage");
+            EXPECT_EQ(
+                r()->error(),
+                R"(12:34 error: @builtin(position) cannot be used in output of fragment pipeline stage)");
         } else if (params.kind == AttributeKind::kInvariant) {
-            EXPECT_EQ(r()->error(),
-                      "12:34 error: invariant attribute must only be applied to a "
-                      "position builtin");
+            EXPECT_EQ(
+                r()->error(),
+                R"(12:34 error: invariant attribute must only be applied to a position builtin)");
         } else if (params.kind == AttributeKind::kLocation) {
             EXPECT_EQ(r()->error(),
-                      "34:56 error: duplicate location attribute\n"
-                      "12:34 note: first attribute declared here");
+                      R"(34:56 error: duplicate location attribute
+12:34 note: first attribute declared here)");
         } else {
             EXPECT_EQ(r()->error(),
-                      "12:34 error: attribute is not valid for entry point return "
-                      "types");
+                      R"(12:34 error: attribute is not valid for entry point return types)");
         }
     }
 }
@@ -470,12 +470,11 @@ TEST_P(VertexShaderReturnTypeAttributeTest, IsValid) {
         EXPECT_FALSE(r()->Resolve());
         if (params.kind == AttributeKind::kLocation) {
             EXPECT_EQ(r()->error(),
-                      "34:56 error: multiple entry point IO attributes\n"
-                      "12:34 note: previously consumed location(1)");
+                      R"(34:56 error: multiple entry point IO attributes
+12:34 note: previously consumed @location)");
         } else {
             EXPECT_EQ(r()->error(),
-                      "12:34 error: attribute is not valid for entry point return "
-                      "types");
+                      R"(12:34 error: attribute is not valid for entry point return types)");
         }
     }
 }
diff --git a/src/tint/resolver/builtins_validation_test.cc b/src/tint/resolver/builtins_validation_test.cc
index a6f5889772..321c0b0e4b 100644
--- a/src/tint/resolver/builtins_validation_test.cc
+++ b/src/tint/resolver/builtins_validation_test.cc
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "src/tint/ast/call_statement.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 
 using namespace tint::number_suffixes;  // NOLINT
@@ -145,7 +146,7 @@ TEST_P(ResolverBuiltinsStageTest, All_input) {
         EXPECT_TRUE(r()->Resolve()) << r()->error();
     } else {
         std::stringstream err;
-        err << "12:34 error: builtin(" << params.builtin << ")";
+        err << "12:34 error: @builtin(" << params.builtin << ")";
         err << " cannot be used in input of " << params.stage << " pipeline stage";
         EXPECT_FALSE(r()->Resolve());
         EXPECT_EQ(r()->error(), err.str());
@@ -178,9 +179,9 @@ TEST_F(ResolverBuiltinsValidationTest, FragDepthIsInput_Fail) {
              Location(0_a),
          });
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(),
-              "12:34 error: builtin(frag_depth) cannot be used in input of "
-              "fragment pipeline stage");
+    EXPECT_EQ(
+        r()->error(),
+        "12:34 error: @builtin(frag_depth) cannot be used in input of fragment pipeline stage");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, FragDepthIsInputStruct_Fail) {
@@ -214,7 +215,7 @@ TEST_F(ResolverBuiltinsValidationTest, FragDepthIsInputStruct_Fail) {
          });
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: builtin(frag_depth) cannot be used in input of "
+              "12:34 error: @builtin(frag_depth) cannot be used in input of "
               "fragment pipeline stage\n"
               "note: while analyzing entry point 'fragShader'");
 }
@@ -272,7 +273,7 @@ TEST_F(ResolverBuiltinsValidationTest, PositionNotF32_Struct_Fail) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(position) must be 'vec4<f32>'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(position) must be 'vec4<f32>'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, PositionNotF32_ReturnType_Fail) {
@@ -288,7 +289,7 @@ TEST_F(ResolverBuiltinsValidationTest, PositionNotF32_ReturnType_Fail) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(position) must be 'vec4<f32>'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(position) must be 'vec4<f32>'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, FragDepthNotF32_Struct_Fail) {
@@ -317,7 +318,7 @@ TEST_F(ResolverBuiltinsValidationTest, FragDepthNotF32_Struct_Fail) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(frag_depth) must be 'f32'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(frag_depth) must be 'f32'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, SampleMaskNotU32_Struct_Fail) {
@@ -346,7 +347,7 @@ TEST_F(ResolverBuiltinsValidationTest, SampleMaskNotU32_Struct_Fail) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(sample_mask) must be 'u32'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(sample_mask) must be 'u32'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, SampleMaskNotU32_ReturnType_Fail) {
@@ -361,7 +362,7 @@ TEST_F(ResolverBuiltinsValidationTest, SampleMaskNotU32_ReturnType_Fail) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(sample_mask) must be 'u32'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(sample_mask) must be 'u32'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, SampleMaskIsNotU32_Fail) {
@@ -387,7 +388,7 @@ TEST_F(ResolverBuiltinsValidationTest, SampleMaskIsNotU32_Fail) {
              Location(0_a),
          });
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(sample_mask) must be 'u32'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(sample_mask) must be 'u32'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, SampleIndexIsNotU32_Struct_Fail) {
@@ -416,7 +417,7 @@ TEST_F(ResolverBuiltinsValidationTest, SampleIndexIsNotU32_Struct_Fail) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(sample_index) must be 'u32'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(sample_index) must be 'u32'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, SampleIndexIsNotU32_Fail) {
@@ -442,7 +443,7 @@ TEST_F(ResolverBuiltinsValidationTest, SampleIndexIsNotU32_Fail) {
              Location(0_a),
          });
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(sample_index) must be 'u32'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(sample_index) must be 'u32'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, PositionIsNotF32_Fail) {
@@ -468,7 +469,7 @@ TEST_F(ResolverBuiltinsValidationTest, PositionIsNotF32_Fail) {
              Location(0_a),
          });
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(position) must be 'vec4<f32>'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(position) must be 'vec4<f32>'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, FragDepthIsNotF32_Fail) {
@@ -487,7 +488,7 @@ TEST_F(ResolverBuiltinsValidationTest, FragDepthIsNotF32_Fail) {
              Builtin(Source{{12, 34}}, builtin::BuiltinValue::kFragDepth),
          });
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(frag_depth) must be 'f32'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(frag_depth) must be 'f32'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, VertexIndexIsNotU32_Fail) {
@@ -512,7 +513,7 @@ TEST_F(ResolverBuiltinsValidationTest, VertexIndexIsNotU32_Fail) {
              Builtin(builtin::BuiltinValue::kPosition),
          });
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(vertex_index) must be 'u32'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(vertex_index) must be 'u32'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, InstanceIndexIsNotU32) {
@@ -537,7 +538,7 @@ TEST_F(ResolverBuiltinsValidationTest, InstanceIndexIsNotU32) {
              Builtin(builtin::BuiltinValue::kPosition),
          });
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(instance_index) must be 'u32'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(instance_index) must be 'u32'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, FragmentBuiltin_Pass) {
@@ -657,7 +658,7 @@ TEST_F(ResolverBuiltinsValidationTest, ComputeBuiltin_WorkGroupIdNotVec3U32) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: store type of builtin(workgroup_id) must be "
+              "12:34 error: store type of @builtin(workgroup_id) must be "
               "'vec3<u32>'");
 }
 
@@ -672,7 +673,7 @@ TEST_F(ResolverBuiltinsValidationTest, ComputeBuiltin_NumWorkgroupsNotVec3U32) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: store type of builtin(num_workgroups) must be "
+              "12:34 error: store type of @builtin(num_workgroups) must be "
               "'vec3<u32>'");
 }
 
@@ -687,7 +688,7 @@ TEST_F(ResolverBuiltinsValidationTest, ComputeBuiltin_GlobalInvocationNotVec3U32
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: store type of builtin(global_invocation_id) must be "
+              "12:34 error: store type of @builtin(global_invocation_id) must be "
               "'vec3<u32>'");
 }
 
@@ -703,7 +704,7 @@ TEST_F(ResolverBuiltinsValidationTest, ComputeBuiltin_LocalInvocationIndexNotU32
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: store type of builtin(local_invocation_index) must be "
+              "12:34 error: store type of @builtin(local_invocation_index) must be "
               "'u32'");
 }
 
@@ -718,7 +719,7 @@ TEST_F(ResolverBuiltinsValidationTest, ComputeBuiltin_LocalInvocationNotVec3U32)
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: store type of builtin(local_invocation_id) must be "
+              "12:34 error: store type of @builtin(local_invocation_id) must be "
               "'vec3<u32>'");
 }
 
@@ -785,7 +786,7 @@ TEST_F(ResolverBuiltinsValidationTest, FrontFacingParamIsNotBool_Fail) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(front_facing) must be 'bool'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(front_facing) must be 'bool'");
 }
 
 TEST_F(ResolverBuiltinsValidationTest, FrontFacingMemberIsNotBool_Fail) {
@@ -814,7 +815,50 @@ TEST_F(ResolverBuiltinsValidationTest, FrontFacingMemberIsNotBool_Fail) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: store type of builtin(front_facing) must be 'bool'");
+    EXPECT_EQ(r()->error(), "12:34 error: store type of @builtin(front_facing) must be 'bool'");
+}
+
+// TODO(crbug.com/tint/1846): This isn't a validation test, but this sits next to other @builtin
+// tests. Clean this up.
+TEST_F(ResolverBuiltinsValidationTest, StructMemberAttributeMapsToSemBuiltinEnum) {
+    // struct S {
+    //   @builtin(front_facing) b : bool;
+    // };
+    // @fragment
+    // fn f(s : S) {}
+
+    auto* builtin = Builtin(builtin::BuiltinValue::kFrontFacing);
+    auto* s = Structure("S", utils::Vector{
+                                 Member("f", ty.bool_(), utils::Vector{builtin}),
+                             });
+    Func("f", utils::Vector{Param("b", ty.Of(s))}, ty.void_(), utils::Empty,
+         utils::Vector{
+             Stage(ast::PipelineStage::kFragment),
+         });
+
+    EXPECT_TRUE(r()->Resolve()) << r()->error();
+    auto* builtin_expr = Sem().Get(builtin);
+    ASSERT_NE(builtin_expr, nullptr);
+    EXPECT_EQ(builtin_expr->Value(), builtin::BuiltinValue::kFrontFacing);
+}
+
+// TODO(crbug.com/tint/1846): This isn't a validation test, but this sits next to other @builtin
+// tests. Clean this up.
+TEST_F(ResolverBuiltinsValidationTest, ParamAttributeMapsToSemBuiltinEnum) {
+    // @fragment
+    // fn f(@builtin(front_facing) b : bool) {}
+
+    auto* builtin = Builtin(builtin::BuiltinValue::kFrontFacing);
+    Func("f", utils::Vector{Param("b", ty.bool_(), utils::Vector{builtin})}, ty.void_(),
+         utils::Empty,
+         utils::Vector{
+             Stage(ast::PipelineStage::kFragment),
+         });
+
+    EXPECT_TRUE(r()->Resolve()) << r()->error();
+    auto* builtin_expr = Sem().Get(builtin);
+    ASSERT_NE(builtin_expr, nullptr);
+    EXPECT_EQ(builtin_expr->Value(), builtin::BuiltinValue::kFrontFacing);
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Length_Float_Scalar) {
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index fbf2b46aec..2100f6b17b 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -55,6 +55,7 @@
 #include "src/tint/ast/while_statement.h"
 #include "src/tint/ast/workgroup_attribute.h"
 #include "src/tint/builtin/builtin.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/scope_stack.h"
 #include "src/tint/sem/builtin.h"
 #include "src/tint/symbol_table.h"
@@ -424,6 +425,10 @@ class DependencyScanner {
                 TraverseValueExpression(binding->expr);
                 return true;
             },
+            [&](const ast::BuiltinAttribute* builtin) {
+                TraverseExpression(builtin->builtin, "builtin", "references");
+                return true;
+            },
             [&](const ast::GroupAttribute* group) {
                 TraverseValueExpression(group->expr);
                 return true;
@@ -480,6 +485,11 @@ class DependencyScanner {
                 graph_.resolved_identifiers.Add(from, ResolvedIdentifier(builtin_ty));
                 return;
             }
+            if (auto builtin_val = builtin::ParseBuiltinValue(s);
+                builtin_val != builtin::BuiltinValue::kUndefined) {
+                graph_.resolved_identifiers.Add(from, ResolvedIdentifier(builtin_val));
+                return;
+            }
             if (auto addr = builtin::ParseAddressSpace(s);
                 addr != builtin::AddressSpace::kUndefined) {
                 graph_.resolved_identifiers.Add(from, ResolvedIdentifier(addr));
@@ -863,6 +873,9 @@ std::string ResolvedIdentifier::String(const SymbolTable& symbols, diag::List& d
     if (auto builtin_ty = BuiltinType(); builtin_ty != builtin::Builtin::kUndefined) {
         return "builtin type '" + utils::ToString(builtin_ty) + "'";
     }
+    if (auto builtin_val = BuiltinValue(); builtin_val != builtin::BuiltinValue::kUndefined) {
+        return "builtin value '" + utils::ToString(builtin_val) + "'";
+    }
     if (auto access = Access(); access != builtin::Access::kUndefined) {
         return "access '" + utils::ToString(access) + "'";
     }
diff --git a/src/tint/resolver/dependency_graph.h b/src/tint/resolver/dependency_graph.h
index 8db2ab4700..382514fab0 100644
--- a/src/tint/resolver/dependency_graph.h
+++ b/src/tint/resolver/dependency_graph.h
@@ -21,6 +21,7 @@
 #include "src/tint/ast/module.h"
 #include "src/tint/builtin/access.h"
 #include "src/tint/builtin/builtin.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/builtin/texel_format.h"
 #include "src/tint/diagnostic/diagnostic.h"
 #include "src/tint/sem/builtin_type.h"
@@ -38,6 +39,7 @@ namespace tint::resolver {
 /// - builtin::Access
 /// - builtin::AddressSpace
 /// - builtin::Builtin
+/// - builtin::BuiltinValue
 /// - builtin::TexelFormat
 class ResolvedIdentifier {
   public:
@@ -95,8 +97,17 @@ class ResolvedIdentifier {
         return builtin::Builtin::kUndefined;
     }
 
-    /// @return the texel format if the ResolvedIdentifier holds builtin::TexelFormat, otherwise
-    /// builtin::TexelFormat::kUndefined
+    /// @return the builtin value if the ResolvedIdentifier holds builtin::BuiltinValue, otherwise
+    /// builtin::BuiltinValue::kUndefined
+    builtin::BuiltinValue BuiltinValue() const {
+        if (auto n = std::get_if<builtin::BuiltinValue>(&value_)) {
+            return *n;
+        }
+        return builtin::BuiltinValue::kUndefined;
+    }
+
+    /// @return the texel format if the ResolvedIdentifier holds type::TexelFormat, otherwise
+    /// type::TexelFormat::kUndefined
     builtin::TexelFormat TexelFormat() const {
         if (auto n = std::get_if<builtin::TexelFormat>(&value_)) {
             return *n;
@@ -133,6 +144,7 @@ class ResolvedIdentifier {
                  builtin::Access,
                  builtin::AddressSpace,
                  builtin::Builtin,
+                 builtin::BuiltinValue,
                  builtin::TexelFormat>
         value_;
 };
diff --git a/src/tint/resolver/dependency_graph_test.cc b/src/tint/resolver/dependency_graph_test.cc
index 8f15ad9886..d8ec08b067 100644
--- a/src/tint/resolver/dependency_graph_test.cc
+++ b/src/tint/resolver/dependency_graph_test.cc
@@ -1500,6 +1500,91 @@ INSTANTIATE_TEST_SUITE_P(Functions,
 
 }  // namespace resolve_to_address_space
 
+////////////////////////////////////////////////////////////////////////////////
+// Resolve to builtin::BuiltinValue tests
+////////////////////////////////////////////////////////////////////////////////
+namespace resolve_to_builtin_value {
+
+using ResolverDependencyGraphResolveToBuiltinValue =
+    ResolverDependencyGraphTestWithParam<std::tuple<SymbolUseKind, const char*>>;
+
+TEST_P(ResolverDependencyGraphResolveToBuiltinValue, Resolve) {
+    const auto use = std::get<0>(GetParam());
+    const auto name = std::get<1>(GetParam());
+    const auto symbol = Symbols().New(name);
+
+    SymbolTestHelper helper(this);
+    auto* ident = helper.Add(use, symbol);
+    helper.Build();
+
+    auto resolved = Build().resolved_identifiers.Get(ident);
+    ASSERT_TRUE(resolved);
+    EXPECT_EQ(resolved->BuiltinValue(), builtin::ParseBuiltinValue(name))
+        << resolved->String(Symbols(), Diagnostics());
+}
+
+TEST_P(ResolverDependencyGraphResolveToBuiltinValue, ShadowedByGlobalConst) {
+    const auto use = std::get<0>(GetParam());
+    const auto builtin = std::get<1>(GetParam());
+    const auto symbol = Symbols().New(utils::ToString(builtin));
+
+    SymbolTestHelper helper(this);
+    auto* decl = helper.Add(SymbolDeclKind::GlobalConst, symbol);
+    auto* ident = helper.Add(use, symbol);
+    helper.Build();
+
+    auto resolved = Build().resolved_identifiers.Get(ident);
+    ASSERT_TRUE(resolved);
+    EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
+}
+
+TEST_P(ResolverDependencyGraphResolveToBuiltinValue, ShadowedByStruct) {
+    const auto use = std::get<0>(GetParam());
+    const auto builtin = std::get<1>(GetParam());
+    const auto symbol = Symbols().New(utils::ToString(builtin));
+
+    SymbolTestHelper helper(this);
+    auto* decl = helper.Add(SymbolDeclKind::Struct, symbol);
+    auto* ident = helper.Add(use, symbol);
+    helper.Build();
+
+    auto resolved = Build().resolved_identifiers.Get(ident);
+    ASSERT_TRUE(resolved);
+    EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
+}
+
+TEST_P(ResolverDependencyGraphResolveToBuiltinValue, ShadowedByFunc) {
+    const auto use = std::get<0>(GetParam());
+    const auto builtin = std::get<1>(GetParam());
+    const auto symbol = Symbols().New(utils::ToString(builtin));
+
+    SymbolTestHelper helper(this);
+    auto* decl = helper.Add(SymbolDeclKind::Function, symbol);
+    auto* ident = helper.Add(use, symbol);
+    helper.Build();
+
+    auto resolved = Build().resolved_identifiers.Get(ident);
+    ASSERT_TRUE(resolved);
+    EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
+}
+
+INSTANTIATE_TEST_SUITE_P(Types,
+                         ResolverDependencyGraphResolveToBuiltinValue,
+                         testing::Combine(testing::ValuesIn(kTypeUseKinds),
+                                          testing::ValuesIn(builtin::kBuiltinValueStrings)));
+
+INSTANTIATE_TEST_SUITE_P(Values,
+                         ResolverDependencyGraphResolveToBuiltinValue,
+                         testing::Combine(testing::ValuesIn(kValueUseKinds),
+                                          testing::ValuesIn(builtin::kBuiltinValueStrings)));
+
+INSTANTIATE_TEST_SUITE_P(Functions,
+                         ResolverDependencyGraphResolveToBuiltinValue,
+                         testing::Combine(testing::ValuesIn(kFuncUseKinds),
+                                          testing::ValuesIn(builtin::kBuiltinValueStrings)));
+
+}  // namespace resolve_to_builtin_value
+
 ////////////////////////////////////////////////////////////////////////////////
 // Resolve to builtin::TexelFormat tests
 ////////////////////////////////////////////////////////////////////////////////
@@ -1686,6 +1771,7 @@ TEST_F(ResolverDependencyGraphTraversalTest, SymbolsReached) {
              Param(Sym(), T,
                    utils::Vector{
                        Location(V),  // Parameter attributes
+                       Builtin(V),
                    }),
          },
          T,  // Return type
diff --git a/src/tint/resolver/entry_point_validation_test.cc b/src/tint/resolver/entry_point_validation_test.cc
index be027d8ef9..dac6cd2e84 100644
--- a/src/tint/resolver/entry_point_validation_test.cc
+++ b/src/tint/resolver/entry_point_validation_test.cc
@@ -16,6 +16,7 @@
 #include "src/tint/ast/location_attribute.h"
 #include "src/tint/ast/return_statement.h"
 #include "src/tint/ast/stage_attribute.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/resolver/resolver.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 
@@ -94,7 +95,7 @@ TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Missing) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: missing entry point IO attribute on return type");
+    EXPECT_EQ(r()->error(), R"(12:34 error: missing entry point IO attribute on return type)");
 }
 
 TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Multiple) {
@@ -116,7 +117,7 @@ TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Multiple) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(), R"(14:52 error: multiple entry point IO attributes
-13:43 note: previously consumed location(0))");
+13:43 note: previously consumed @location)");
 }
 
 TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_Valid) {
@@ -170,7 +171,7 @@ TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_MemberMultipleAttribu
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(), R"(14:52 error: multiple entry point IO attributes
-13:43 note: previously consumed location(0)
+13:43 note: previously consumed @location
 12:34 note: while analyzing entry point 'main')");
 }
 
@@ -226,9 +227,8 @@ TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_DuplicateBuiltins) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(
-        r()->error(),
-        R"(12:34 error: builtin(frag_depth) attribute appears multiple times as pipeline output
+    EXPECT_EQ(r()->error(),
+              R"(12:34 error: @builtin(frag_depth) appears multiple times as pipeline output
 12:34 note: while analyzing entry point 'main')");
 }
 
@@ -265,7 +265,7 @@ TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Missing) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "13:43 error: missing entry point IO attribute on parameter");
+    EXPECT_EQ(r()->error(), R"(13:43 error: missing entry point IO attribute on parameter)");
 }
 
 TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Multiple) {
@@ -287,7 +287,7 @@ TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Multiple) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(), R"(14:52 error: multiple entry point IO attributes
-13:43 note: previously consumed location(0))");
+13:43 note: previously consumed @location)");
 }
 
 TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_Valid) {
@@ -341,7 +341,7 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_MemberMultipleAttribut
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(), R"(14:52 error: multiple entry point IO attributes
-13:43 note: previously consumed location(0)
+13:43 note: previously consumed @location
 12:34 note: while analyzing entry point 'main')");
 }
 
@@ -396,8 +396,7 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_DuplicateBuiltins) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: builtin(sample_index) attribute appears multiple times as "
-              "pipeline input");
+              "12:34 error: @builtin(sample_index) appears multiple times as pipeline input");
 }
 
 TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_DuplicateBuiltins) {
@@ -432,9 +431,8 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_DuplicateBuiltins) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(
-        r()->error(),
-        R"(12:34 error: builtin(sample_index) attribute appears multiple times as pipeline input
+    EXPECT_EQ(r()->error(),
+              R"(12:34 error: @builtin(sample_index) appears multiple times as pipeline input
 12:34 note: while analyzing entry point 'main')");
 }
 
@@ -785,10 +783,8 @@ TEST_F(LocationAttributeTests, BadType_Input_bool) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: cannot apply 'location' attribute to declaration of "
-              "type 'bool'\n"
-              "34:56 note: 'location' attribute must only be applied to "
-              "declarations of numeric scalar or numeric vector type");
+              R"(12:34 error: cannot apply @location to declaration of type 'bool'
+34:56 note: @location must only be applied to declarations of numeric scalar or numeric vector type)");
 }
 
 TEST_F(LocationAttributeTests, BadType_Output_Array) {
@@ -808,10 +804,8 @@ TEST_F(LocationAttributeTests, BadType_Output_Array) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: cannot apply 'location' attribute to declaration of "
-              "type 'array<f32, 2>'\n"
-              "34:56 note: 'location' attribute must only be applied to "
-              "declarations of numeric scalar or numeric vector type");
+              R"(12:34 error: cannot apply @location to declaration of type 'array<f32, 2>'
+34:56 note: @location must only be applied to declarations of numeric scalar or numeric vector type)");
 }
 
 TEST_F(LocationAttributeTests, BadType_Input_Struct) {
@@ -838,10 +832,8 @@ TEST_F(LocationAttributeTests, BadType_Input_Struct) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: cannot apply 'location' attribute to declaration of "
-              "type 'Input'\n"
-              "13:43 note: 'location' attribute must only be applied to "
-              "declarations of numeric scalar or numeric vector type");
+              R"(12:34 error: cannot apply @location to declaration of type 'Input'
+13:43 note: @location must only be applied to declarations of numeric scalar or numeric vector type)");
 }
 
 TEST_F(LocationAttributeTests, BadType_Input_Struct_NestedStruct) {
@@ -872,8 +864,8 @@ TEST_F(LocationAttributeTests, BadType_Input_Struct_NestedStruct) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "14:52 error: nested structures cannot be used for entry point IO\n"
-              "12:34 note: while analyzing entry point 'main'");
+              R"(14:52 error: nested structures cannot be used for entry point IO
+12:34 note: while analyzing entry point 'main')");
 }
 
 TEST_F(LocationAttributeTests, BadType_Input_Struct_RuntimeArray) {
@@ -898,10 +890,8 @@ TEST_F(LocationAttributeTests, BadType_Input_Struct_RuntimeArray) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "13:43 error: cannot apply 'location' attribute to declaration of "
-              "type 'array<f32>'\n"
-              "note: 'location' attribute must only be applied to declarations "
-              "of numeric scalar or numeric vector type");
+              R"(13:43 error: cannot apply @location to declaration of type 'array<f32>'
+note: @location must only be applied to declarations of numeric scalar or numeric vector type)");
 }
 
 TEST_F(LocationAttributeTests, BadMemberType_Input) {
@@ -927,10 +917,8 @@ TEST_F(LocationAttributeTests, BadMemberType_Input) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "34:56 error: cannot apply 'location' attribute to declaration of "
-              "type 'array<i32>'\n"
-              "12:34 note: 'location' attribute must only be applied to "
-              "declarations of numeric scalar or numeric vector type");
+              R"(34:56 error: cannot apply @location to declaration of type 'array<i32>'
+12:34 note: @location must only be applied to declarations of numeric scalar or numeric vector type)");
 }
 
 TEST_F(LocationAttributeTests, BadMemberType_Output) {
@@ -954,10 +942,8 @@ TEST_F(LocationAttributeTests, BadMemberType_Output) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "34:56 error: cannot apply 'location' attribute to declaration of "
-              "type 'atomic<i32>'\n"
-              "12:34 note: 'location' attribute must only be applied to "
-              "declarations of numeric scalar or numeric vector type");
+              R"(34:56 error: cannot apply @location to declaration of type 'atomic<i32>'
+12:34 note: @location must only be applied to declarations of numeric scalar or numeric vector type)");
 }
 
 TEST_F(LocationAttributeTests, BadMemberType_Unused) {
@@ -971,10 +957,8 @@ TEST_F(LocationAttributeTests, BadMemberType_Unused) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "34:56 error: cannot apply 'location' attribute to declaration of "
-              "type 'mat3x2<f32>'\n"
-              "12:34 note: 'location' attribute must only be applied to "
-              "declarations of numeric scalar or numeric vector type");
+              R"(34:56 error: cannot apply @location to declaration of type 'mat3x2<f32>'
+12:34 note: @location must only be applied to declarations of numeric scalar or numeric vector type)");
 }
 
 TEST_F(LocationAttributeTests, ReturnType_Struct_Valid) {
@@ -1026,11 +1010,8 @@ TEST_F(LocationAttributeTests, ReturnType_Struct) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(),
-              "12:34 error: cannot apply 'location' attribute to declaration of "
-              "type 'Output'\n"
-              "13:43 note: 'location' attribute must only be applied to "
-              "declarations of numeric scalar or numeric vector type");
+    EXPECT_EQ(r()->error(), R"(12:34 error: cannot apply @location to declaration of type 'Output'
+13:43 note: @location must only be applied to declarations of numeric scalar or numeric vector type)");
 }
 
 TEST_F(LocationAttributeTests, ReturnType_Struct_NestedStruct) {
@@ -1059,8 +1040,8 @@ TEST_F(LocationAttributeTests, ReturnType_Struct_NestedStruct) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "14:52 error: nested structures cannot be used for entry point IO\n"
-              "12:34 note: while analyzing entry point 'main'");
+              R"(14:52 error: nested structures cannot be used for entry point IO
+12:34 note: while analyzing entry point 'main')");
 }
 
 TEST_F(LocationAttributeTests, ReturnType_Struct_RuntimeArray) {
@@ -1085,10 +1066,8 @@ TEST_F(LocationAttributeTests, ReturnType_Struct_RuntimeArray) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "13:43 error: cannot apply 'location' attribute to declaration of "
-              "type 'array<f32>'\n"
-              "12:34 note: 'location' attribute must only be applied to "
-              "declarations of numeric scalar or numeric vector type");
+              R"(13:43 error: cannot apply @location to declaration of type 'array<f32>'
+12:34 note: @location must only be applied to declarations of numeric scalar or numeric vector type)");
 }
 
 TEST_F(LocationAttributeTests, ComputeShaderLocation_Input) {
@@ -1105,7 +1084,7 @@ TEST_F(LocationAttributeTests, ComputeShaderLocation_Input) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: attribute is not valid for compute shader output");
+    EXPECT_EQ(r()->error(), R"(12:34 error: attribute is not valid for compute shader output)");
 }
 
 TEST_F(LocationAttributeTests, ComputeShaderLocation_Output) {
@@ -1120,7 +1099,7 @@ TEST_F(LocationAttributeTests, ComputeShaderLocation_Output) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: attribute is not valid for compute shader inputs");
+    EXPECT_EQ(r()->error(), R"(12:34 error: attribute is not valid for compute shader inputs)");
 }
 
 TEST_F(LocationAttributeTests, ComputeShaderLocationStructMember_Output) {
@@ -1186,7 +1165,7 @@ TEST_F(LocationAttributeTests, Duplicate_input) {
          });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: location(1) attribute appears multiple times");
+    EXPECT_EQ(r()->error(), R"(12:34 error: @location(1) appears multiple times)");
 }
 
 TEST_F(LocationAttributeTests, Duplicate_struct) {
@@ -1219,8 +1198,8 @@ TEST_F(LocationAttributeTests, Duplicate_struct) {
 
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "34:56 error: location(1) attribute appears multiple times\n"
-              "12:34 note: while analyzing entry point 'main'");
+              R"(34:56 error: @location(1) appears multiple times
+12:34 note: while analyzing entry point 'main')");
 }
 
 }  // namespace
diff --git a/src/tint/resolver/expression_kind_test.cc b/src/tint/resolver/expression_kind_test.cc
index 681b5c3e99..87610553fe 100644
--- a/src/tint/resolver/expression_kind_test.cc
+++ b/src/tint/resolver/expression_kind_test.cc
@@ -27,6 +27,7 @@ enum class Def {
     kAddressSpace,
     kBuiltinFunction,
     kBuiltinType,
+    kBuiltinValue,
     kFunction,
     kStruct,
     kTexelFormat,
@@ -44,6 +45,8 @@ std::ostream& operator<<(std::ostream& out, Def def) {
             return out << "Def::kBuiltinFunction";
         case Def::kBuiltinType:
             return out << "Def::kBuiltinType";
+        case Def::kBuiltinValue:
+            return out << "Def::kBuiltinValue";
         case Def::kFunction:
             return out << "Def::kFunction";
         case Def::kStruct:
@@ -62,6 +65,7 @@ enum class Use {
     kAccess,
     kAddressSpace,
     kBinaryOp,
+    kBuiltinValue,
     kCallExpr,
     kCallStmt,
     kFunctionReturnType,
@@ -80,6 +84,8 @@ std::ostream& operator<<(std::ostream& out, Use use) {
             return out << "Use::kAddressSpace";
         case Use::kBinaryOp:
             return out << "Use::kBinaryOp";
+        case Use::kBuiltinValue:
+            return out << "Use::kBuiltinValue";
         case Use::kCallExpr:
             return out << "Use::kCallExpr";
         case Use::kCallStmt:
@@ -156,6 +162,16 @@ TEST_P(ResolverExpressionKindTest, Test) {
             };
             break;
         }
+        case Def::kBuiltinValue: {
+            sym = Sym("position");
+            check_expr = [](const sem::Expression* expr) {
+                ASSERT_NE(expr, nullptr);
+                auto* enum_expr = expr->As<sem::BuiltinEnumExpression<builtin::BuiltinValue>>();
+                ASSERT_NE(enum_expr, nullptr);
+                EXPECT_EQ(enum_expr->Value(), builtin::BuiltinValue::kPosition);
+            };
+            break;
+        }
         case Def::kFunction: {
             auto* fn = Func(kDefSource, "FUNCTION", utils::Empty, ty.i32(), Return(1_i));
             sym = Sym("FUNCTION");
@@ -233,6 +249,10 @@ TEST_P(ResolverExpressionKindTest, Test) {
         case Use::kBinaryOp:
             GlobalVar("v", builtin::AddressSpace::kPrivate, Mul(1_a, expr));
             break;
+        case Use::kBuiltinValue:
+            Func("f", utils::Vector{Param("p", ty.vec4<f32>(), utils::Vector{Builtin(expr)})},
+                 ty.void_(), utils::Empty, utils::Vector{Stage(ast::PipelineStage::kFragment)});
+            break;
         case Use::kFunctionReturnType:
             Func("f", utils::Empty, ty(expr), Return(Call(sym)));
             break;
@@ -271,6 +291,8 @@ INSTANTIATE_TEST_SUITE_P(
         {Def::kAccess, Use::kAddressSpace,
          R"(5:6 error: cannot use access 'write' as address space)"},
         {Def::kAccess, Use::kBinaryOp, R"(5:6 error: cannot use access 'write' as value)"},
+        {Def::kAccess, Use::kBuiltinValue,
+         R"(5:6 error: cannot use access 'write' as builtin value)"},
         {Def::kAccess, Use::kCallExpr, R"(5:6 error: cannot use access 'write' as call target)"},
         {Def::kAccess, Use::kCallStmt, R"(5:6 error: cannot use access 'write' as call target)"},
         {Def::kAccess, Use::kFunctionReturnType, R"(5:6 error: cannot use access 'write' as type)"},
@@ -286,6 +308,8 @@ INSTANTIATE_TEST_SUITE_P(
         {Def::kAddressSpace, Use::kAddressSpace, kPass},
         {Def::kAddressSpace, Use::kBinaryOp,
          R"(5:6 error: cannot use address space 'workgroup' as value)"},
+        {Def::kAddressSpace, Use::kBuiltinValue,
+         R"(5:6 error: cannot use address space 'workgroup' as builtin value)"},
         {Def::kAddressSpace, Use::kCallExpr,
          R"(5:6 error: cannot use address space 'workgroup' as call target)"},
         {Def::kAddressSpace, Use::kCallStmt,
@@ -309,6 +333,8 @@ INSTANTIATE_TEST_SUITE_P(
          R"(7:8 error: missing '(' for builtin function call)"},
         {Def::kBuiltinFunction, Use::kBinaryOp,
          R"(7:8 error: missing '(' for builtin function call)"},
+        {Def::kBuiltinFunction, Use::kBuiltinValue,
+         R"(7:8 error: missing '(' for builtin function call)"},
         {Def::kBuiltinFunction, Use::kCallStmt, kPass},
         {Def::kBuiltinFunction, Use::kFunctionReturnType,
          R"(7:8 error: missing '(' for builtin function call)"},
@@ -329,6 +355,8 @@ INSTANTIATE_TEST_SUITE_P(
         {Def::kBuiltinType, Use::kBinaryOp,
          R"(5:6 error: cannot use type 'vec4<f32>' as value
 7:8 note: are you missing '()' for type initializer?)"},
+        {Def::kBuiltinType, Use::kBuiltinValue,
+         R"(5:6 error: cannot use type 'vec4<f32>' as builtin value)"},
         {Def::kBuiltinType, Use::kCallExpr, kPass},
         {Def::kBuiltinType, Use::kFunctionReturnType, kPass},
         {Def::kBuiltinType, Use::kMemberType, kPass},
@@ -342,12 +370,39 @@ INSTANTIATE_TEST_SUITE_P(
          R"(5:6 error: cannot use type 'vec4<f32>' as value
 7:8 note: are you missing '()' for type initializer?)"},
 
+        {Def::kBuiltinValue, Use::kAccess,
+         R"(5:6 error: cannot use builtin value 'position' as access)"},
+        {Def::kBuiltinValue, Use::kAddressSpace,
+         R"(5:6 error: cannot use builtin value 'position' as address space)"},
+        {Def::kBuiltinValue, Use::kBinaryOp,
+         R"(5:6 error: cannot use builtin value 'position' as value)"},
+        {Def::kBuiltinValue, Use::kBuiltinValue, kPass},
+        {Def::kBuiltinValue, Use::kCallStmt,
+         R"(5:6 error: cannot use builtin value 'position' as call target)"},
+        {Def::kBuiltinValue, Use::kCallExpr,
+         R"(5:6 error: cannot use builtin value 'position' as call target)"},
+        {Def::kBuiltinValue, Use::kFunctionReturnType,
+         R"(5:6 error: cannot use builtin value 'position' as type)"},
+        {Def::kBuiltinValue, Use::kMemberType,
+         R"(5:6 error: cannot use builtin value 'position' as type)"},
+        {Def::kBuiltinValue, Use::kTexelFormat,
+         R"(5:6 error: cannot use builtin value 'position' as texel format)"},
+        {Def::kBuiltinValue, Use::kValueExpression,
+         R"(5:6 error: cannot use builtin value 'position' as value)"},
+        {Def::kBuiltinValue, Use::kVariableType,
+         R"(5:6 error: cannot use builtin value 'position' as type)"},
+        {Def::kBuiltinValue, Use::kUnaryOp,
+         R"(5:6 error: cannot use builtin value 'position' as value)"},
+
         {Def::kFunction, Use::kAccess, R"(5:6 error: cannot use function 'FUNCTION' as access
 1:2 note: function 'FUNCTION' declared here)"},
         {Def::kFunction, Use::kAddressSpace,
          R"(5:6 error: cannot use function 'FUNCTION' as address space
 1:2 note: function 'FUNCTION' declared here)"},
         {Def::kFunction, Use::kBinaryOp, R"(5:6 error: cannot use function 'FUNCTION' as value
+1:2 note: function 'FUNCTION' declared here)"},
+        {Def::kFunction, Use::kBuiltinValue,
+         R"(5:6 error: cannot use function 'FUNCTION' as builtin value
 1:2 note: function 'FUNCTION' declared here)"},
         {Def::kFunction, Use::kCallExpr, kPass},
         {Def::kFunction, Use::kCallStmt, kPass},
@@ -375,6 +430,8 @@ INSTANTIATE_TEST_SUITE_P(
         {Def::kStruct, Use::kBinaryOp, R"(5:6 error: cannot use type 'STRUCT' as value
 7:8 note: are you missing '()' for type initializer?
 1:2 note: struct 'STRUCT' declared here)"},
+        {Def::kStruct, Use::kBuiltinValue,
+         R"(5:6 error: cannot use type 'STRUCT' as builtin value)"},
         {Def::kStruct, Use::kFunctionReturnType, kPass},
         {Def::kStruct, Use::kMemberType, kPass},
         {Def::kStruct, Use::kTexelFormat, R"(5:6 error: cannot use type 'STRUCT' as texel format)"},
@@ -394,6 +451,8 @@ INSTANTIATE_TEST_SUITE_P(
          R"(5:6 error: cannot use texel format 'rgba8unorm' as address space)"},
         {Def::kTexelFormat, Use::kBinaryOp,
          R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"},
+        {Def::kTexelFormat, Use::kBuiltinValue,
+         R"(5:6 error: cannot use texel format 'rgba8unorm' as builtin value)"},
         {Def::kTexelFormat, Use::kCallExpr,
          R"(5:6 error: cannot use texel format 'rgba8unorm' as call target)"},
         {Def::kTexelFormat, Use::kCallStmt,
@@ -416,6 +475,8 @@ INSTANTIATE_TEST_SUITE_P(
         {Def::kTypeAlias, Use::kBinaryOp,
          R"(5:6 error: cannot use type 'i32' as value
 7:8 note: are you missing '()' for type initializer?)"},
+        {Def::kTypeAlias, Use::kBuiltinValue,
+         R"(5:6 error: cannot use type 'i32' as builtin value)"},
         {Def::kTypeAlias, Use::kCallExpr, kPass},
         {Def::kTypeAlias, Use::kFunctionReturnType, kPass},
         {Def::kTypeAlias, Use::kMemberType, kPass},
@@ -434,6 +495,9 @@ INSTANTIATE_TEST_SUITE_P(
          R"(5:6 error: cannot use const 'VARIABLE' as address space
 1:2 note: const 'VARIABLE' declared here)"},
         {Def::kVariable, Use::kBinaryOp, kPass},
+        {Def::kVariable, Use::kBuiltinValue,
+         R"(5:6 error: cannot use const 'VARIABLE' as builtin value
+1:2 note: const 'VARIABLE' declared here)"},
         {Def::kVariable, Use::kCallStmt,
          R"(5:6 error: cannot use const 'VARIABLE' as call target
 1:2 note: const 'VARIABLE' declared here)"},
diff --git a/src/tint/resolver/function_validation_test.cc b/src/tint/resolver/function_validation_test.cc
index b6b5ed6422..b7af242ec3 100644
--- a/src/tint/resolver/function_validation_test.cc
+++ b/src/tint/resolver/function_validation_test.cc
@@ -15,6 +15,7 @@
 #include "src/tint/ast/discard_statement.h"
 #include "src/tint/ast/return_statement.h"
 #include "src/tint/ast/stage_attribute.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/resolver/resolver.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 2bbf15d817..3d0b5398f3 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -89,6 +89,7 @@
 
 TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::builtin::Access>);
 TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::builtin::AddressSpace>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::builtin::BuiltinValue>);
 TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::builtin::TexelFormat>);
 
 namespace tint::resolver {
@@ -611,7 +612,9 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
     };
 
     for (auto* attr : param->attributes) {
-        Mark(attr);
+        if (!Attribute(attr)) {
+            return nullptr;
+        }
     }
     if (!validator_.NoDuplicateAttributes(param->attributes)) {
         return nullptr;
@@ -792,7 +795,9 @@ sem::GlobalVariable* Resolver::GlobalVariable(const ast::Variable* v) {
     }
 
     for (auto* attr : v->attributes) {
-        Mark(attr);
+        if (!Attribute(attr)) {
+            return nullptr;
+        }
     }
 
     if (!validator_.NoDuplicateAttributes(v->attributes)) {
@@ -854,11 +859,8 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
     validator_.DiagnosticFilters().Push();
     TINT_DEFER(validator_.DiagnosticFilters().Pop());
     for (auto* attr : decl->attributes) {
-        Mark(attr);
-        if (auto* dc = attr->As<ast::DiagnosticAttribute>()) {
-            if (!DiagnosticControl(dc->control)) {
-                return nullptr;
-            }
+        if (!Attribute(attr)) {
+            return nullptr;
         }
     }
     if (!validator_.NoDuplicateAttributes(decl->attributes)) {
@@ -921,7 +923,9 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
     // Determine if the return type has a location
     std::optional<uint32_t> return_location;
     for (auto* attr : decl->return_type_attributes) {
-        Mark(attr);
+        if (!Attribute(attr)) {
+            return nullptr;
+        }
 
         if (auto* loc_attr = attr->As<ast::LocationAttribute>()) {
             auto value = LocationAttribute(loc_attr);
@@ -1502,6 +1506,11 @@ sem::BuiltinEnumExpression<builtin::AddressSpace>* Resolver::AddressSpaceExpress
     return sem_.AsAddressSpace(Expression(expr));
 }
 
+sem::BuiltinEnumExpression<builtin::BuiltinValue>* Resolver::BuiltinValueExpression(
+    const ast::Expression* expr) {
+    return sem_.AsBuiltinValue(Expression(expr));
+}
+
 sem::BuiltinEnumExpression<builtin::TexelFormat>* Resolver::TexelFormatExpression(
     const ast::Expression* expr) {
     return sem_.AsTexelFormat(Expression(expr));
@@ -2987,6 +2996,11 @@ sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) {
             expr, current_statement_, addr);
     }
 
+    if (auto builtin = resolved->BuiltinValue(); builtin != builtin::BuiltinValue::kUndefined) {
+        return builder_->create<sem::BuiltinEnumExpression<builtin::BuiltinValue>>(
+            expr, current_statement_, builtin);
+    }
+
     if (auto fmt = resolved->TexelFormat(); fmt != builtin::TexelFormat::kUndefined) {
         return builder_->create<sem::BuiltinEnumExpression<builtin::TexelFormat>>(
             expr, current_statement_, fmt);
@@ -3307,6 +3321,26 @@ sem::ValueExpression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
     return sem;
 }
 
+bool Resolver::Attribute(const ast::Attribute* attr) {
+    Mark(attr);
+    return Switch(
+        attr,  //
+        [&](const ast::BuiltinAttribute* b) { return BuiltinAttribute(b); },
+        [&](const ast::DiagnosticAttribute* dc) { return DiagnosticControl(dc->control); },
+        [&](Default) { return true; });
+}
+
+bool Resolver::BuiltinAttribute(const ast::BuiltinAttribute* attr) {
+    auto* builtin_expr = BuiltinValueExpression(attr->builtin);
+    if (!builtin_expr) {
+        return false;
+    }
+    // Apply the resolved tint::sem::BuiltinEnumExpression<tint::builtin::BuiltinValue> to the
+    // attribute.
+    builder_->Sem().Add(attr, builtin_expr);
+    return true;
+}
+
 bool Resolver::DiagnosticControl(const ast::DiagnosticControl& control) {
     Mark(control.rule_name);
 
@@ -3522,7 +3556,9 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
         bool has_size_attr = false;
         std::optional<uint32_t> location;
         for (auto* attr : member->attributes) {
-            Mark(attr);
+            if (!Attribute(attr)) {
+                return nullptr;
+            }
             bool ok = Switch(
                 attr,  //
                 [&](const ast::StructMemberOffsetAttribute* o) {
diff --git a/src/tint/resolver/resolver.h b/src/tint/resolver/resolver.h
index 6829bac3dd..2a04a2a558 100644
--- a/src/tint/resolver/resolver.h
+++ b/src/tint/resolver/resolver.h
@@ -146,9 +146,15 @@ class Resolver {
         const ast::Expression* expr);
 
     /// @returns the call of Expression() cast to a
-    /// sem::BuiltinEnumExpression<builtin::TexelFormat>. If the sem::Expression is not a
-    /// sem::BuiltinEnumExpression<builtin::TexelFormat>, then an error diagnostic is raised and
+    /// sem::BuiltinEnumExpression<builtin::BuiltinValue>. If the sem::Expression is not a
+    /// sem::BuiltinEnumExpression<builtin::BuiltinValue>, then an error diagnostic is raised and
     /// nullptr is returned.
+    sem::BuiltinEnumExpression<builtin::BuiltinValue>* BuiltinValueExpression(
+        const ast::Expression* expr);
+
+    /// @returns the call of Expression() cast to a sem::BuiltinEnumExpression<type::TexelFormat>.
+    /// If the sem::Expression is not a sem::BuiltinEnumExpression<type::TexelFormat>, then an error
+    /// diagnostic is raised and nullptr is returned.
     sem::BuiltinEnumExpression<builtin::TexelFormat>* TexelFormatExpression(
         const ast::Expression* expr);
 
@@ -290,6 +296,14 @@ class Resolver {
     /// current_function_
     bool WorkgroupSize(const ast::Function*);
 
+    /// Resolves the attribute @p attr
+    /// @returns true on success, false on failure
+    bool Attribute(const ast::Attribute* attr);
+
+    /// Resolves the `@builtin` attribute @p attr
+    /// @returns true on success, false on failure
+    bool BuiltinAttribute(const ast::BuiltinAttribute* attr);
+
     /// @param control the diagnostic control
     /// @returns true on success, false on failure
     bool DiagnosticControl(const ast::DiagnosticControl& control);
diff --git a/src/tint/resolver/resolver_test.cc b/src/tint/resolver/resolver_test.cc
index 87bb8d0067..0915866246 100644
--- a/src/tint/resolver/resolver_test.cc
+++ b/src/tint/resolver/resolver_test.cc
@@ -34,6 +34,7 @@
 #include "src/tint/ast/unary_op_expression.h"
 #include "src/tint/ast/variable_decl_statement.h"
 #include "src/tint/ast/workgroup_attribute.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 #include "src/tint/sem/call.h"
 #include "src/tint/sem/function.h"
diff --git a/src/tint/resolver/sem_helper.cc b/src/tint/resolver/sem_helper.cc
index 3379ad264c..b8c328c613 100644
--- a/src/tint/resolver/sem_helper.cc
+++ b/src/tint/resolver/sem_helper.cc
@@ -84,6 +84,11 @@ void SemHelper::ErrorUnexpectedExprKind(const sem::Expression* expr,
                          std::string(wanted),
                      addr->Declaration()->source);
         },
+        [&](const sem::BuiltinEnumExpression<builtin::BuiltinValue>* builtin) {
+            AddError("cannot use builtin value '" + utils::ToString(builtin->Value()) + "' as " +
+                         std::string(wanted),
+                     builtin->Declaration()->source);
+        },
         [&](const sem::BuiltinEnumExpression<builtin::TexelFormat>* fmt) {
             AddError("cannot use texel format '" + utils::ToString(fmt->Value()) + "' as " +
                          std::string(wanted),
diff --git a/src/tint/resolver/sem_helper.h b/src/tint/resolver/sem_helper.h
index e8940d109d..a7c37b1629 100644
--- a/src/tint/resolver/sem_helper.h
+++ b/src/tint/resolver/sem_helper.h
@@ -17,6 +17,7 @@
 
 #include <string>
 
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/diagnostic/diagnostic.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/resolver/dependency_graph.h"
@@ -120,8 +121,23 @@ class SemHelper {
 
     /// @param expr the semantic node
     /// @returns nullptr if @p expr is nullptr, or @p expr cast to
-    /// sem::BuiltinEnumExpression<builtin::TexelFormat> if the cast is successful, otherwise an
+    /// sem::BuiltinEnumExpression<builtin::BuiltinValue> if the cast is successful, otherwise an
     /// error diagnostic is raised.
+    sem::BuiltinEnumExpression<builtin::BuiltinValue>* AsBuiltinValue(sem::Expression* expr) const {
+        if (TINT_LIKELY(expr)) {
+            auto* enum_expr = expr->As<sem::BuiltinEnumExpression<builtin::BuiltinValue>>();
+            if (TINT_LIKELY(enum_expr)) {
+                return enum_expr;
+            }
+            ErrorUnexpectedExprKind(expr, "builtin value");
+        }
+        return nullptr;
+    }
+
+    /// @param expr the semantic node
+    /// @returns nullptr if @p expr is nullptr, or @p expr cast to
+    /// sem::BuiltinEnumExpression<type::TexelFormat> if the cast is successful, otherwise an error
+    /// diagnostic is raised.
     sem::BuiltinEnumExpression<builtin::TexelFormat>* AsTexelFormat(sem::Expression* expr) const {
         if (TINT_LIKELY(expr)) {
             auto* enum_expr = expr->As<sem::BuiltinEnumExpression<builtin::TexelFormat>>();
diff --git a/src/tint/resolver/struct_pipeline_stage_use_test.cc b/src/tint/resolver/struct_pipeline_stage_use_test.cc
index 90e9505c9d..4707650af9 100644
--- a/src/tint/resolver/struct_pipeline_stage_use_test.cc
+++ b/src/tint/resolver/struct_pipeline_stage_use_test.cc
@@ -16,6 +16,7 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/ast/stage_attribute.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 #include "src/tint/sem/struct.h"
 
diff --git a/src/tint/resolver/uniformity.cc b/src/tint/resolver/uniformity.cc
index 549c0cc697..d02be8dc0b 100644
--- a/src/tint/resolver/uniformity.cc
+++ b/src/tint/resolver/uniformity.cc
@@ -20,6 +20,7 @@
 #include <utility>
 #include <vector>
 
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/resolver/dependency_graph.h"
 #include "src/tint/scope_stack.h"
@@ -1145,11 +1146,12 @@ class UniformityGraph {
                                                    const ast::IdentifierExpression* ident,
                                                    bool load_rule = false) {
         // Helper to check if the entry point attribute of `obj` indicates non-uniformity.
-        auto has_nonuniform_entry_point_attribute = [](auto* obj) {
+        auto has_nonuniform_entry_point_attribute = [&](auto* obj) {
             // Only the num_workgroups and workgroup_id builtins are uniform.
-            if (auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(obj->attributes)) {
-                if (builtin->builtin == builtin::BuiltinValue::kNumWorkgroups ||
-                    builtin->builtin == builtin::BuiltinValue::kWorkgroupId) {
+            if (auto* builtin_attr = ast::GetAttribute<ast::BuiltinAttribute>(obj->attributes)) {
+                auto builtin = builder_->Sem().Get(builtin_attr)->Value();
+                if (builtin == builtin::BuiltinValue::kNumWorkgroups ||
+                    builtin == builtin::BuiltinValue::kWorkgroupId) {
                     return false;
                 }
             }
diff --git a/src/tint/resolver/validation_test.cc b/src/tint/resolver/validation_test.cc
index 0e239dd2e6..1e806d3f1b 100644
--- a/src/tint/resolver/validation_test.cc
+++ b/src/tint/resolver/validation_test.cc
@@ -30,6 +30,7 @@
 #include "src/tint/ast/switch_statement.h"
 #include "src/tint/ast/unary_op_expression.h"
 #include "src/tint/ast/variable_decl_statement.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 #include "src/tint/sem/call.h"
 #include "src/tint/sem/function.h"
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index ebb8284692..5e64d98ad2 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -114,15 +114,11 @@ bool IsValidStorageTextureTexelFormat(builtin::TexelFormat format) {
 }
 
 // Helper to stringify a pipeline IO attribute.
-std::string attr_to_str(const ast::Attribute* attr,
-                        std::optional<uint32_t> location = std::nullopt) {
-    std::stringstream str;
-    if (auto* builtin = attr->As<ast::BuiltinAttribute>()) {
-        str << "builtin(" << builtin->builtin << ")";
-    } else if (attr->Is<ast::LocationAttribute>()) {
-        str << "location(" << location.value() << ")";
-    }
-    return str.str();
+std::string AttrToStr(const ast::Attribute* attr) {
+    return Switch(
+        attr,  //
+        [&](const ast::BuiltinAttribute*) { return "@builtin"; },
+        [&](const ast::LocationAttribute*) { return "@location"; });
 }
 
 template <typename CALLBACK>
@@ -868,7 +864,8 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
     stage_name << stage;
     bool is_stage_mismatch = false;
     bool is_output = !is_input;
-    switch (attr->builtin) {
+    auto builtin = sem_.Get(attr)->Value();
+    switch (builtin) {
         case builtin::BuiltinValue::kPosition:
             if (stage != ast::PipelineStage::kNone &&
                 !((is_input && stage == ast::PipelineStage::kFragment) ||
@@ -876,8 +873,9 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
                 is_stage_mismatch = true;
             }
             if (!(type->is_float_vector() && type->As<type::Vector>()->Width() == 4)) {
-                AddError("store type of " + attr_to_str(attr) + " must be 'vec4<f32>'",
-                         attr->source);
+                std::stringstream err;
+                err << "store type of @builtin(" << builtin << ") must be 'vec4<f32>'";
+                AddError(err.str(), attr->source);
                 return false;
             }
             break;
@@ -890,8 +888,9 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
                 is_stage_mismatch = true;
             }
             if (!(type->is_unsigned_integer_vector() && type->As<type::Vector>()->Width() == 3)) {
-                AddError("store type of " + attr_to_str(attr) + " must be 'vec3<u32>'",
-                         attr->source);
+                std::stringstream err;
+                err << "store type of @builtin(" << builtin << ") must be 'vec3<u32>'";
+                AddError(err.str(), attr->source);
                 return false;
             }
             break;
@@ -901,7 +900,9 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
                 is_stage_mismatch = true;
             }
             if (!type->Is<type::F32>()) {
-                AddError("store type of " + attr_to_str(attr) + " must be 'f32'", attr->source);
+                std::stringstream err;
+                err << "store type of @builtin(" << builtin << ") must be 'f32'";
+                AddError(err.str(), attr->source);
                 return false;
             }
             break;
@@ -911,7 +912,9 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
                 is_stage_mismatch = true;
             }
             if (!type->Is<type::Bool>()) {
-                AddError("store type of " + attr_to_str(attr) + " must be 'bool'", attr->source);
+                std::stringstream err;
+                err << "store type of @builtin(" << builtin << ") must be 'bool'";
+                AddError(err.str(), attr->source);
                 return false;
             }
             break;
@@ -921,7 +924,9 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
                 is_stage_mismatch = true;
             }
             if (!type->Is<type::U32>()) {
-                AddError("store type of " + attr_to_str(attr) + " must be 'u32'", attr->source);
+                std::stringstream err;
+                err << "store type of @builtin(" << builtin << ") must be 'u32'";
+                AddError(err.str(), attr->source);
                 return false;
             }
             break;
@@ -932,7 +937,9 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
                 is_stage_mismatch = true;
             }
             if (!type->Is<type::U32>()) {
-                AddError("store type of " + attr_to_str(attr) + " must be 'u32'", attr->source);
+                std::stringstream err;
+                err << "store type of @builtin(" << builtin << ") must be 'u32'";
+                AddError(err.str(), attr->source);
                 return false;
             }
             break;
@@ -941,7 +948,9 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
                 is_stage_mismatch = true;
             }
             if (!type->Is<type::U32>()) {
-                AddError("store type of " + attr_to_str(attr) + " must be 'u32'", attr->source);
+                std::stringstream err;
+                err << "store type of @builtin(" << builtin << ") must be 'u32'";
+                AddError(err.str(), attr->source);
                 return false;
             }
             break;
@@ -951,7 +960,9 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
                 is_stage_mismatch = true;
             }
             if (!type->Is<type::U32>()) {
-                AddError("store type of " + attr_to_str(attr) + " must be 'u32'", attr->source);
+                std::stringstream err;
+                err << "store type of @builtin(" << builtin << ") must be 'u32'";
+                AddError(err.str(), attr->source);
                 return false;
             }
             break;
@@ -960,9 +971,10 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
     }
 
     if (is_stage_mismatch) {
-        AddError(attr_to_str(attr) + " cannot be used in " +
-                     (is_input ? "input of " : "output of ") + stage_name.str() + " pipeline stage",
-                 attr->source);
+        std::stringstream err;
+        err << "@builtin(" << builtin << ") cannot be used in "
+            << (is_input ? "input of " : "output of ") << stage_name.str() << " pipeline stage";
+        AddError(err.str(), attr->source);
         return false;
     }
 
@@ -1098,32 +1110,34 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
         for (auto* attr : attrs) {
             auto is_invalid_compute_shader_attribute = false;
 
-            if (auto* builtin = attr->As<ast::BuiltinAttribute>()) {
+            if (auto* builtin_attr = attr->As<ast::BuiltinAttribute>()) {
+                auto builtin = sem_.Get(builtin_attr)->Value();
+
                 if (pipeline_io_attribute) {
                     AddError("multiple entry point IO attributes", attr->source);
-                    AddNote("previously consumed " + attr_to_str(pipeline_io_attribute, location),
+                    AddNote("previously consumed " + AttrToStr(pipeline_io_attribute),
                             pipeline_io_attribute->source);
                     return false;
                 }
                 pipeline_io_attribute = attr;
 
-                if (builtins.Contains(builtin->builtin)) {
-                    AddError(attr_to_str(builtin) +
-                                 " attribute appears multiple times as pipeline " +
-                                 (param_or_ret == ParamOrRetType::kParameter ? "input" : "output"),
-                             decl->source);
+                if (builtins.Contains(builtin)) {
+                    std::stringstream err;
+                    err << "@builtin(" << builtin << ") appears multiple times as pipeline "
+                        << (param_or_ret == ParamOrRetType::kParameter ? "input" : "output");
+                    AddError(err.str(), decl->source);
                     return false;
                 }
 
-                if (!BuiltinAttribute(builtin, ty, stage,
+                if (!BuiltinAttribute(builtin_attr, ty, stage,
                                       /* is_input */ param_or_ret == ParamOrRetType::kParameter)) {
                     return false;
                 }
-                builtins.Add(builtin->builtin);
+                builtins.Add(builtin);
             } else if (auto* loc_attr = attr->As<ast::LocationAttribute>()) {
                 if (pipeline_io_attribute) {
                     AddError("multiple entry point IO attributes", attr->source);
-                    AddNote("previously consumed " + attr_to_str(pipeline_io_attribute),
+                    AddNote("previously consumed " + AttrToStr(pipeline_io_attribute),
                             pipeline_io_attribute->source);
                     return false;
                 }
@@ -1183,16 +1197,16 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
                     if (decl->PipelineStage() == ast::PipelineStage::kVertex &&
                         param_or_ret == ParamOrRetType::kReturnType) {
                         AddError(
-                            "integral user-defined vertex outputs must have a flat "
-                            "interpolation attribute",
+                            "integral user-defined vertex outputs must have a flat interpolation "
+                            "attribute",
                             source);
                         return false;
                     }
                     if (decl->PipelineStage() == ast::PipelineStage::kFragment &&
                         param_or_ret == ParamOrRetType::kParameter) {
                         AddError(
-                            "integral user-defined fragment inputs must have a flat "
-                            "interpolation attribute",
+                            "integral user-defined fragment inputs must have a flat interpolation "
+                            "attribute",
                             source);
                         return false;
                     }
@@ -1211,15 +1225,14 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
             if (invariant_attribute) {
                 bool has_position = false;
                 if (pipeline_io_attribute) {
-                    if (auto* builtin = pipeline_io_attribute->As<ast::BuiltinAttribute>()) {
-                        has_position = (builtin->builtin == builtin::BuiltinValue::kPosition);
+                    if (auto* builtin_attr = pipeline_io_attribute->As<ast::BuiltinAttribute>()) {
+                        auto builtin = sem_.Get(builtin_attr)->Value();
+                        has_position = (builtin == builtin::BuiltinValue::kPosition);
                     }
                 }
                 if (!has_position) {
-                    AddError(
-                        "invariant attribute must only be applied to a position "
-                        "builtin",
-                        invariant_attribute->source);
+                    AddError("invariant attribute must only be applied to a position builtin",
+                             invariant_attribute->source);
                     return false;
                 }
             }
@@ -1280,9 +1293,10 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
         // Check module-scope variables, as the SPIR-V sanitizer generates these.
         bool found = false;
         for (auto* global : func->TransitivelyReferencedGlobals()) {
-            if (auto* builtin =
+            if (auto* builtin_attr =
                     ast::GetAttribute<ast::BuiltinAttribute>(global->Declaration()->attributes)) {
-                if (builtin->builtin == builtin::BuiltinValue::kPosition) {
+                auto builtin = sem_.Get(builtin_attr)->Value();
+                if (builtin == builtin::BuiltinValue::kPosition) {
                     found = true;
                     break;
                 }
@@ -2120,12 +2134,13 @@ bool Validator::Structure(const sem::Struct* str, ast::PipelineStage stage) cons
                     }
                     return true;
                 },
-                [&](const ast::BuiltinAttribute* builtin) {
-                    if (!BuiltinAttribute(builtin, member->Type(), stage,
+                [&](const ast::BuiltinAttribute* builtin_attr) {
+                    if (!BuiltinAttribute(builtin_attr, member->Type(), stage,
                                           /* is_input */ false)) {
                         return false;
                     }
-                    if (builtin->builtin == builtin::BuiltinValue::kPosition) {
+                    auto builtin = sem_.Get(builtin_attr)->Value();
+                    if (builtin == builtin::BuiltinValue::kPosition) {
                         has_position = true;
                     }
                     return true;
@@ -2208,18 +2223,18 @@ bool Validator::LocationAttribute(const ast::LocationAttribute* loc_attr,
 
     if (!type->is_numeric_scalar_or_vector()) {
         std::string invalid_type = sem_.TypeNameOf(type);
-        AddError("cannot apply 'location' attribute to declaration of type '" + invalid_type + "'",
-                 source);
+        AddError("cannot apply @location to declaration of type '" + invalid_type + "'", source);
         AddNote(
-            "'location' attribute must only be applied to declarations of numeric scalar or "
-            "numeric vector type",
+            "@location must only be applied to declarations of numeric scalar or numeric vector "
+            "type",
             loc_attr->source);
         return false;
     }
 
     if (!locations.Add(location)) {
-        AddError(attr_to_str(loc_attr, location) + " attribute appears multiple times",
-                 loc_attr->source);
+        std::stringstream err;
+        err << "@location(" << location << ") appears multiple times";
+        AddError(err.str(), loc_attr->source);
         return false;
     }
 
diff --git a/src/tint/sem/type_mappings.h b/src/tint/sem/type_mappings.h
index fa7d8c61e3..efcd3a6fb8 100644
--- a/src/tint/sem/type_mappings.h
+++ b/src/tint/sem/type_mappings.h
@@ -17,6 +17,8 @@
 
 #include <type_traits>
 
+#include "src/tint/sem/builtin_enum_expression.h"
+
 // Forward declarations
 namespace tint {
 class CastableBase;
@@ -25,6 +27,7 @@ namespace tint::ast {
 class AccessorExpression;
 class BinaryExpression;
 class BitcastExpression;
+class BuiltinAttribute;
 class CallExpression;
 class Expression;
 class ForLoopStatement;
@@ -43,6 +46,9 @@ class Variable;
 class WhileStatement;
 class UnaryOpExpression;
 }  // namespace tint::ast
+namespace tint::builtin {
+enum class BuiltinValue;
+}
 namespace tint::sem {
 class Expression;
 class ForLoopStatement;
@@ -71,21 +77,22 @@ namespace tint::sem {
 /// rules will be used to infer the return type based on the argument type.
 struct TypeMappings {
     //! @cond Doxygen_Suppress
+    BuiltinEnumExpression<builtin::BuiltinValue>* operator()(ast::BuiltinAttribute*);
+    CastableBase* operator()(ast::Node*);
+    Expression* operator()(ast::Expression*);
     ForLoopStatement* operator()(ast::ForLoopStatement*);
     Function* operator()(ast::Function*);
-    IfStatement* operator()(ast::IfStatement*);
-    CastableBase* operator()(ast::Node*);
     GlobalVariable* operator()(ast::Override*);
+    IfStatement* operator()(ast::IfStatement*);
     Statement* operator()(ast::Statement*);
     Struct* operator()(ast::Struct*);
     StructMember* operator()(ast::StructMember*);
     SwitchStatement* operator()(ast::SwitchStatement*);
     type::Type* operator()(ast::TypeDecl*);
-    Expression* operator()(ast::Expression*);
     ValueExpression* operator()(ast::AccessorExpression*);
-    ValueExpression* operator()(ast::CallExpression*);
     ValueExpression* operator()(ast::BinaryExpression*);
     ValueExpression* operator()(ast::BitcastExpression*);
+    ValueExpression* operator()(ast::CallExpression*);
     ValueExpression* operator()(ast::LiteralExpression*);
     ValueExpression* operator()(ast::PhonyExpression*);
     ValueExpression* operator()(ast::UnaryOpExpression*);
diff --git a/src/tint/transform/canonicalize_entry_point_io.cc b/src/tint/transform/canonicalize_entry_point_io.cc
index 80b51dcfba..3c9c6d0469 100644
--- a/src/tint/transform/canonicalize_entry_point_io.cc
+++ b/src/tint/transform/canonicalize_entry_point_io.cc
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "src/tint/ast/disable_validation_attribute.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/sem/function.h"
 #include "src/tint/transform/unshadow.h"
@@ -81,46 +82,12 @@ uint32_t BuiltinOrder(builtin::BuiltinValue builtin) {
     return 0;
 }
 
-/// Comparison function used to reorder struct members such that all members with
-/// location attributes appear first (ordered by location slot), followed by
-/// those with builtin attributes.
-/// @param a a struct member
-/// @param b another struct member
-/// @returns true if a comes before b
-bool StructMemberComparator(const MemberInfo& a, const MemberInfo& b) {
-    auto* a_loc = ast::GetAttribute<ast::LocationAttribute>(a.member->attributes);
-    auto* b_loc = ast::GetAttribute<ast::LocationAttribute>(b.member->attributes);
-    auto* a_blt = ast::GetAttribute<ast::BuiltinAttribute>(a.member->attributes);
-    auto* b_blt = ast::GetAttribute<ast::BuiltinAttribute>(b.member->attributes);
-    if (a_loc) {
-        if (!b_loc) {
-            // `a` has location attribute and `b` does not: `a` goes first.
-            return true;
-        }
-        // Both have location attributes: smallest goes first.
-        return a.location < b.location;
-    } else {
-        if (b_loc) {
-            // `b` has location attribute and `a` does not: `b` goes first.
-            return false;
-        }
-        // Both are builtins: order matters for FXC.
-        return BuiltinOrder(a_blt->builtin) < BuiltinOrder(b_blt->builtin);
-    }
-}
-
 // Returns true if `attr` is a shader IO attribute.
 bool IsShaderIOAttribute(const ast::Attribute* attr) {
     return attr->IsAnyOf<ast::BuiltinAttribute, ast::InterpolateAttribute, ast::InvariantAttribute,
                          ast::LocationAttribute>();
 }
 
-// Returns true if `attrs` contains a `sample_mask` builtin.
-bool HasSampleMask(utils::VectorRef<const ast::Attribute*> attrs) {
-    auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(attrs);
-    return builtin && builtin->builtin == builtin::BuiltinValue::kSampleMask;
-}
-
 }  // namespace
 
 /// PIMPL state for the transform
@@ -132,7 +99,7 @@ struct CanonicalizeEntryPointIO::State {
         /// The type of the output value.
         ast::Type type;
         /// The shader IO attributes.
-        utils::Vector<const ast::Attribute*, 2> attributes;
+        utils::Vector<const ast::Attribute*, 8> attributes;
         /// The value itself.
         const ast::Expression* value;
         /// The output location.
@@ -165,6 +132,8 @@ struct CanonicalizeEntryPointIO::State {
     utils::Vector<const ast::Statement*, 8> wrapper_body;
     /// Input names used by the entrypoint
     std::unordered_set<std::string> input_names;
+    /// A map of cloned attribute to builtin value
+    utils::Hashmap<const ast::BuiltinAttribute*, builtin::BuiltinValue, 16> builtin_attrs;
 
     /// Constructor
     /// @param context the clone context
@@ -175,20 +144,64 @@ struct CanonicalizeEntryPointIO::State {
           const ast::Function* function)
         : ctx(context), cfg(config), func_ast(function), func_sem(ctx.src->Sem().Get(function)) {}
 
-    /// Clones the shader IO attributes from `src`.
-    /// @param src the attributes to clone
+    /// Clones the attributes from @p in and adds it to @p out. If @p in is a builtin attribute,
+    /// then builtin_attrs is updated with the builtin information.
+    /// @param in the attribute to clone
+    /// @param out the output Attributes
+    template <size_t N>
+    void CloneAttribute(const ast::Attribute* in, utils::Vector<const ast::Attribute*, N>& out) {
+        auto* cloned = ctx.Clone(in);
+        out.Push(cloned);
+        if (auto* builtin = in->As<ast::BuiltinAttribute>()) {
+            builtin_attrs.Add(cloned->As<ast::BuiltinAttribute>(),
+                              ctx.src->Sem().Get(builtin)->Value());
+        }
+    }
+
+    /// Clones the shader IO attributes from @p in.
+    /// @param in the attributes to clone
     /// @param do_interpolate whether to clone InterpolateAttribute
     /// @return the cloned attributes
     template <size_t N>
-    auto CloneShaderIOAttributes(utils::Vector<const ast::Attribute*, N> src, bool do_interpolate) {
-        utils::Vector<const ast::Attribute*, N> new_attributes;
-        for (auto* attr : src) {
+    auto CloneShaderIOAttributes(const utils::Vector<const ast::Attribute*, N> in,
+                                 bool do_interpolate) {
+        utils::Vector<const ast::Attribute*, N> out;
+        for (auto* attr : in) {
             if (IsShaderIOAttribute(attr) &&
                 (do_interpolate || !attr->template Is<ast::InterpolateAttribute>())) {
-                new_attributes.Push(ctx.Clone(attr));
+                CloneAttribute(attr, out);
             }
         }
-        return new_attributes;
+        return out;
+    }
+
+    /// @param attr the input attribute
+    /// @returns the builtin value of the attribute
+    builtin::BuiltinValue BuiltinOf(const ast::BuiltinAttribute* attr) {
+        if (attr->program_id == ctx.dst->ID()) {
+            // attr belongs to the target program.
+            // Obtain the builtin value from #builtin_attrs.
+            if (auto b = builtin_attrs.Get(attr)) {
+                return *b;
+            }
+        } else {
+            // attr belongs to the source program.
+            // Obtain the builtin value from the semantic info.
+            return ctx.src->Sem().Get(attr)->Value();
+        }
+        TINT_ICE(Resolver, ctx.dst->Diagnostics())
+            << "could not obtain builtin value from attribute";
+        return builtin::BuiltinValue::kUndefined;
+    }
+
+    /// @param attrs the input attribute list
+    /// @returns the builtin value if any of the attributes in @p attrs is a builtin attribute,
+    /// otherwise builtin::BuiltinValue::kUndefined
+    builtin::BuiltinValue BuiltinOf(utils::VectorRef<const ast::Attribute*> attrs) {
+        if (auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(attrs)) {
+            return BuiltinOf(builtin);
+        }
+        return builtin::BuiltinValue::kUndefined;
     }
 
     /// Create or return a symbol for the wrapper function's struct parameter.
@@ -204,13 +217,16 @@ struct CanonicalizeEntryPointIO::State {
     /// @param name the name of the shader input
     /// @param type the type of the shader input
     /// @param location the location if provided
-    /// @param attributes the attributes to apply to the shader input
+    /// @param attrs the attributes to apply to the shader input
     /// @returns an expression which evaluates to the value of the shader input
     const ast::Expression* AddInput(std::string name,
                                     const type::Type* type,
                                     std::optional<uint32_t> location,
-                                    utils::Vector<const ast::Attribute*, 8> attributes) {
+                                    utils::Vector<const ast::Attribute*, 8> attrs) {
         auto ast_type = CreateASTTypeFor(ctx, type);
+
+        auto builtin_attr = BuiltinOf(attrs);
+
         if (cfg.shader_style == ShaderStyle::kSpirv || cfg.shader_style == ShaderStyle::kGlsl) {
             // Vulkan requires that integer user-defined fragment inputs are always decorated with
             // `Flat`. See:
@@ -219,21 +235,21 @@ struct CanonicalizeEntryPointIO::State {
             // required for integers.
             if (func_ast->PipelineStage() == ast::PipelineStage::kFragment &&
                 type->is_integer_scalar_or_vector() &&
-                !ast::HasAttribute<ast::InterpolateAttribute>(attributes) &&
-                (ast::HasAttribute<ast::LocationAttribute>(attributes) ||
+                !ast::HasAttribute<ast::InterpolateAttribute>(attrs) &&
+                (ast::HasAttribute<ast::LocationAttribute>(attrs) ||
                  cfg.shader_style == ShaderStyle::kSpirv)) {
-                attributes.Push(ctx.dst->Interpolate(builtin::InterpolationType::kFlat,
-                                                     builtin::InterpolationSampling::kUndefined));
+                attrs.Push(ctx.dst->Interpolate(builtin::InterpolationType::kFlat,
+                                                builtin::InterpolationSampling::kUndefined));
             }
 
             // Disable validation for use of the `input` address space.
-            attributes.Push(ctx.dst->Disable(ast::DisabledValidation::kIgnoreAddressSpace));
+            attrs.Push(ctx.dst->Disable(ast::DisabledValidation::kIgnoreAddressSpace));
 
             // In GLSL, if it's a builtin, override the name with the
             // corresponding gl_ builtin name
-            auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(attributes);
-            if (cfg.shader_style == ShaderStyle::kGlsl && builtin) {
-                name = GLSLBuiltinToString(builtin->builtin, func_ast->PipelineStage(),
+            if (cfg.shader_style == ShaderStyle::kGlsl &&
+                builtin_attr != builtin::BuiltinValue::kUndefined) {
+                name = GLSLBuiltinToString(builtin_attr, func_ast->PipelineStage(),
                                            builtin::AddressSpace::kIn);
             }
             auto symbol = ctx.dst->Symbols().New(name);
@@ -241,32 +257,32 @@ struct CanonicalizeEntryPointIO::State {
             // Create the global variable and use its value for the shader input.
             const ast::Expression* value = ctx.dst->Expr(symbol);
 
-            if (builtin) {
+            if (builtin_attr != builtin::BuiltinValue::kUndefined) {
                 if (cfg.shader_style == ShaderStyle::kGlsl) {
-                    value = FromGLSLBuiltin(builtin->builtin, value, ast_type);
-                } else if (builtin->builtin == builtin::BuiltinValue::kSampleMask) {
+                    value = FromGLSLBuiltin(builtin_attr, value, ast_type);
+                } else if (builtin_attr == builtin::BuiltinValue::kSampleMask) {
                     // Vulkan requires the type of a SampleMask builtin to be an array.
                     // Declare it as array<u32, 1> and then load the first element.
                     ast_type = ctx.dst->ty.array(ast_type, 1_u);
                     value = ctx.dst->IndexAccessor(value, 0_i);
                 }
             }
-            ctx.dst->GlobalVar(symbol, ast_type, builtin::AddressSpace::kIn, std::move(attributes));
+            ctx.dst->GlobalVar(symbol, ast_type, builtin::AddressSpace::kIn, std::move(attrs));
             return value;
         } else if (cfg.shader_style == ShaderStyle::kMsl &&
-                   ast::HasAttribute<ast::BuiltinAttribute>(attributes)) {
+                   builtin_attr != builtin::BuiltinValue::kUndefined) {
             // If this input is a builtin and we are targeting MSL, then add it to the
             // parameter list and pass it directly to the inner function.
             Symbol symbol = input_names.emplace(name).second ? ctx.dst->Symbols().Register(name)
                                                              : ctx.dst->Symbols().New(name);
-            wrapper_ep_parameters.Push(ctx.dst->Param(symbol, ast_type, std::move(attributes)));
+            wrapper_ep_parameters.Push(ctx.dst->Param(symbol, ast_type, std::move(attrs)));
             return ctx.dst->Expr(symbol);
         } else {
             // Otherwise, move it to the new structure member list.
             Symbol symbol = input_names.emplace(name).second ? ctx.dst->Symbols().Register(name)
                                                              : ctx.dst->Symbols().New(name);
             wrapper_struct_param_members.Push(
-                {ctx.dst->Member(symbol, ast_type, std::move(attributes)), location});
+                {ctx.dst->Member(symbol, ast_type, std::move(attrs)), location});
             return ctx.dst->MemberAccessor(InputStructSymbol(), symbol);
         }
     }
@@ -275,13 +291,14 @@ struct CanonicalizeEntryPointIO::State {
     /// @param name the name of the shader output
     /// @param type the type of the shader output
     /// @param location the location if provided
-    /// @param attributes the attributes to apply to the shader output
+    /// @param attrs the attributes to apply to the shader output
     /// @param value the value of the shader output
     void AddOutput(std::string name,
                    const type::Type* type,
                    std::optional<uint32_t> location,
-                   utils::Vector<const ast::Attribute*, 8> attributes,
+                   utils::Vector<const ast::Attribute*, 8> attrs,
                    const ast::Expression* value) {
+        auto builtin_attr = BuiltinOf(attrs);
         // Vulkan requires that integer user-defined vertex outputs are always decorated with
         // `Flat`.
         // TODO(crbug.com/tint/1224): Remove this once a flat interpolation attribute is required
@@ -289,26 +306,26 @@ struct CanonicalizeEntryPointIO::State {
         if (cfg.shader_style == ShaderStyle::kSpirv &&
             func_ast->PipelineStage() == ast::PipelineStage::kVertex &&
             type->is_integer_scalar_or_vector() &&
-            ast::HasAttribute<ast::LocationAttribute>(attributes) &&
-            !ast::HasAttribute<ast::InterpolateAttribute>(attributes)) {
-            attributes.Push(ctx.dst->Interpolate(builtin::InterpolationType::kFlat,
-                                                 builtin::InterpolationSampling::kUndefined));
+            ast::HasAttribute<ast::LocationAttribute>(attrs) &&
+            !ast::HasAttribute<ast::InterpolateAttribute>(attrs)) {
+            attrs.Push(ctx.dst->Interpolate(builtin::InterpolationType::kFlat,
+                                            builtin::InterpolationSampling::kUndefined));
         }
 
         // In GLSL, if it's a builtin, override the name with the
         // corresponding gl_ builtin name
         if (cfg.shader_style == ShaderStyle::kGlsl) {
-            if (auto* b = ast::GetAttribute<ast::BuiltinAttribute>(attributes)) {
-                name = GLSLBuiltinToString(b->builtin, func_ast->PipelineStage(),
+            if (builtin_attr != builtin::BuiltinValue::kUndefined) {
+                name = GLSLBuiltinToString(builtin_attr, func_ast->PipelineStage(),
                                            builtin::AddressSpace::kOut);
-                value = ToGLSLBuiltin(b->builtin, value, type);
+                value = ToGLSLBuiltin(builtin_attr, value, type);
             }
         }
 
         OutputValue output;
         output.name = name;
         output.type = CreateASTTypeFor(ctx, type);
-        output.attributes = std::move(attributes);
+        output.attributes = std::move(attrs);
         output.value = value;
         output.location = location;
         wrapper_output_values.Push(output);
@@ -322,14 +339,14 @@ struct CanonicalizeEntryPointIO::State {
     void ProcessNonStructParameter(const sem::Parameter* param) {
         // Do not add interpolation attributes on vertex input
         bool do_interpolate = func_ast->PipelineStage() != ast::PipelineStage::kVertex;
-        // Remove the shader IO attributes from the inner function parameter, and
-        // attach them to the new object instead.
+        // Remove the shader IO attributes from the inner function parameter, and attach them to the
+        // new object instead.
         utils::Vector<const ast::Attribute*, 8> attributes;
         for (auto* attr : param->Declaration()->attributes) {
             if (IsShaderIOAttribute(attr)) {
                 ctx.Remove(param->Declaration()->attributes, attr);
                 if ((do_interpolate || !attr->Is<ast::InterpolateAttribute>())) {
-                    attributes.Push(ctx.Clone(attr));
+                    CloneAttribute(attr, attributes);
                 }
             }
         }
@@ -412,25 +429,28 @@ struct CanonicalizeEntryPointIO::State {
     void AddFixedSampleMask() {
         // Check the existing output values for a sample mask builtin.
         for (auto& outval : wrapper_output_values) {
-            if (HasSampleMask(outval.attributes)) {
+            if (BuiltinOf(outval.attributes) == builtin::BuiltinValue::kSampleMask) {
                 // Combine the authored sample mask with the fixed mask.
                 outval.value = ctx.dst->And(outval.value, u32(cfg.fixed_sample_mask));
                 return;
             }
         }
 
-        // No existing sample mask builtin was found, so create a new output value
-        // using the fixed sample mask.
-        AddOutput("fixed_sample_mask", ctx.dst->create<type::U32>(), std::nullopt,
-                  {ctx.dst->Builtin(builtin::BuiltinValue::kSampleMask)},
+        // No existing sample mask builtin was found, so create a new output value using the fixed
+        // sample mask.
+        auto* builtin = ctx.dst->Builtin(builtin::BuiltinValue::kSampleMask);
+        builtin_attrs.Add(builtin, builtin::BuiltinValue::kSampleMask);
+        AddOutput("fixed_sample_mask", ctx.dst->create<type::U32>(), std::nullopt, {builtin},
                   ctx.dst->Expr(u32(cfg.fixed_sample_mask)));
     }
 
     /// Add a point size builtin to the wrapper function output.
     void AddVertexPointSize() {
         // Create a new output value and assign it a literal 1.0 value.
-        AddOutput("vertex_point_size", ctx.dst->create<type::F32>(), std::nullopt,
-                  {ctx.dst->Builtin(builtin::BuiltinValue::kPointSize)}, ctx.dst->Expr(1_f));
+        auto* builtin = ctx.dst->Builtin(builtin::BuiltinValue::kPointSize);
+        builtin_attrs.Add(builtin, builtin::BuiltinValue::kPointSize);
+        AddOutput("vertex_point_size", ctx.dst->create<type::F32>(), std::nullopt, {builtin},
+                  ctx.dst->Expr(1_f));
     }
 
     /// Create an expression for gl_Position.[component]
@@ -442,11 +462,40 @@ struct CanonicalizeEntryPointIO::State {
         return ctx.dst->MemberAccessor(ctx.dst->Expr(pos), c);
     }
 
+    /// Comparison function used to reorder struct members such that all members with
+    /// location attributes appear first (ordered by location slot), followed by
+    /// those with builtin attributes.
+    /// @param a a struct member
+    /// @param b another struct member
+    /// @returns true if a comes before b
+    bool StructMemberComparator(const MemberInfo& a, const MemberInfo& b) {
+        auto* a_loc = ast::GetAttribute<ast::LocationAttribute>(a.member->attributes);
+        auto* b_loc = ast::GetAttribute<ast::LocationAttribute>(b.member->attributes);
+        auto* a_blt = ast::GetAttribute<ast::BuiltinAttribute>(a.member->attributes);
+        auto* b_blt = ast::GetAttribute<ast::BuiltinAttribute>(b.member->attributes);
+        if (a_loc) {
+            if (!b_loc) {
+                // `a` has location attribute and `b` does not: `a` goes first.
+                return true;
+            }
+            // Both have location attributes: smallest goes first.
+            return a.location < b.location;
+        } else {
+            if (b_loc) {
+                // `b` has location attribute and `a` does not: `b` goes first.
+                return false;
+            }
+            // Both are builtins: order matters for FXC.
+            auto builtin_a = BuiltinOf(a_blt);
+            auto builtin_b = BuiltinOf(b_blt);
+            return BuiltinOrder(builtin_a) < BuiltinOrder(builtin_b);
+        }
+    }
     /// Create the wrapper function's struct parameter and type objects.
     void CreateInputStruct() {
         // Sort the struct members to satisfy HLSL interfacing matching rules.
         std::sort(wrapper_struct_param_members.begin(), wrapper_struct_param_members.end(),
-                  StructMemberComparator);
+                  [&](auto& a, auto& b) { return StructMemberComparator(a, b); });
 
         utils::Vector<const ast::StructMember*, 8> members;
         for (auto& mem : wrapper_struct_param_members) {
@@ -483,16 +532,17 @@ struct CanonicalizeEntryPointIO::State {
             }
             member_names.insert(ctx.dst->Symbols().NameFor(name));
 
-            wrapper_struct_output_members.Push(
-                {ctx.dst->Member(name, outval.type, std::move(outval.attributes)),
-                 outval.location});
+            wrapper_struct_output_members.Push({
+                ctx.dst->Member(name, outval.type, std::move(outval.attributes)),
+                outval.location,
+            });
             assignments.Push(
                 ctx.dst->Assign(ctx.dst->MemberAccessor(wrapper_result, name), outval.value));
         }
 
         // Sort the struct members to satisfy HLSL interfacing matching rules.
         std::sort(wrapper_struct_output_members.begin(), wrapper_struct_output_members.end(),
-                  StructMemberComparator);
+                  [&](auto& a, auto& b) { return StructMemberComparator(a, b); });
 
         utils::Vector<const ast::StructMember*, 8> members;
         for (auto& mem : wrapper_struct_output_members) {
@@ -519,14 +569,14 @@ struct CanonicalizeEntryPointIO::State {
     void CreateGlobalOutputVariables() {
         for (auto& outval : wrapper_output_values) {
             // Disable validation for use of the `output` address space.
-            utils::Vector<const ast::Attribute*, 8> attributes = std::move(outval.attributes);
+            auto attributes = std::move(outval.attributes);
             attributes.Push(ctx.dst->Disable(ast::DisabledValidation::kIgnoreAddressSpace));
 
             // Create the global variable and assign it the output value.
             auto name = ctx.dst->Symbols().New(outval.name);
             ast::Type type = outval.type;
             const ast::Expression* lhs = ctx.dst->Expr(name);
-            if (HasSampleMask(attributes)) {
+            if (BuiltinOf(attributes) == builtin::BuiltinValue::kSampleMask) {
                 // Vulkan requires the type of a SampleMask builtin to be an array.
                 // Declare it as array<u32, 1> and then store to the first element.
                 type = ctx.dst->ty.array(type, 1_u);
diff --git a/src/tint/transform/canonicalize_entry_point_io_test.cc b/src/tint/transform/canonicalize_entry_point_io_test.cc
index db6385efc6..08b84307cd 100644
--- a/src/tint/transform/canonicalize_entry_point_io_test.cc
+++ b/src/tint/transform/canonicalize_entry_point_io_test.cc
@@ -3163,7 +3163,7 @@ fn vert_main() -> @builtin(position) vec4<f32> {
     auto* expect = R"(
 @builtin(position) @internal(disable_validation__ignore_address_space) var<__out> value : vec4<f32>;
 
-@builtin(point_size) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size : f32;
+@builtin(__point_size) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size : f32;
 
 fn vert_main_inner() -> vec4<f32> {
   return vec4<f32>();
@@ -3197,7 +3197,7 @@ fn vert_main() -> @builtin(position) vec4<f32> {
 struct tint_symbol {
   @builtin(position)
   value : vec4<f32>,
-  @builtin(point_size)
+  @builtin(__point_size)
   vertex_point_size : f32,
 }
 
@@ -3238,7 +3238,7 @@ fn vert_main() -> VertOut {
     auto* expect = R"(
 @builtin(position) @internal(disable_validation__ignore_address_space) var<__out> pos_1 : vec4<f32>;
 
-@builtin(point_size) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size : f32;
+@builtin(__point_size) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size : f32;
 
 struct VertOut {
   pos : vec4<f32>,
@@ -3279,7 +3279,7 @@ struct VertOut {
     auto* expect = R"(
 @builtin(position) @internal(disable_validation__ignore_address_space) var<__out> pos_1 : vec4<f32>;
 
-@builtin(point_size) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size : f32;
+@builtin(__point_size) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size : f32;
 
 fn vert_main_inner() -> VertOut {
   return VertOut();
@@ -3325,7 +3325,7 @@ struct VertOut {
 struct tint_symbol {
   @builtin(position)
   pos : vec4<f32>,
-  @builtin(point_size)
+  @builtin(__point_size)
   vertex_point_size : f32,
 }
 
@@ -3367,7 +3367,7 @@ struct VertOut {
 struct tint_symbol {
   @builtin(position)
   pos : vec4<f32>,
-  @builtin(point_size)
+  @builtin(__point_size)
   vertex_point_size : f32,
 }
 
@@ -3432,7 +3432,7 @@ fn vert_main(collide : VertIn1, collide_1 : VertIn2) -> VertOut {
 
 @builtin(position) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size_1_1 : vec4<f32>;
 
-@builtin(point_size) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size_4 : f32;
+@builtin(__point_size) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size_4 : f32;
 
 var<private> vertex_point_size : f32;
 
@@ -3510,7 +3510,7 @@ struct VertOut {
 
 @builtin(position) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size_1_1 : vec4<f32>;
 
-@builtin(point_size) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size_4 : f32;
+@builtin(__point_size) @internal(disable_validation__ignore_address_space) var<__out> vertex_point_size_4 : f32;
 
 fn vert_main_inner(collide : VertIn1, collide_1 : VertIn2) -> VertOut {
   let x = (collide.collide + collide_1.collide);
@@ -3601,7 +3601,7 @@ struct tint_symbol_2 {
   vertex_point_size : vec4<f32>,
   @builtin(position)
   vertex_point_size_1 : vec4<f32>,
-  @builtin(point_size)
+  @builtin(__point_size)
   vertex_point_size_2 : f32,
 }
 
@@ -3664,7 +3664,7 @@ struct tint_symbol_2 {
   vertex_point_size : vec4<f32>,
   @builtin(position)
   vertex_point_size_1 : vec4<f32>,
-  @builtin(point_size)
+  @builtin(__point_size)
   vertex_point_size_2 : f32,
 }
 
@@ -3753,7 +3753,7 @@ struct tint_symbol_2 {
   vertex_point_size : vec4<f32>,
   @builtin(position)
   vertex_point_size_1 : vec4<f32>,
-  @builtin(point_size)
+  @builtin(__point_size)
   vertex_point_size_2 : f32,
 }
 
@@ -3816,7 +3816,7 @@ struct tint_symbol_2 {
   vertex_point_size : vec4<f32>,
   @builtin(position)
   vertex_point_size_1 : vec4<f32>,
-  @builtin(point_size)
+  @builtin(__point_size)
   vertex_point_size_2 : f32,
 }
 
diff --git a/src/tint/transform/clamp_frag_depth.cc b/src/tint/transform/clamp_frag_depth.cc
index 951dc3046e..77d897d009 100644
--- a/src/tint/transform/clamp_frag_depth.cc
+++ b/src/tint/transform/clamp_frag_depth.cc
@@ -33,178 +33,196 @@ TINT_INSTANTIATE_TYPEINFO(tint::transform::ClampFragDepth);
 
 namespace tint::transform {
 
-namespace {
+/// PIMPL state for the transform
+struct ClampFragDepth::State {
+    /// The source program
+    const Program* const src;
+    /// The target program builder
+    ProgramBuilder b{};
+    /// The clone context
+    CloneContext ctx = {&b, src, /* auto_clone_symbols */ true};
+    /// The sem::Info of the program
+    const sem::Info& sem = src->Sem();
+    /// The symbols of the program
+    const SymbolTable& sym = src->Symbols();
 
-bool ContainsFragDepth(utils::VectorRef<const ast::Attribute*> attributes) {
-    for (auto* attribute : attributes) {
-        if (auto* builtin_attribute = attribute->As<ast::BuiltinAttribute>()) {
-            if (builtin_attribute->builtin == builtin::BuiltinValue::kFragDepth) {
+    /// Runs the transform
+    /// @returns the new program or SkipTransform if the transform is not required
+    Transform::ApplyResult Run() {
+        // Abort on any use of push constants in the module.
+        for (auto* global : src->AST().GlobalVariables()) {
+            if (auto* var = global->As<ast::Var>()) {
+                auto* v = src->Sem().Get(var);
+                if (TINT_UNLIKELY(v->AddressSpace() == builtin::AddressSpace::kPushConstant)) {
+                    TINT_ICE(Transform, b.Diagnostics())
+                        << "ClampFragDepth doesn't know how to handle module that already use push "
+                           "constants";
+                    return Program(std::move(b));
+                }
+            }
+        }
+
+        if (!ShouldRun()) {
+            return SkipTransform;
+        }
+
+        // At least one entry-point needs clamping. Add the following to the module:
+        //
+        //   enable chromium_experimental_push_constant;
+        //
+        //   struct FragDepthClampArgs {
+        //       min : f32,
+        //       max : f32,
+        //   }
+        //   var<push_constant> frag_depth_clamp_args : FragDepthClampArgs;
+        //
+        //   fn clamp_frag_depth(v : f32) -> f32 {
+        //       return clamp(v, frag_depth_clamp_args.min, frag_depth_clamp_args.max);
+        //   }
+        b.Enable(builtin::Extension::kChromiumExperimentalPushConstant);
+
+        b.Structure(b.Symbols().New("FragDepthClampArgs"),
+                    utils::Vector{b.Member("min", b.ty.f32()), b.Member("max", b.ty.f32())});
+
+        auto args_sym = b.Symbols().New("frag_depth_clamp_args");
+        b.GlobalVar(args_sym, b.ty("FragDepthClampArgs"), builtin::AddressSpace::kPushConstant);
+
+        auto base_fn_sym = b.Symbols().New("clamp_frag_depth");
+        b.Func(base_fn_sym, utils::Vector{b.Param("v", b.ty.f32())}, b.ty.f32(),
+               utils::Vector{b.Return(b.Call("clamp", "v", b.MemberAccessor(args_sym, "min"),
+                                             b.MemberAccessor(args_sym, "max")))});
+
+        // If true, the currently cloned function returns frag depth directly as a scalar
+        bool returns_frag_depth_as_value = false;
+
+        // If valid, the currently cloned function returns frag depth in a struct
+        // The symbol is the name of the helper function to apply the depth clamping.
+        Symbol returns_frag_depth_as_struct_helper;
+
+        // Map of io struct to helper function to return the structure with the depth clamping
+        // applied.
+        utils::Hashmap<const ast::Struct*, Symbol, 4u> io_structs_clamp_helpers;
+
+        // Register a callback that will be called for each visted AST function.
+        // This call wraps the cloning of the function's statements, and will assign to
+        // `returns_frag_depth_as_value` or `returns_frag_depth_as_struct_helper` if the function's
+        // return value requires depth clamping.
+        ctx.ReplaceAll([&](const ast::Function* fn) {
+            if (fn->PipelineStage() != ast::PipelineStage::kFragment) {
+                return ctx.CloneWithoutTransform(fn);
+            }
+
+            if (ReturnsFragDepthAsValue(fn)) {
+                TINT_SCOPED_ASSIGNMENT(returns_frag_depth_as_value, true);
+                return ctx.CloneWithoutTransform(fn);
+            }
+
+            if (ReturnsFragDepthInStruct(fn)) {
+                // At most once per I/O struct, add the conversion function:
+                //
+                //   fn clamp_frag_depth_S(s : S) -> S {
+                //       return S(s.first, s.second, clamp_frag_depth(s.frag_depth), s.last);
+                //   }
+                auto* struct_ty = sem.Get(fn)->ReturnType()->As<sem::Struct>()->Declaration();
+                auto helper = io_structs_clamp_helpers.GetOrCreate(struct_ty, [&] {
+                    auto return_ty = fn->return_type;
+                    auto fn_sym =
+                        b.Symbols().New("clamp_frag_depth_" + sym.NameFor(struct_ty->name->symbol));
+
+                    utils::Vector<const ast::Expression*, 8u> initializer_args;
+                    for (auto* member : struct_ty->members) {
+                        const ast::Expression* arg =
+                            b.MemberAccessor("s", ctx.Clone(member->name->symbol));
+                        if (ContainsFragDepth(member->attributes)) {
+                            arg = b.Call(base_fn_sym, arg);
+                        }
+                        initializer_args.Push(arg);
+                    }
+                    utils::Vector params{b.Param("s", ctx.Clone(return_ty))};
+                    utils::Vector body{
+                        b.Return(b.Call(ctx.Clone(return_ty), std::move(initializer_args))),
+                    };
+                    b.Func(fn_sym, params, ctx.Clone(return_ty), body);
+                    return fn_sym;
+                });
+
+                TINT_SCOPED_ASSIGNMENT(returns_frag_depth_as_struct_helper, helper);
+                return ctx.CloneWithoutTransform(fn);
+            }
+
+            return ctx.CloneWithoutTransform(fn);
+        });
+
+        // Replace the return statements `return expr` with `return clamp_frag_depth(expr)`.
+        ctx.ReplaceAll([&](const ast::ReturnStatement* stmt) -> const ast::ReturnStatement* {
+            if (returns_frag_depth_as_value) {
+                return b.Return(stmt->source, b.Call(base_fn_sym, ctx.Clone(stmt->value)));
+            }
+            if (returns_frag_depth_as_struct_helper.IsValid()) {
+                return b.Return(stmt->source, b.Call(returns_frag_depth_as_struct_helper,
+                                                     ctx.Clone(stmt->value)));
+            }
+            return nullptr;
+        });
+
+        ctx.Clone();
+        return Program(std::move(b));
+    }
+
+  private:
+    /// @returns true if the transform should run
+    bool ShouldRun() {
+        for (auto* fn : src->AST().Functions()) {
+            if (fn->PipelineStage() == ast::PipelineStage::kFragment &&
+                (ReturnsFragDepthAsValue(fn) || ReturnsFragDepthInStruct(fn))) {
                 return true;
             }
         }
+
+        return false;
     }
-
-    return false;
-}
-
-bool ReturnsFragDepthAsValue(const ast::Function* fn) {
-    return ContainsFragDepth(fn->return_type_attributes);
-}
-
-bool ReturnsFragDepthInStruct(const sem::Info& sem, const ast::Function* fn) {
-    if (auto* struct_ty = sem.Get(fn)->ReturnType()->As<sem::Struct>()) {
-        for (auto* member : struct_ty->Members()) {
-            if (ContainsFragDepth(member->Declaration()->attributes)) {
-                return true;
+    /// @param attrs the attributes to examine
+    /// @returns true if @p attrs contains a `@builtin(frag_depth)` attribute
+    bool ContainsFragDepth(utils::VectorRef<const ast::Attribute*> attrs) {
+        for (auto* attribute : attrs) {
+            if (auto* builtin_attr = attribute->As<ast::BuiltinAttribute>()) {
+                auto builtin = sem.Get(builtin_attr)->Value();
+                if (builtin == builtin::BuiltinValue::kFragDepth) {
+                    return true;
+                }
             }
         }
+
+        return false;
     }
 
-    return false;
-}
+    /// @param fn the function to examine
+    /// @returns true if @p fn has a return type with a `@builtin(frag_depth)` attribute
+    bool ReturnsFragDepthAsValue(const ast::Function* fn) {
+        return ContainsFragDepth(fn->return_type_attributes);
+    }
 
-bool ShouldRun(const Program* program) {
-    auto& sem = program->Sem();
-
-    for (auto* fn : program->AST().Functions()) {
-        if (fn->PipelineStage() == ast::PipelineStage::kFragment &&
-            (ReturnsFragDepthAsValue(fn) || ReturnsFragDepthInStruct(sem, fn))) {
-            return true;
+    /// @param fn the function to examine
+    /// @returns true if @p fn has a return structure with a `@builtin(frag_depth)` attribute on one
+    /// of the members
+    bool ReturnsFragDepthInStruct(const ast::Function* fn) {
+        if (auto* struct_ty = sem.Get(fn)->ReturnType()->As<sem::Struct>()) {
+            for (auto* member : struct_ty->Members()) {
+                if (ContainsFragDepth(member->Declaration()->attributes)) {
+                    return true;
+                }
+            }
         }
+
+        return false;
     }
-
-    return false;
-}
-
-}  // anonymous namespace
+};
 
 ClampFragDepth::ClampFragDepth() = default;
 ClampFragDepth::~ClampFragDepth() = default;
 
 Transform::ApplyResult ClampFragDepth::Apply(const Program* src, const DataMap&, DataMap&) const {
-    ProgramBuilder b;
-    CloneContext ctx{&b, src, /* auto_clone_symbols */ true};
-
-    // Abort on any use of push constants in the module.
-    for (auto* global : src->AST().GlobalVariables()) {
-        if (auto* var = global->As<ast::Var>()) {
-            auto* v = src->Sem().Get(var);
-            if (TINT_UNLIKELY(v->AddressSpace() == builtin::AddressSpace::kPushConstant)) {
-                TINT_ICE(Transform, b.Diagnostics())
-                    << "ClampFragDepth doesn't know how to handle module that already use push "
-                       "constants";
-                return Program(std::move(b));
-            }
-        }
-    }
-
-    if (!ShouldRun(src)) {
-        return SkipTransform;
-    }
-
-    auto& sem = src->Sem();
-    auto& sym = src->Symbols();
-
-    // At least one entry-point needs clamping. Add the following to the module:
-    //
-    //   enable chromium_experimental_push_constant;
-    //
-    //   struct FragDepthClampArgs {
-    //       min : f32,
-    //       max : f32,
-    //   }
-    //   var<push_constant> frag_depth_clamp_args : FragDepthClampArgs;
-    //
-    //   fn clamp_frag_depth(v : f32) -> f32 {
-    //       return clamp(v, frag_depth_clamp_args.min, frag_depth_clamp_args.max);
-    //   }
-    b.Enable(builtin::Extension::kChromiumExperimentalPushConstant);
-
-    b.Structure(b.Symbols().New("FragDepthClampArgs"),
-                utils::Vector{b.Member("min", b.ty.f32()), b.Member("max", b.ty.f32())});
-
-    auto args_sym = b.Symbols().New("frag_depth_clamp_args");
-    b.GlobalVar(args_sym, b.ty("FragDepthClampArgs"), builtin::AddressSpace::kPushConstant);
-
-    auto base_fn_sym = b.Symbols().New("clamp_frag_depth");
-    b.Func(base_fn_sym, utils::Vector{b.Param("v", b.ty.f32())}, b.ty.f32(),
-           utils::Vector{b.Return(b.Call("clamp", "v", b.MemberAccessor(args_sym, "min"),
-                                         b.MemberAccessor(args_sym, "max")))});
-
-    // If true, the currently cloned function returns frag depth directly as a scalar
-    bool returns_frag_depth_as_value = false;
-
-    // If valid, the currently cloned function returns frag depth in a struct
-    // The symbol is the name of the helper function to apply the depth clamping.
-    Symbol returns_frag_depth_as_struct_helper;
-
-    // Map of io struct to helper function to return the structure with the depth clamping applied.
-    utils::Hashmap<const ast::Struct*, Symbol, 4u> io_structs_clamp_helpers;
-
-    // Register a callback that will be called for each visted AST function.
-    // This call wraps the cloning of the function's statements, and will assign to
-    // `returns_frag_depth_as_value` or `returns_frag_depth_as_struct_helper` if the function's
-    // return value requires depth clamping.
-    ctx.ReplaceAll([&](const ast::Function* fn) {
-        if (fn->PipelineStage() != ast::PipelineStage::kFragment) {
-            return ctx.CloneWithoutTransform(fn);
-        }
-
-        if (ReturnsFragDepthAsValue(fn)) {
-            TINT_SCOPED_ASSIGNMENT(returns_frag_depth_as_value, true);
-            return ctx.CloneWithoutTransform(fn);
-        }
-
-        if (ReturnsFragDepthInStruct(sem, fn)) {
-            // At most once per I/O struct, add the conversion function:
-            //
-            //   fn clamp_frag_depth_S(s : S) -> S {
-            //       return S(s.first, s.second, clamp_frag_depth(s.frag_depth), s.last);
-            //   }
-            auto* struct_ty = sem.Get(fn)->ReturnType()->As<sem::Struct>()->Declaration();
-            auto helper = io_structs_clamp_helpers.GetOrCreate(struct_ty, [&] {
-                auto return_ty = fn->return_type;
-                auto fn_sym =
-                    b.Symbols().New("clamp_frag_depth_" + sym.NameFor(struct_ty->name->symbol));
-
-                utils::Vector<const ast::Expression*, 8u> initializer_args;
-                for (auto* member : struct_ty->members) {
-                    const ast::Expression* arg =
-                        b.MemberAccessor("s", ctx.Clone(member->name->symbol));
-                    if (ContainsFragDepth(member->attributes)) {
-                        arg = b.Call(base_fn_sym, arg);
-                    }
-                    initializer_args.Push(arg);
-                }
-                utils::Vector params{b.Param("s", ctx.Clone(return_ty))};
-                utils::Vector body{
-                    b.Return(b.Call(ctx.Clone(return_ty), std::move(initializer_args))),
-                };
-                b.Func(fn_sym, params, ctx.Clone(return_ty), body);
-                return fn_sym;
-            });
-
-            TINT_SCOPED_ASSIGNMENT(returns_frag_depth_as_struct_helper, helper);
-            return ctx.CloneWithoutTransform(fn);
-        }
-
-        return ctx.CloneWithoutTransform(fn);
-    });
-
-    // Replace the return statements `return expr` with `return clamp_frag_depth(expr)`.
-    ctx.ReplaceAll([&](const ast::ReturnStatement* stmt) -> const ast::ReturnStatement* {
-        if (returns_frag_depth_as_value) {
-            return b.Return(stmt->source, b.Call(base_fn_sym, ctx.Clone(stmt->value)));
-        }
-        if (returns_frag_depth_as_struct_helper.IsValid()) {
-            return b.Return(stmt->source,
-                            b.Call(returns_frag_depth_as_struct_helper, ctx.Clone(stmt->value)));
-        }
-        return nullptr;
-    });
-
-    ctx.Clone();
-    return Program(std::move(b));
+    return State{src}.Run();
 }
 
 }  // namespace tint::transform
diff --git a/src/tint/transform/clamp_frag_depth.h b/src/tint/transform/clamp_frag_depth.h
index 1e9d0d6146..3e3f168ff7 100644
--- a/src/tint/transform/clamp_frag_depth.h
+++ b/src/tint/transform/clamp_frag_depth.h
@@ -65,6 +65,9 @@ class ClampFragDepth final : public Castable<ClampFragDepth, Transform> {
     ApplyResult Apply(const Program* program,
                       const DataMap& inputs,
                       DataMap& outputs) const override;
+
+  private:
+    struct State;
 };
 
 }  // namespace tint::transform
diff --git a/src/tint/transform/first_index_offset.cc b/src/tint/transform/first_index_offset.cc
index cac1299204..59588e24f7 100644
--- a/src/tint/transform/first_index_offset.cc
+++ b/src/tint/transform/first_index_offset.cc
@@ -18,6 +18,7 @@
 #include <unordered_map>
 #include <utility>
 
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/sem/function.h"
 #include "src/tint/sem/member_accessor_expression.h"
@@ -88,7 +89,7 @@ Transform::ApplyResult FirstIndexOffset::Apply(const Program* src,
         if (auto* var = node->As<ast::Variable>()) {
             for (auto* attr : var->attributes) {
                 if (auto* builtin_attr = attr->As<ast::BuiltinAttribute>()) {
-                    builtin::BuiltinValue builtin = builtin_attr->builtin;
+                    builtin::BuiltinValue builtin = src->Sem().Get(builtin_attr)->Value();
                     if (builtin == builtin::BuiltinValue::kVertexIndex) {
                         auto* sem_var = ctx.src->Sem().Get(var);
                         builtin_vars.emplace(sem_var, kFirstVertexName);
@@ -105,7 +106,7 @@ Transform::ApplyResult FirstIndexOffset::Apply(const Program* src,
         if (auto* member = node->As<ast::StructMember>()) {
             for (auto* attr : member->attributes) {
                 if (auto* builtin_attr = attr->As<ast::BuiltinAttribute>()) {
-                    builtin::BuiltinValue builtin = builtin_attr->builtin;
+                    builtin::BuiltinValue builtin = src->Sem().Get(builtin_attr)->Value();
                     if (builtin == builtin::BuiltinValue::kVertexIndex) {
                         auto* sem_mem = ctx.src->Sem().Get(member);
                         builtin_members.emplace(sem_mem, kFirstVertexName);
diff --git a/src/tint/transform/num_workgroups_from_uniform.cc b/src/tint/transform/num_workgroups_from_uniform.cc
index a62cf429fc..e4bb05ebea 100644
--- a/src/tint/transform/num_workgroups_from_uniform.cc
+++ b/src/tint/transform/num_workgroups_from_uniform.cc
@@ -19,6 +19,7 @@
 #include <unordered_set>
 #include <utility>
 
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/sem/function.h"
 #include "src/tint/transform/canonicalize_entry_point_io.h"
@@ -33,7 +34,7 @@ namespace {
 bool ShouldRun(const Program* program) {
     for (auto* node : program->ASTNodes().Objects()) {
         if (auto* attr = node->As<ast::BuiltinAttribute>()) {
-            if (attr->builtin == builtin::BuiltinValue::kNumWorkgroups) {
+            if (program->Sem().Get(attr)->Value() == builtin::BuiltinValue::kNumWorkgroups) {
                 return true;
             }
         }
@@ -100,7 +101,8 @@ Transform::ApplyResult NumWorkgroupsFromUniform::Apply(const Program* src,
             for (auto* member : str->Members()) {
                 auto* builtin =
                     ast::GetAttribute<ast::BuiltinAttribute>(member->Declaration()->attributes);
-                if (!builtin || builtin->builtin != builtin::BuiltinValue::kNumWorkgroups) {
+                if (!builtin ||
+                    src->Sem().Get(builtin)->Value() != builtin::BuiltinValue::kNumWorkgroups) {
                     continue;
                 }
 
diff --git a/src/tint/transform/vertex_pulling.cc b/src/tint/transform/vertex_pulling.cc
index 9faddb7f15..ecc75763b2 100644
--- a/src/tint/transform/vertex_pulling.cc
+++ b/src/tint/transform/vertex_pulling.cc
@@ -20,6 +20,7 @@
 #include "src/tint/ast/assignment_statement.h"
 #include "src/tint/ast/bitcast_expression.h"
 #include "src/tint/ast/variable_decl_statement.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/sem/variable.h"
 #include "src/tint/utils/compiler_macros.h"
@@ -773,17 +774,18 @@ struct VertexPulling::State {
             }
             location_info[sem->Location().value()] = info;
         } else {
-            auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(param->attributes);
-            if (TINT_UNLIKELY(!builtin)) {
+            auto* builtin_attr = ast::GetAttribute<ast::BuiltinAttribute>(param->attributes);
+            if (TINT_UNLIKELY(!builtin_attr)) {
                 TINT_ICE(Transform, b.Diagnostics()) << "Invalid entry point parameter";
                 return;
             }
+            auto builtin = src->Sem().Get(builtin_attr)->Value();
             // Check for existing vertex_index and instance_index builtins.
-            if (builtin->builtin == builtin::BuiltinValue::kVertexIndex) {
+            if (builtin == builtin::BuiltinValue::kVertexIndex) {
                 vertex_index_expr = [this, param]() {
                     return b.Expr(ctx.Clone(param->name->symbol));
                 };
-            } else if (builtin->builtin == builtin::BuiltinValue::kInstanceIndex) {
+            } else if (builtin == builtin::BuiltinValue::kInstanceIndex) {
                 instance_index_expr = [this, param]() {
                     return b.Expr(ctx.Clone(param->name->symbol));
                 };
@@ -826,15 +828,16 @@ struct VertexPulling::State {
                 location_info[sem->Location().value()] = info;
                 has_locations = true;
             } else {
-                auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(member->attributes);
-                if (TINT_UNLIKELY(!builtin)) {
+                auto* builtin_attr = ast::GetAttribute<ast::BuiltinAttribute>(member->attributes);
+                if (TINT_UNLIKELY(!builtin_attr)) {
                     TINT_ICE(Transform, b.Diagnostics()) << "Invalid entry point parameter";
                     return;
                 }
+                auto builtin = src->Sem().Get(builtin_attr)->Value();
                 // Check for existing vertex_index and instance_index builtins.
-                if (builtin->builtin == builtin::BuiltinValue::kVertexIndex) {
+                if (builtin == builtin::BuiltinValue::kVertexIndex) {
                     vertex_index_expr = member_expr;
-                } else if (builtin->builtin == builtin::BuiltinValue::kInstanceIndex) {
+                } else if (builtin == builtin::BuiltinValue::kInstanceIndex) {
                     instance_index_expr = member_expr;
                 }
                 members_to_clone.Push(member);
diff --git a/src/tint/transform/zero_init_workgroup_memory.cc b/src/tint/transform/zero_init_workgroup_memory.cc
index 2071abcb46..7dafc0644c 100644
--- a/src/tint/transform/zero_init_workgroup_memory.cc
+++ b/src/tint/transform/zero_init_workgroup_memory.cc
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "src/tint/ast/workgroup_attribute.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/sem/function.h"
 #include "src/tint/sem/variable.h"
@@ -159,8 +160,9 @@ struct ZeroInitWorkgroupMemory::State {
         // parameter
         std::function<const ast::Expression*()> local_index;
         for (auto* param : fn->params) {
-            if (auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(param->attributes)) {
-                if (builtin->builtin == builtin::BuiltinValue::kLocalInvocationIndex) {
+            if (auto* builtin_attr = ast::GetAttribute<ast::BuiltinAttribute>(param->attributes)) {
+                auto builtin = sem.Get(builtin_attr)->Value();
+                if (builtin == builtin::BuiltinValue::kLocalInvocationIndex) {
                     local_index = [=] { return b.Expr(ctx.Clone(param->name->symbol)); };
                     break;
                 }
@@ -168,9 +170,10 @@ struct ZeroInitWorkgroupMemory::State {
 
             if (auto* str = sem.Get(param)->Type()->As<sem::Struct>()) {
                 for (auto* member : str->Members()) {
-                    if (auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(
+                    if (auto* builtin_attr = ast::GetAttribute<ast::BuiltinAttribute>(
                             member->Declaration()->attributes)) {
-                        if (builtin->builtin == builtin::BuiltinValue::kLocalInvocationIndex) {
+                        auto builtin = sem.Get(builtin_attr)->Value();
+                        if (builtin == builtin::BuiltinValue::kLocalInvocationIndex) {
                             local_index = [=] {
                                 auto* param_expr = b.Expr(ctx.Clone(param->name->symbol));
                                 auto* member_name = ctx.Clone(member->Declaration()->name);
@@ -184,10 +187,9 @@ struct ZeroInitWorkgroupMemory::State {
         }
         if (!local_index) {
             // No existing local index parameter. Append one to the entry point.
-            auto* param = b.Param(b.Symbols().New("local_invocation_index"), b.ty.u32(),
-                                  utils::Vector{
-                                      b.Builtin(builtin::BuiltinValue::kLocalInvocationIndex),
-                                  });
+            auto param_name = b.Symbols().New("local_invocation_index");
+            auto* local_invocation_index = b.Builtin(builtin::BuiltinValue::kLocalInvocationIndex);
+            auto* param = b.Param(param_name, b.ty.u32(), utils::Vector{local_invocation_index});
             ctx.InsertBack(fn->params, param);
             local_index = [=] { return b.Expr(param->name->symbol); };
         }
diff --git a/src/tint/utils/enum_set.h b/src/tint/utils/enum_set.h
index 19d1a82223..9b75ba072e 100644
--- a/src/tint/utils/enum_set.h
+++ b/src/tint/utils/enum_set.h
@@ -192,14 +192,14 @@ struct EnumSet {
     };
 
     /// @returns an read-only iterator to the beginning of the set
-    Iterator begin() {
+    Iterator begin() const {
         auto it = Iterator{set, -1};
         ++it;  // Move to first set bit
         return it;
     }
 
     /// @returns an iterator to the beginning of the set
-    Iterator end() { return Iterator{set, Iterator::kEnd}; }
+    Iterator end() const { return Iterator{set, Iterator::kEnd}; }
 
   private:
     static constexpr uint64_t Bit(Enum value) {
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index d89aaaf94f..773bcaf181 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -2155,9 +2155,10 @@ bool GeneratorImpl::EmitWorkgroupVariable(const sem::Variable* var) {
 bool GeneratorImpl::EmitIOVariable(const sem::GlobalVariable* var) {
     auto* decl = var->Declaration();
 
-    if (auto* b = ast::GetAttribute<ast::BuiltinAttribute>(decl->attributes)) {
+    if (auto* attr = ast::GetAttribute<ast::BuiltinAttribute>(decl->attributes)) {
+        auto builtin = program_->Sem().Get(attr)->Value();
         // Use of gl_SampleID requires the GL_OES_sample_variables extension
-        if (RequiresOESSampleVariables(b->builtin)) {
+        if (RequiresOESSampleVariables(builtin)) {
             requires_oes_sample_variables_ = true;
         }
         // Do not emit builtin (gl_) variables.
diff --git a/src/tint/writer/glsl/generator_impl.h b/src/tint/writer/glsl/generator_impl.h
index 629566d8ae..260852e9e6 100644
--- a/src/tint/writer/glsl/generator_impl.h
+++ b/src/tint/writer/glsl/generator_impl.h
@@ -32,6 +32,7 @@
 #include "src/tint/ast/return_statement.h"
 #include "src/tint/ast/switch_statement.h"
 #include "src/tint/ast/unary_op_expression.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/scope_stack.h"
 #include "src/tint/transform/decompose_memory_access.h"
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index 2659a529e8..4c7c9ee2b1 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -4210,8 +4210,9 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
                         } else {
                             TINT_ICE(Writer, diagnostics_) << "invalid use of location attribute";
                         }
-                    } else if (auto* builtin = attr->As<ast::BuiltinAttribute>()) {
-                        auto name = builtin_to_attribute(builtin->builtin);
+                    } else if (auto* builtin_attr = attr->As<ast::BuiltinAttribute>()) {
+                        auto builtin = program_->Sem().Get(builtin_attr)->Value();
+                        auto name = builtin_to_attribute(builtin);
                         if (name.empty()) {
                             diagnostics_.add_error(diag::System::Writer, "unsupported builtin");
                             return false;
diff --git a/src/tint/writer/hlsl/generator_impl.h b/src/tint/writer/hlsl/generator_impl.h
index 1f272efdce..abf1fcb9ab 100644
--- a/src/tint/writer/hlsl/generator_impl.h
+++ b/src/tint/writer/hlsl/generator_impl.h
@@ -31,6 +31,7 @@
 #include "src/tint/ast/return_statement.h"
 #include "src/tint/ast/switch_statement.h"
 #include "src/tint/ast/unary_op_expression.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/scope_stack.h"
 #include "src/tint/sem/binding_point.h"
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 0f6b390261..8723222e6b 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -2077,14 +2077,15 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) {
                     auto& attrs = param->attributes;
                     bool builtin_found = false;
                     for (auto* attr : attrs) {
-                        auto* builtin = attr->As<ast::BuiltinAttribute>();
-                        if (!builtin) {
+                        auto* builtin_attr = attr->As<ast::BuiltinAttribute>();
+                        if (!builtin_attr) {
                             continue;
                         }
+                        auto builtin = program_->Sem().Get(builtin_attr)->Value();
 
                         builtin_found = true;
 
-                        auto name = builtin_to_attribute(builtin->builtin);
+                        auto name = builtin_to_attribute(builtin);
                         if (name.empty()) {
                             diagnostics_.add_error(diag::System::Writer, "unknown builtin");
                             return false;
@@ -2854,8 +2855,9 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
             for (auto* attr : decl->attributes) {
                 bool ok = Switch(
                     attr,
-                    [&](const ast::BuiltinAttribute* builtin) {
-                        auto name = builtin_to_attribute(builtin->builtin);
+                    [&](const ast::BuiltinAttribute* builtin_attr) {
+                        auto builtin = program_->Sem().Get(builtin_attr)->Value();
+                        auto name = builtin_to_attribute(builtin);
                         if (name.empty()) {
                             diagnostics_.add_error(diag::System::Writer, "unknown builtin");
                             return false;
diff --git a/src/tint/writer/msl/generator_impl.h b/src/tint/writer/msl/generator_impl.h
index 3e84546e4b..57c129b195 100644
--- a/src/tint/writer/msl/generator_impl.h
+++ b/src/tint/writer/msl/generator_impl.h
@@ -36,6 +36,7 @@
 #include "src/tint/ast/return_statement.h"
 #include "src/tint/ast/switch_statement.h"
 #include "src/tint/ast/unary_op_expression.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/program.h"
 #include "src/tint/scope_stack.h"
 #include "src/tint/sem/struct.h"
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index 0a3c5ba4d8..eeaa1e114e 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -548,8 +548,9 @@ bool Builder::GenerateExecutionModes(const ast::Function* func, uint32_t id) {
              Operand(wgsize[0].value()), Operand(wgsize[1].value()), Operand(wgsize[2].value())});
     }
 
-    for (auto builtin : func_sem->TransitivelyReferencedBuiltinVariables()) {
-        if (builtin.second->builtin == builtin::BuiltinValue::kFragDepth) {
+    for (auto it : func_sem->TransitivelyReferencedBuiltinVariables()) {
+        auto builtin = builder_.Sem().Get(it.second)->Value();
+        if (builtin == builtin::BuiltinValue::kFragDepth) {
             push_execution_mode(spv::Op::OpExecutionMode,
                                 {Operand(id), U32Operand(SpvExecutionModeDepthReplacing)});
         }
@@ -837,10 +838,11 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* v) {
     for (auto* attr : v->attributes) {
         bool ok = Switch(
             attr,
-            [&](const ast::BuiltinAttribute* builtin) {
+            [&](const ast::BuiltinAttribute* builtin_attr) {
+                auto builtin = builder_.Sem().Get(builtin_attr)->Value();
                 push_annot(spv::Op::OpDecorate,
                            {Operand(var_id), U32Operand(SpvDecorationBuiltIn),
-                            U32Operand(ConvertBuiltin(builtin->builtin, sem->AddressSpace()))});
+                            U32Operand(ConvertBuiltin(builtin, sem->AddressSpace()))});
                 return true;
             },
             [&](const ast::LocationAttribute*) {
diff --git a/src/tint/writer/spirv/builder.h b/src/tint/writer/spirv/builder.h
index d4aa11bf54..adfe65908f 100644
--- a/src/tint/writer/spirv/builder.h
+++ b/src/tint/writer/spirv/builder.h
@@ -33,6 +33,7 @@
 #include "src/tint/ast/switch_statement.h"
 #include "src/tint/ast/unary_op_expression.h"
 #include "src/tint/ast/variable_decl_statement.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/program_builder.h"
 #include "src/tint/scope_stack.h"
 #include "src/tint/sem/builtin.h"
diff --git a/src/tint/writer/wgsl/generator_impl.cc b/src/tint/writer/wgsl/generator_impl.cc
index 0902d2cd8c..1fa03ffde5 100644
--- a/src/tint/writer/wgsl/generator_impl.cc
+++ b/src/tint/writer/wgsl/generator_impl.cc
@@ -564,7 +564,11 @@ bool GeneratorImpl::EmitAttributes(std::ostream& out,
                 return true;
             },
             [&](const ast::BuiltinAttribute* builtin) {
-                out << "builtin(" << builtin->builtin << ")";
+                out << "builtin(";
+                if (!EmitExpression(out, builtin->builtin)) {
+                    return false;
+                }
+                out << ")";
                 return true;
             },
             [&](const ast::DiagnosticAttribute* diagnostic) {
diff --git a/src/tint/writer/wgsl/generator_impl_function_test.cc b/src/tint/writer/wgsl/generator_impl_function_test.cc
index 53131cdf40..04103ffb4c 100644
--- a/src/tint/writer/wgsl/generator_impl_function_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_function_test.cc
@@ -15,6 +15,7 @@
 #include "src/tint/ast/stage_attribute.h"
 #include "src/tint/ast/variable_decl_statement.h"
 #include "src/tint/ast/workgroup_attribute.h"
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/writer/wgsl/test_helper.h"
 
 using namespace tint::number_suffixes;  // NOLINT
diff --git a/src/tint/writer/wgsl/generator_impl_type_test.cc b/src/tint/writer/wgsl/generator_impl_type_test.cc
index baa6d5b413..422b7112e0 100644
--- a/src/tint/writer/wgsl/generator_impl_type_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_type_test.cc
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "src/tint/builtin/builtin_value.h"
 #include "src/tint/type/depth_texture.h"
 #include "src/tint/type/multisampled_texture.h"
 #include "src/tint/type/sampled_texture.h"
diff --git a/test/tint/bug/tint/1088.spvasm.expected.dxc.hlsl b/test/tint/bug/tint/1088.spvasm.expected.dxc.hlsl
index dce65eb620..1588b26de3 100644
--- a/test/tint/bug/tint/1088.spvasm.expected.dxc.hlsl
+++ b/test/tint/bug/tint/1088.spvasm.expected.dxc.hlsl
@@ -1,4 +1,4 @@
-static float3 position = float3(0.0f, 0.0f, 0.0f);
+static float3 position_1 = float3(0.0f, 0.0f, 0.0f);
 cbuffer cbuffer_x_14 : register(b2, space2) {
   uint4 x_14[17];
 };
@@ -18,13 +18,13 @@ float4x4 tint_symbol_4(uint4 buffer[17], uint offset) {
 void main_1() {
   float4 q = float4(0.0f, 0.0f, 0.0f, 0.0f);
   float3 p = float3(0.0f, 0.0f, 0.0f);
-  const float3 x_13 = position;
+  const float3 x_13 = position_1;
   q = float4(x_13.x, x_13.y, x_13.z, 1.0f);
   const float4 x_21 = q;
   p = float3(x_21.x, x_21.y, x_21.z);
   const float x_27 = p.x;
   const float x_41 = asfloat(x_14[13].x);
-  const float x_45 = position.y;
+  const float x_45 = position_1.y;
   const float x_49 = asfloat(x_14[4].x);
   p.x = (x_27 + sin(((x_41 * x_45) + x_49)));
   const float x_55 = p.y;
@@ -45,7 +45,7 @@ struct main_out {
   float2 vUV_1;
 };
 struct tint_symbol_1 {
-  float3 position_param : TEXCOORD0;
+  float3 position_1_param : TEXCOORD0;
   float3 normal_param : TEXCOORD1;
   float2 uv_param : TEXCOORD2;
 };
@@ -54,8 +54,8 @@ struct tint_symbol_2 {
   float4 gl_Position : SV_Position;
 };
 
-main_out main_inner(float3 position_param, float2 uv_param, float3 normal_param) {
-  position = position_param;
+main_out main_inner(float3 position_1_param, float2 uv_param, float3 normal_param) {
+  position_1 = position_1_param;
   uv = uv_param;
   normal = normal_param;
   main_1();
@@ -64,7 +64,7 @@ main_out main_inner(float3 position_param, float2 uv_param, float3 normal_param)
 }
 
 tint_symbol_2 main(tint_symbol_1 tint_symbol) {
-  const main_out inner_result = main_inner(tint_symbol.position_param, tint_symbol.uv_param, tint_symbol.normal_param);
+  const main_out inner_result = main_inner(tint_symbol.position_1_param, tint_symbol.uv_param, tint_symbol.normal_param);
   tint_symbol_2 wrapper_result = (tint_symbol_2)0;
   wrapper_result.gl_Position = inner_result.gl_Position;
   wrapper_result.vUV_1 = inner_result.vUV_1;
diff --git a/test/tint/bug/tint/1088.spvasm.expected.fxc.hlsl b/test/tint/bug/tint/1088.spvasm.expected.fxc.hlsl
index dce65eb620..1588b26de3 100644
--- a/test/tint/bug/tint/1088.spvasm.expected.fxc.hlsl
+++ b/test/tint/bug/tint/1088.spvasm.expected.fxc.hlsl
@@ -1,4 +1,4 @@
-static float3 position = float3(0.0f, 0.0f, 0.0f);
+static float3 position_1 = float3(0.0f, 0.0f, 0.0f);
 cbuffer cbuffer_x_14 : register(b2, space2) {
   uint4 x_14[17];
 };
@@ -18,13 +18,13 @@ float4x4 tint_symbol_4(uint4 buffer[17], uint offset) {
 void main_1() {
   float4 q = float4(0.0f, 0.0f, 0.0f, 0.0f);
   float3 p = float3(0.0f, 0.0f, 0.0f);
-  const float3 x_13 = position;
+  const float3 x_13 = position_1;
   q = float4(x_13.x, x_13.y, x_13.z, 1.0f);
   const float4 x_21 = q;
   p = float3(x_21.x, x_21.y, x_21.z);
   const float x_27 = p.x;
   const float x_41 = asfloat(x_14[13].x);
-  const float x_45 = position.y;
+  const float x_45 = position_1.y;
   const float x_49 = asfloat(x_14[4].x);
   p.x = (x_27 + sin(((x_41 * x_45) + x_49)));
   const float x_55 = p.y;
@@ -45,7 +45,7 @@ struct main_out {
   float2 vUV_1;
 };
 struct tint_symbol_1 {
-  float3 position_param : TEXCOORD0;
+  float3 position_1_param : TEXCOORD0;
   float3 normal_param : TEXCOORD1;
   float2 uv_param : TEXCOORD2;
 };
@@ -54,8 +54,8 @@ struct tint_symbol_2 {
   float4 gl_Position : SV_Position;
 };
 
-main_out main_inner(float3 position_param, float2 uv_param, float3 normal_param) {
-  position = position_param;
+main_out main_inner(float3 position_1_param, float2 uv_param, float3 normal_param) {
+  position_1 = position_1_param;
   uv = uv_param;
   normal = normal_param;
   main_1();
@@ -64,7 +64,7 @@ main_out main_inner(float3 position_param, float2 uv_param, float3 normal_param)
 }
 
 tint_symbol_2 main(tint_symbol_1 tint_symbol) {
-  const main_out inner_result = main_inner(tint_symbol.position_param, tint_symbol.uv_param, tint_symbol.normal_param);
+  const main_out inner_result = main_inner(tint_symbol.position_1_param, tint_symbol.uv_param, tint_symbol.normal_param);
   tint_symbol_2 wrapper_result = (tint_symbol_2)0;
   wrapper_result.gl_Position = inner_result.gl_Position;
   wrapper_result.vUV_1 = inner_result.vUV_1;
diff --git a/test/tint/bug/tint/1088.spvasm.expected.glsl b/test/tint/bug/tint/1088.spvasm.expected.glsl
index 88d88ecd59..678a63ee9e 100644
--- a/test/tint/bug/tint/1088.spvasm.expected.glsl
+++ b/test/tint/bug/tint/1088.spvasm.expected.glsl
@@ -1,6 +1,6 @@
 #version 310 es
 
-layout(location = 0) in vec3 position_param_1;
+layout(location = 0) in vec3 position_1_param_1;
 layout(location = 2) in vec2 uv_param_1;
 layout(location = 1) in vec3 normal_param_1;
 layout(location = 0) out vec2 vUV_1_1;
@@ -21,7 +21,7 @@ struct LeftOver {
   strided_arr test[4];
 };
 
-vec3 position = vec3(0.0f, 0.0f, 0.0f);
+vec3 position_1 = vec3(0.0f, 0.0f, 0.0f);
 layout(binding = 2, std140) uniform x_14_block_ubo {
   LeftOver inner;
 } x_14;
@@ -33,13 +33,13 @@ vec4 tint_symbol = vec4(0.0f, 0.0f, 0.0f, 0.0f);
 void main_1() {
   vec4 q = vec4(0.0f, 0.0f, 0.0f, 0.0f);
   vec3 p = vec3(0.0f, 0.0f, 0.0f);
-  vec3 x_13 = position;
+  vec3 x_13 = position_1;
   q = vec4(x_13.x, x_13.y, x_13.z, 1.0f);
   vec4 x_21 = q;
   p = vec3(x_21.x, x_21.y, x_21.z);
   float x_27 = p.x;
   float x_41 = x_14.inner.test[0].el;
-  float x_45 = position.y;
+  float x_45 = position_1.y;
   float x_49 = x_14.inner.time;
   p.x = (x_27 + sin(((x_41 * x_45) + x_49)));
   float x_55 = p.y;
@@ -60,8 +60,8 @@ struct main_out {
   vec2 vUV_1;
 };
 
-main_out tint_symbol_1(vec3 position_param, vec2 uv_param, vec3 normal_param) {
-  position = position_param;
+main_out tint_symbol_1(vec3 position_1_param, vec2 uv_param, vec3 normal_param) {
+  position_1 = position_1_param;
   uv = uv_param;
   normal = normal_param;
   main_1();
@@ -71,7 +71,7 @@ main_out tint_symbol_1(vec3 position_param, vec2 uv_param, vec3 normal_param) {
 
 void main() {
   gl_PointSize = 1.0;
-  main_out inner_result = tint_symbol_1(position_param_1, uv_param_1, normal_param_1);
+  main_out inner_result = tint_symbol_1(position_1_param_1, uv_param_1, normal_param_1);
   gl_Position = inner_result.tint_symbol;
   vUV_1_1 = inner_result.vUV_1;
   gl_Position.y = -(gl_Position.y);
diff --git a/test/tint/bug/tint/1088.spvasm.expected.msl b/test/tint/bug/tint/1088.spvasm.expected.msl
index 5970249e5e..2fc3f5f0a9 100644
--- a/test/tint/bug/tint/1088.spvasm.expected.msl
+++ b/test/tint/bug/tint/1088.spvasm.expected.msl
@@ -58,7 +58,7 @@ struct main_out {
 };
 
 struct tint_symbol_2 {
-  float3 position_param [[attribute(0)]];
+  float3 position_1_param [[attribute(0)]];
   float3 normal_param [[attribute(1)]];
   float2 uv_param [[attribute(2)]];
 };
@@ -68,9 +68,9 @@ struct tint_symbol_3 {
   float4 gl_Position [[position]];
 };
 
-main_out tint_symbol_inner(float3 position_param, float2 uv_param, float3 normal_param, thread float3* const tint_symbol_10, thread float2* const tint_symbol_11, const constant LeftOver* const tint_symbol_13, thread float4* const tint_symbol_14, thread float2* const tint_symbol_15) {
+main_out tint_symbol_inner(float3 position_1_param, float2 uv_param, float3 normal_param, thread float3* const tint_symbol_10, thread float2* const tint_symbol_11, const constant LeftOver* const tint_symbol_13, thread float4* const tint_symbol_14, thread float2* const tint_symbol_15) {
   thread float3 tint_symbol_12 = 0.0f;
-  *(tint_symbol_10) = position_param;
+  *(tint_symbol_10) = position_1_param;
   *(tint_symbol_11) = uv_param;
   tint_symbol_12 = normal_param;
   main_1(tint_symbol_10, tint_symbol_13, tint_symbol_14, tint_symbol_11, tint_symbol_15);
@@ -83,7 +83,7 @@ vertex tint_symbol_3 tint_symbol(const constant LeftOver* tint_symbol_18 [[buffe
   thread float2 tint_symbol_17 = 0.0f;
   thread float4 tint_symbol_19 = 0.0f;
   thread float2 tint_symbol_20 = 0.0f;
-  main_out const inner_result = tint_symbol_inner(tint_symbol_1.position_param, tint_symbol_1.uv_param, tint_symbol_1.normal_param, &(tint_symbol_16), &(tint_symbol_17), tint_symbol_18, &(tint_symbol_19), &(tint_symbol_20));
+  main_out const inner_result = tint_symbol_inner(tint_symbol_1.position_1_param, tint_symbol_1.uv_param, tint_symbol_1.normal_param, &(tint_symbol_16), &(tint_symbol_17), tint_symbol_18, &(tint_symbol_19), &(tint_symbol_20));
   tint_symbol_3 wrapper_result = {};
   wrapper_result.gl_Position = inner_result.gl_Position;
   wrapper_result.vUV_1 = inner_result.vUV_1;
diff --git a/test/tint/bug/tint/1088.spvasm.expected.spvasm b/test/tint/bug/tint/1088.spvasm.expected.spvasm
index 3221d0a799..10fa5cb52c 100644
--- a/test/tint/bug/tint/1088.spvasm.expected.spvasm
+++ b/test/tint/bug/tint/1088.spvasm.expected.spvasm
@@ -6,14 +6,14 @@
                OpCapability Shader
          %76 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
-               OpEntryPoint Vertex %main "main" %position_param_1 %uv_param_1 %normal_param_1 %gl_Position_1 %vUV_1_1 %vertex_point_size
-               OpName %position_param_1 "position_param_1"
+               OpEntryPoint Vertex %main "main" %position_1_param_1 %uv_param_1 %normal_param_1 %gl_Position_1 %vUV_1_1 %vertex_point_size
+               OpName %position_1_param_1 "position_1_param_1"
                OpName %uv_param_1 "uv_param_1"
                OpName %normal_param_1 "normal_param_1"
                OpName %gl_Position_1 "gl_Position_1"
                OpName %vUV_1_1 "vUV_1_1"
                OpName %vertex_point_size "vertex_point_size"
-               OpName %position "position"
+               OpName %position_1 "position_1"
                OpName %x_14_block "x_14_block"
                OpMemberName %x_14_block 0 "inner"
                OpName %LeftOver "LeftOver"
@@ -35,11 +35,11 @@
                OpMemberName %main_out 0 "gl_Position"
                OpMemberName %main_out 1 "vUV_1"
                OpName %main_inner "main_inner"
-               OpName %position_param "position_param"
+               OpName %position_1_param "position_1_param"
                OpName %uv_param "uv_param"
                OpName %normal_param "normal_param"
                OpName %main "main"
-               OpDecorate %position_param_1 Location 0
+               OpDecorate %position_1_param_1 Location 0
                OpDecorate %uv_param_1 Location 2
                OpDecorate %normal_param_1 Location 1
                OpDecorate %gl_Position_1 BuiltIn Position
@@ -66,7 +66,7 @@
       %float = OpTypeFloat 32
     %v3float = OpTypeVector %float 3
 %_ptr_Input_v3float = OpTypePointer Input %v3float
-%position_param_1 = OpVariable %_ptr_Input_v3float Input
+%position_1_param_1 = OpVariable %_ptr_Input_v3float Input
     %v2float = OpTypeVector %float 2
 %_ptr_Input_v2float = OpTypePointer Input %v2float
  %uv_param_1 = OpVariable %_ptr_Input_v2float Input
@@ -83,7 +83,7 @@
 %vertex_point_size = OpVariable %_ptr_Output_float Output %18
 %_ptr_Private_v3float = OpTypePointer Private %v3float
          %21 = OpConstantNull %v3float
-   %position = OpVariable %_ptr_Private_v3float Private %21
+ %position_1 = OpVariable %_ptr_Private_v3float Private %21
 %mat4v4float = OpTypeMatrix %v4float 4
        %uint = OpTypeInt 32 0
      %uint_2 = OpConstant %uint 2
@@ -123,7 +123,7 @@
          %42 = OpLabel
           %q = OpVariable %_ptr_Function_v4float Function %12
           %p = OpVariable %_ptr_Function_v3float Function %21
-         %47 = OpLoad %v3float %position
+         %47 = OpLoad %v3float %position_1
          %48 = OpCompositeExtract %float %47 0
          %49 = OpCompositeExtract %float %47 1
          %50 = OpCompositeExtract %float %47 2
@@ -139,7 +139,7 @@
          %61 = OpLoad %float %60
          %66 = OpAccessChain %_ptr_Uniform_float %x_14 %uint_0 %uint_3 %64 %uint_0
          %67 = OpLoad %float %66
-         %70 = OpAccessChain %_ptr_Private_float %position %uint_1
+         %70 = OpAccessChain %_ptr_Private_float %position_1 %uint_1
          %71 = OpLoad %float %70
          %72 = OpAccessChain %_ptr_Uniform_float %x_14 %uint_0 %uint_1
          %73 = OpLoad %float %72
@@ -177,11 +177,11 @@
                OpReturn
                OpFunctionEnd
  %main_inner = OpFunction %main_out None %104
-%position_param = OpFunctionParameter %v3float
+%position_1_param = OpFunctionParameter %v3float
    %uv_param = OpFunctionParameter %v2float
 %normal_param = OpFunctionParameter %v3float
         %110 = OpLabel
-               OpStore %position %position_param
+               OpStore %position_1 %position_1_param
                OpStore %uv %uv_param
                OpStore %normal %normal_param
         %111 = OpFunctionCall %void %main_1
@@ -192,7 +192,7 @@
                OpFunctionEnd
        %main = OpFunction %void None %39
         %116 = OpLabel
-        %118 = OpLoad %v3float %position_param_1
+        %118 = OpLoad %v3float %position_1_param_1
         %119 = OpLoad %v2float %uv_param_1
         %120 = OpLoad %v3float %normal_param_1
         %117 = OpFunctionCall %main_out %main_inner %118 %119 %120
diff --git a/test/tint/bug/tint/1088.spvasm.expected.wgsl b/test/tint/bug/tint/1088.spvasm.expected.wgsl
index 8d4079947d..8ef95624e0 100644
--- a/test/tint/bug/tint/1088.spvasm.expected.wgsl
+++ b/test/tint/bug/tint/1088.spvasm.expected.wgsl
@@ -18,7 +18,7 @@ struct LeftOver {
   test : Arr_1,
 }
 
-var<private> position : vec3<f32>;
+var<private> position_1 : vec3<f32>;
 
 @group(2) @binding(2) var<uniform> x_14 : LeftOver;
 
@@ -33,13 +33,13 @@ var<private> gl_Position : vec4<f32>;
 fn main_1() {
   var q : vec4<f32>;
   var p : vec3<f32>;
-  let x_13 : vec3<f32> = position;
+  let x_13 : vec3<f32> = position_1;
   q = vec4<f32>(x_13.x, x_13.y, x_13.z, 1.0f);
   let x_21 : vec4<f32> = q;
   p = vec3<f32>(x_21.x, x_21.y, x_21.z);
   let x_27 : f32 = p.x;
   let x_41 : f32 = x_14.test[0i].el;
-  let x_45 : f32 = position.y;
+  let x_45 : f32 = position_1.y;
   let x_49 : f32 = x_14.time;
   p.x = (x_27 + sin(((x_41 * x_45) + x_49)));
   let x_55 : f32 = p.y;
@@ -63,8 +63,8 @@ struct main_out {
 }
 
 @vertex
-fn main(@location(0) position_param : vec3<f32>, @location(2) uv_param : vec2<f32>, @location(1) normal_param : vec3<f32>) -> main_out {
-  position = position_param;
+fn main(@location(0) position_1_param : vec3<f32>, @location(2) uv_param : vec2<f32>, @location(1) normal_param : vec3<f32>) -> main_out {
+  position_1 = position_1_param;
   uv = uv_param;
   normal = normal_param;
   main_1();
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.dxc.hlsl
index f3fc89828a..0c3cc70cf8 100644
--- a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.dxc.hlsl
@@ -9,9 +9,9 @@ uint tint_mod(uint lhs, uint rhs) {
   return (lhs % ((rhs == 0u) ? 1u : rhs));
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     const uint x_25 = idx;
     if (!((x_25 < 6u))) {
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.fxc.hlsl
index f3fc89828a..0c3cc70cf8 100644
--- a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.fxc.hlsl
@@ -9,9 +9,9 @@ uint tint_mod(uint lhs, uint rhs) {
   return (lhs % ((rhs == 0u) ? 1u : rhs));
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     const uint x_25 = idx;
     if (!((x_25 < 6u))) {
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.glsl b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.glsl
index 0912c08785..800af68e1e 100644
--- a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.glsl
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.glsl
@@ -10,9 +10,9 @@ uint tint_mod(uint lhs, uint rhs) {
   return (lhs % ((rhs == 0u) ? 1u : rhs));
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     uint x_25 = idx;
     if (!((x_25 < 6u))) {
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.msl b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.msl
index f1220afa5b..d17c9b4d04 100644
--- a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.msl
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.msl
@@ -22,9 +22,9 @@ uint tint_mod(uint lhs, uint rhs) {
   return (lhs % select(rhs, 1u, (rhs == 0u)));
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup tint_array<tint_array<tint_array<atomic_uint, 1>, 2>, 3>* const tint_symbol_3) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup tint_array<tint_array<tint_array<atomic_uint, 1>, 2>, 3>* const tint_symbol_3) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     uint const x_25 = idx;
     if (!((x_25 < 6u))) {
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.spvasm
index fb00bc8230..71bb07eba0 100644
--- a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.spvasm
@@ -17,7 +17,7 @@
                OpName %lhs_0 "lhs"
                OpName %rhs_0 "rhs"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %idx "idx"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
@@ -75,11 +75,11 @@
                OpReturnValue %30
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %31
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %35 = OpLabel
         %idx = OpVariable %_ptr_Function_uint Function %6
                OpStore %idx %6
-               OpStore %idx %local_invocation_index
+               OpStore %idx %local_invocation_index_2
                OpBranch %38
          %38 = OpLabel
                OpLoopMerge %39 %40 None
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.wgsl
index 4c957ceae4..cab082308b 100644
--- a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.wgsl
@@ -8,9 +8,9 @@ var<private> local_invocation_index_1 : u32;
 
 var<workgroup> wg : array<array<array<atomic<u32>, 1u>, 2u>, 3u>;
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   var idx : u32 = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   loop {
     let x_25 : u32 = idx;
     if (!((x_25 < 6u))) {
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomicStore/array/array.spvasm.expected.dxc.hlsl
index ea978dfd65..0016dc8716 100644
--- a/test/tint/builtins/atomicStore/array/array.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.dxc.hlsl
@@ -1,9 +1,9 @@
 static uint local_invocation_index_1 = 0u;
 groupshared uint wg[4];
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     const uint x_21 = idx;
     if (!((x_21 < 4u))) {
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomicStore/array/array.spvasm.expected.fxc.hlsl
index ea978dfd65..0016dc8716 100644
--- a/test/tint/builtins/atomicStore/array/array.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.fxc.hlsl
@@ -1,9 +1,9 @@
 static uint local_invocation_index_1 = 0u;
 groupshared uint wg[4];
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     const uint x_21 = idx;
     if (!((x_21 < 4u))) {
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.glsl b/test/tint/builtins/atomicStore/array/array.spvasm.expected.glsl
index bf89caeeaa..3567dd6274 100644
--- a/test/tint/builtins/atomicStore/array/array.spvasm.expected.glsl
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.glsl
@@ -2,9 +2,9 @@
 
 uint local_invocation_index_1 = 0u;
 shared uint wg[4];
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     uint x_21 = idx;
     if (!((x_21 < 4u))) {
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.msl b/test/tint/builtins/atomicStore/array/array.spvasm.expected.msl
index 8ef9d3975b..a4eb243dd8 100644
--- a/test/tint/builtins/atomicStore/array/array.spvasm.expected.msl
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.msl
@@ -14,9 +14,9 @@ struct tint_array {
     T elements[N];
 };
 
-void compute_main_inner(uint local_invocation_index, threadgroup tint_array<atomic_uint, 4>* const tint_symbol) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup tint_array<atomic_uint, 4>* const tint_symbol) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     uint const x_21 = idx;
     if (!((x_21 < 4u))) {
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/array/array.spvasm.expected.spvasm
index e15c3dbc1a..be9caabae1 100644
--- a/test/tint/builtins/atomicStore/array/array.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.spvasm
@@ -11,7 +11,7 @@
                OpName %local_invocation_index_1 "local_invocation_index_1"
                OpName %wg "wg"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %idx "idx"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
@@ -43,11 +43,11 @@
       %int_1 = OpConstant %int 1
          %45 = OpTypeFunction %void
 %compute_main_inner = OpFunction %void None %11
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %15 = OpLabel
         %idx = OpVariable %_ptr_Function_uint Function %6
                OpStore %idx %6
-               OpStore %idx %local_invocation_index
+               OpStore %idx %local_invocation_index_2
                OpBranch %18
          %18 = OpLabel
                OpLoopMerge %19 %20 None
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/array/array.spvasm.expected.wgsl
index f1ce6c7772..6b51227140 100644
--- a/test/tint/builtins/atomicStore/array/array.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.wgsl
@@ -4,9 +4,9 @@ var<private> local_invocation_index_1 : u32;
 
 var<workgroup> wg : array<atomic<u32>, 4u>;
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   var idx : u32 = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   loop {
     let x_21 : u32 = idx;
     if (!((x_21 < 4u))) {
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.dxc.hlsl
index f3fc89828a..0c3cc70cf8 100644
--- a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.dxc.hlsl
@@ -9,9 +9,9 @@ uint tint_mod(uint lhs, uint rhs) {
   return (lhs % ((rhs == 0u) ? 1u : rhs));
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     const uint x_25 = idx;
     if (!((x_25 < 6u))) {
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.fxc.hlsl
index f3fc89828a..0c3cc70cf8 100644
--- a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.fxc.hlsl
@@ -9,9 +9,9 @@ uint tint_mod(uint lhs, uint rhs) {
   return (lhs % ((rhs == 0u) ? 1u : rhs));
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     const uint x_25 = idx;
     if (!((x_25 < 6u))) {
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.glsl b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.glsl
index 0912c08785..800af68e1e 100644
--- a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.glsl
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.glsl
@@ -10,9 +10,9 @@ uint tint_mod(uint lhs, uint rhs) {
   return (lhs % ((rhs == 0u) ? 1u : rhs));
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     uint x_25 = idx;
     if (!((x_25 < 6u))) {
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.msl b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.msl
index f1220afa5b..d17c9b4d04 100644
--- a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.msl
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.msl
@@ -22,9 +22,9 @@ uint tint_mod(uint lhs, uint rhs) {
   return (lhs % select(rhs, 1u, (rhs == 0u)));
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup tint_array<tint_array<tint_array<atomic_uint, 1>, 2>, 3>* const tint_symbol_3) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup tint_array<tint_array<tint_array<atomic_uint, 1>, 2>, 3>* const tint_symbol_3) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     uint const x_25 = idx;
     if (!((x_25 < 6u))) {
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.spvasm
index fb00bc8230..71bb07eba0 100644
--- a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.spvasm
@@ -17,7 +17,7 @@
                OpName %lhs_0 "lhs"
                OpName %rhs_0 "rhs"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %idx "idx"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
@@ -75,11 +75,11 @@
                OpReturnValue %30
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %31
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %35 = OpLabel
         %idx = OpVariable %_ptr_Function_uint Function %6
                OpStore %idx %6
-               OpStore %idx %local_invocation_index
+               OpStore %idx %local_invocation_index_2
                OpBranch %38
          %38 = OpLabel
                OpLoopMerge %39 %40 None
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.wgsl
index 4c957ceae4..cab082308b 100644
--- a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.wgsl
@@ -8,9 +8,9 @@ var<private> local_invocation_index_1 : u32;
 
 var<workgroup> wg : array<array<array<atomic<u32>, 1u>, 2u>, 3u>;
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   var idx : u32 = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   loop {
     let x_25 : u32 = idx;
     if (!((x_25 < 6u))) {
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.dxc.hlsl
index 29a168e8ea..965a8af3f0 100644
--- a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.dxc.hlsl
@@ -7,9 +7,9 @@ struct S_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S_atomic wg[10];
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     const uint x_23 = idx;
     if (!((x_23 < 10u))) {
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.fxc.hlsl
index 29a168e8ea..965a8af3f0 100644
--- a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.fxc.hlsl
@@ -7,9 +7,9 @@ struct S_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S_atomic wg[10];
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     const uint x_23 = idx;
     if (!((x_23 < 10u))) {
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.glsl
index 6252580643..a1fc729d44 100644
--- a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.glsl
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.glsl
@@ -14,9 +14,9 @@ struct S {
 
 uint local_invocation_index_1 = 0u;
 shared S_atomic wg[10];
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     uint x_23 = idx;
     if (!((x_23 < 10u))) {
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.msl
index f4fd526a21..f9bac41d9f 100644
--- a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.msl
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.msl
@@ -26,9 +26,9 @@ struct S {
   uint y;
 };
 
-void compute_main_inner(uint local_invocation_index, threadgroup tint_array<S_atomic, 10>* const tint_symbol) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup tint_array<S_atomic, 10>* const tint_symbol) {
   uint idx = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     uint const x_23 = idx;
     if (!((x_23 < 10u))) {
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.spvasm
index b25f900d0e..ee16a5c935 100644
--- a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.spvasm
@@ -15,7 +15,7 @@
                OpMemberName %S_atomic 2 "y"
                OpName %wg "wg"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %idx "idx"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
@@ -54,11 +54,11 @@
       %int_4 = OpConstant %int 4
          %51 = OpTypeFunction %void
 %compute_main_inner = OpFunction %void None %13
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %17 = OpLabel
         %idx = OpVariable %_ptr_Function_uint Function %6
                OpStore %idx %6
-               OpStore %idx %local_invocation_index
+               OpStore %idx %local_invocation_index_2
                OpBranch %20
          %20 = OpLabel
                OpLoopMerge %21 %22 None
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.wgsl
index b3a11050b5..81a23a5f90 100644
--- a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.wgsl
@@ -22,9 +22,9 @@ var<private> local_invocation_index_1 : u32;
 
 var<workgroup> wg : array<S_atomic, 10u>;
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   var idx : u32 = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   loop {
     let x_23 : u32 = idx;
     if (!((x_23 < 10u))) {
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.dxc.hlsl
index aa81130719..c56ccea78c 100644
--- a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.dxc.hlsl
@@ -7,7 +7,7 @@ struct S_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S_atomic wg;
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   uint atomic_result = 0u;
   InterlockedExchange(wg.a, 0u, atomic_result);
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.fxc.hlsl
index aa81130719..c56ccea78c 100644
--- a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.fxc.hlsl
@@ -7,7 +7,7 @@ struct S_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S_atomic wg;
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   uint atomic_result = 0u;
   InterlockedExchange(wg.a, 0u, atomic_result);
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.glsl
index 0b676180b9..a183ccfdfa 100644
--- a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.glsl
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.glsl
@@ -14,7 +14,7 @@ struct S {
 
 uint local_invocation_index_1 = 0u;
 shared S_atomic wg;
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   atomicExchange(wg.a, 0u);
   atomicExchange(wg.b, 0u);
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.msl
index 4e1363de46..9ff385d6b9 100644
--- a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.msl
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.msl
@@ -13,7 +13,7 @@ struct S {
   uint b;
 };
 
-void compute_main_inner(uint local_invocation_index, threadgroup S_atomic* const tint_symbol) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup S_atomic* const tint_symbol) {
   (*(tint_symbol)).x = 0;
   atomic_store_explicit(&((*(tint_symbol)).a), 0u, memory_order_relaxed);
   atomic_store_explicit(&((*(tint_symbol)).b), 0u, memory_order_relaxed);
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.spvasm
index 5ee475d00d..de9e2a6d74 100644
--- a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.spvasm
@@ -15,7 +15,7 @@
                OpMemberName %S_atomic 2 "b"
                OpName %wg "wg"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -45,7 +45,7 @@
    %uint_264 = OpConstant %uint 264
          %37 = OpTypeFunction %void
 %compute_main_inner = OpFunction %void None %11
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %15 = OpLabel
          %18 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
                OpStore %18 %19
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.wgsl
index c9a899df0c..3f9e97bf9d 100644
--- a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.wgsl
@@ -20,7 +20,7 @@ var<private> local_invocation_index_1 : u32;
 
 var<workgroup> wg : S_atomic;
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   wg.x = 0i;
   atomicStore(&(wg.a), 0u);
   atomicStore(&(wg.b), 0u);
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.dxc.hlsl
index 2245126b0f..d735498dba 100644
--- a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.dxc.hlsl
@@ -7,7 +7,7 @@ struct S_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S_atomic wg;
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   uint atomic_result = 0u;
   InterlockedExchange(wg.a, 0u, atomic_result);
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.fxc.hlsl
index 2245126b0f..d735498dba 100644
--- a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.fxc.hlsl
@@ -7,7 +7,7 @@ struct S_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S_atomic wg;
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   uint atomic_result = 0u;
   InterlockedExchange(wg.a, 0u, atomic_result);
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.glsl
index 4116efd52a..a3dfff680c 100644
--- a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.glsl
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.glsl
@@ -14,7 +14,7 @@ struct S {
 
 uint local_invocation_index_1 = 0u;
 shared S_atomic wg;
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   atomicExchange(wg.a, 0u);
   wg.y = 0u;
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.msl
index 524820aff7..7e1b7dcb18 100644
--- a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.msl
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.msl
@@ -13,7 +13,7 @@ struct S {
   uint y;
 };
 
-void compute_main_inner(uint local_invocation_index, threadgroup S_atomic* const tint_symbol) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup S_atomic* const tint_symbol) {
   (*(tint_symbol)).x = 0;
   atomic_store_explicit(&((*(tint_symbol)).a), 0u, memory_order_relaxed);
   (*(tint_symbol)).y = 0u;
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.spvasm
index 35d0d2b420..0c6e7b916a 100644
--- a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.spvasm
@@ -15,7 +15,7 @@
                OpMemberName %S_atomic 2 "y"
                OpName %wg "wg"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
    %uint_264 = OpConstant %uint 264
          %33 = OpTypeFunction %void
 %compute_main_inner = OpFunction %void None %11
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %15 = OpLabel
          %18 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
                OpStore %18 %19
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.wgsl
index ff3d543baf..5180091389 100644
--- a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.wgsl
@@ -20,7 +20,7 @@ var<private> local_invocation_index_1 : u32;
 
 var<workgroup> wg : S_atomic;
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   wg.x = 0i;
   atomicStore(&(wg.a), 0u);
   wg.y = 0u;
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.dxc.hlsl
index 8a073d14e4..b564c9c8f5 100644
--- a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.dxc.hlsl
@@ -20,7 +20,7 @@ struct S2_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S2_atomic wg;
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   wg.y = 0;
   wg.z = 0;
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.fxc.hlsl
index 8a073d14e4..b564c9c8f5 100644
--- a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.fxc.hlsl
@@ -20,7 +20,7 @@ struct S2_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S2_atomic wg;
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   wg.y = 0;
   wg.z = 0;
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.glsl
index c0e09d02d2..ea69be374a 100644
--- a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.glsl
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.glsl
@@ -44,7 +44,7 @@ struct S2 {
 
 uint local_invocation_index_1 = 0u;
 shared S2_atomic wg;
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   wg.y = 0;
   wg.z = 0;
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.msl
index 1ed439c62f..0e4963c719 100644
--- a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.msl
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.msl
@@ -43,7 +43,7 @@ struct S2 {
   S1 a;
 };
 
-void compute_main_inner(uint local_invocation_index, threadgroup S2_atomic* const tint_symbol) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup S2_atomic* const tint_symbol) {
   (*(tint_symbol)).x = 0;
   (*(tint_symbol)).y = 0;
   (*(tint_symbol)).z = 0;
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.spvasm
index 9f756f397e..ba5cca6f40 100644
--- a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.spvasm
@@ -26,7 +26,7 @@
                OpMemberName %S1_atomic 3 "z"
                OpName %wg "wg"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -68,7 +68,7 @@
    %uint_264 = OpConstant %uint 264
          %42 = OpTypeFunction %void
 %compute_main_inner = OpFunction %void None %13
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %17 = OpLabel
          %20 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
                OpStore %20 %21
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.wgsl
index e448d74aac..268d74fe41 100644
--- a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.wgsl
@@ -68,7 +68,7 @@ var<private> local_invocation_index_1 : u32;
 
 var<workgroup> wg : S2_atomic;
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   wg.x = 0i;
   wg.y = 0i;
   wg.z = 0i;
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.dxc.hlsl
index c685a44858..69d98abffe 100644
--- a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.dxc.hlsl
@@ -7,11 +7,11 @@ struct S_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S_atomic wg;
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
   wg.x = 0;
   wg.y = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     const uint x_30 = idx;
     if (!((x_30 < 10u))) {
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.fxc.hlsl
index c685a44858..69d98abffe 100644
--- a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.fxc.hlsl
@@ -7,11 +7,11 @@ struct S_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S_atomic wg;
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
   wg.x = 0;
   wg.y = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     const uint x_30 = idx;
     if (!((x_30 < 10u))) {
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.glsl
index b6add351d9..06b3b6ebed 100644
--- a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.glsl
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.glsl
@@ -14,11 +14,11 @@ struct S {
 
 uint local_invocation_index_1 = 0u;
 shared S_atomic wg;
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint idx = 0u;
   wg.x = 0;
   wg.y = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     uint x_30 = idx;
     if (!((x_30 < 10u))) {
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.msl
index 69d565e3d5..fc285333e9 100644
--- a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.msl
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.msl
@@ -26,11 +26,11 @@ struct S {
   uint y;
 };
 
-void compute_main_inner(uint local_invocation_index, threadgroup S_atomic* const tint_symbol) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup S_atomic* const tint_symbol) {
   uint idx = 0u;
   (*(tint_symbol)).x = 0;
   (*(tint_symbol)).y = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   while (true) {
     uint const x_30 = idx;
     if (!((x_30 < 10u))) {
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.spvasm
index d7743741fc..b6bd6d73ab 100644
--- a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.spvasm
@@ -15,7 +15,7 @@
                OpMemberName %S_atomic 2 "y"
                OpName %wg "wg"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %idx "idx"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
@@ -54,7 +54,7 @@
       %int_4 = OpConstant %int 4
          %51 = OpTypeFunction %void
 %compute_main_inner = OpFunction %void None %13
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %17 = OpLabel
         %idx = OpVariable %_ptr_Function_uint Function %6
                OpStore %idx %6
@@ -62,7 +62,7 @@
                OpStore %22 %23
          %26 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_2
                OpStore %26 %6
-               OpStore %idx %local_invocation_index
+               OpStore %idx %local_invocation_index_2
                OpBranch %27
          %27 = OpLabel
                OpLoopMerge %28 %29 None
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.wgsl
index b8953f12b3..d03070cb52 100644
--- a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.wgsl
@@ -22,11 +22,11 @@ var<private> local_invocation_index_1 : u32;
 
 var<workgroup> wg : S_atomic;
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   var idx : u32 = 0u;
   wg.x = 0i;
   wg.y = 0u;
-  idx = local_invocation_index;
+  idx = local_invocation_index_2;
   loop {
     let x_30 : u32 = idx;
     if (!((x_30 < 10u))) {
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.dxc.hlsl
index 2245126b0f..d735498dba 100644
--- a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.dxc.hlsl
@@ -7,7 +7,7 @@ struct S_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S_atomic wg;
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   uint atomic_result = 0u;
   InterlockedExchange(wg.a, 0u, atomic_result);
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.fxc.hlsl
index 2245126b0f..d735498dba 100644
--- a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.fxc.hlsl
@@ -7,7 +7,7 @@ struct S_atomic {
 static uint local_invocation_index_1 = 0u;
 groupshared S_atomic wg;
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   uint atomic_result = 0u;
   InterlockedExchange(wg.a, 0u, atomic_result);
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.glsl
index 4116efd52a..a3dfff680c 100644
--- a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.glsl
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.glsl
@@ -14,7 +14,7 @@ struct S {
 
 uint local_invocation_index_1 = 0u;
 shared S_atomic wg;
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   wg.x = 0;
   atomicExchange(wg.a, 0u);
   wg.y = 0u;
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.msl
index 524820aff7..7e1b7dcb18 100644
--- a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.msl
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.msl
@@ -13,7 +13,7 @@ struct S {
   uint y;
 };
 
-void compute_main_inner(uint local_invocation_index, threadgroup S_atomic* const tint_symbol) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup S_atomic* const tint_symbol) {
   (*(tint_symbol)).x = 0;
   atomic_store_explicit(&((*(tint_symbol)).a), 0u, memory_order_relaxed);
   (*(tint_symbol)).y = 0u;
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.spvasm
index 35d0d2b420..0c6e7b916a 100644
--- a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.spvasm
@@ -15,7 +15,7 @@
                OpMemberName %S_atomic 2 "y"
                OpName %wg "wg"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
    %uint_264 = OpConstant %uint 264
          %33 = OpTypeFunction %void
 %compute_main_inner = OpFunction %void None %11
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %15 = OpLabel
          %18 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
                OpStore %18 %19
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.wgsl
index ff3d543baf..5180091389 100644
--- a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.wgsl
@@ -20,7 +20,7 @@ var<private> local_invocation_index_1 : u32;
 
 var<workgroup> wg : S_atomic;
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   wg.x = 0i;
   atomicStore(&(wg.a), 0u);
   wg.y = 0u;
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.dxc.hlsl
index 89a6a358ba..0c494d211e 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.fxc.hlsl
index 89a6a358ba..0c494d211e 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.glsl
index c95c6a9f49..a9f59ed490 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.msl
index 62639d7b4a..5f8945fc05 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_794055(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.spvasm
index 3dc0a5d301..1f62e68258 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicAdd_794055 "atomicAdd_794055"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.wgsl
index 723a1135af..d59a523473 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicAdd_794055() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.dxc.hlsl
index d1179cc47d..99ac4aaded 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.fxc.hlsl
index d1179cc47d..99ac4aaded 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.glsl
index 5a5b50b48c..e0f09816ce 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.msl
index 04a890a74c..6dab26276f 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_d5db1d(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.spvasm
index 5daee6404f..66a3661a68 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -44,7 +44,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %20
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %23 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.wgsl
index 61d34ccb7b..5a1db0ecf7 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicAdd_d5db1d() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.dxc.hlsl
index c3e91bf29c..bb3fe38434 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicAnd_45a819() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.fxc.hlsl
index c3e91bf29c..bb3fe38434 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicAnd_45a819() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.glsl
index 601ae32d8b..09f9466001 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicAnd_45a819() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicAnd_45a819();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.msl
index ee4b602e3f..af7eadc300 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicAnd_45a819(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAnd_45a819(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.spvasm
index b7e9939338..350c984ca1 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicAnd_45a819 "atomicAnd_45a819"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.wgsl
index 9369271687..7ac8d286ae 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicAnd_45a819() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicAnd_45a819();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.dxc.hlsl
index b215600474..15512d377a 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicAnd_34edd3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.fxc.hlsl
index b215600474..15512d377a 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicAnd_34edd3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.glsl
index 9b6741bc0b..8db98c5dd9 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicAnd_34edd3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicAnd_34edd3();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.msl
index ffc5ace33c..2da6bbdc71 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicAnd_34edd3(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAnd_34edd3(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.spvasm
index 02a5b899e1..43720d2d28 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicAnd_34edd3 "atomicAnd_34edd3"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -44,7 +44,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %20
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %23 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.wgsl
index ee27cf61cc..a077ce7348 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicAnd_34edd3() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicAnd_34edd3();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.dxc.hlsl
index 44cf7405de..fe0811a1f7 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -24,7 +24,7 @@ void atomicCompareExchangeWeak_e88938() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.fxc.hlsl
index 44cf7405de..fe0811a1f7 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -24,7 +24,7 @@ void atomicCompareExchangeWeak_e88938() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl
index a4305e7e74..11092c71de 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl
@@ -26,7 +26,7 @@ void atomicCompareExchangeWeak_e88938() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicCompareExchangeWeak_e88938();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl
index a296185998..25e9db31ea 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl
@@ -27,7 +27,7 @@ void atomicCompareExchangeWeak_e88938(threadgroup atomic_int* const tint_symbol_
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_3) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_3) {
   atomic_store_explicit(tint_symbol_3, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicCompareExchangeWeak_e88938(tint_symbol_3);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm
index f82b2cb51c..e4be06c9df 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm
@@ -19,7 +19,7 @@
                OpMemberName %__atomic_compare_exchange_resulti32 0 "old_value"
                OpMemberName %__atomic_compare_exchange_resulti32 1 "exchanged"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -65,7 +65,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %30
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %33 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %36
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl
index f85055d118..4104721006 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl
@@ -17,7 +17,7 @@ fn atomicCompareExchangeWeak_e88938() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicCompareExchangeWeak_e88938();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.dxc.hlsl
index 1e87d0a101..89f85cc2a2 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -24,7 +24,7 @@ void atomicCompareExchangeWeak_83580d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.fxc.hlsl
index 1e87d0a101..89f85cc2a2 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -24,7 +24,7 @@ void atomicCompareExchangeWeak_83580d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl
index 680871b5ff..59a68d220d 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl
@@ -26,7 +26,7 @@ void atomicCompareExchangeWeak_83580d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicCompareExchangeWeak_83580d();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl
index c980f5d9d9..287ea417ca 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl
@@ -27,7 +27,7 @@ void atomicCompareExchangeWeak_83580d(threadgroup atomic_uint* const tint_symbol
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_3) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_3) {
   atomic_store_explicit(tint_symbol_3, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicCompareExchangeWeak_83580d(tint_symbol_3);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm
index 9c927f23b0..6200f8954b 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm
@@ -19,7 +19,7 @@
                OpMemberName %__atomic_compare_exchange_resultu32 0 "old_value"
                OpMemberName %__atomic_compare_exchange_resultu32 1 "exchanged"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -63,7 +63,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %29
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %32 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl
index 8855c3bee3..df6689483e 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl
@@ -17,7 +17,7 @@ fn atomicCompareExchangeWeak_83580d() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicCompareExchangeWeak_83580d();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.dxc.hlsl
index 92f0f6ebcd..154f6cfa26 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicExchange_e114ba() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.fxc.hlsl
index 92f0f6ebcd..154f6cfa26 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicExchange_e114ba() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.glsl
index e836943c64..35e9a4773d 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicExchange_e114ba() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicExchange_e114ba();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.msl
index 7126a8a502..d0b8f90f37 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicExchange_e114ba(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicExchange_e114ba(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.spvasm
index bb829c958f..e553f3dfb8 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicExchange_e114ba "atomicExchange_e114ba"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.wgsl
index 4e35c0e9bf..b8eb11a96b 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicExchange_e114ba() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicExchange_e114ba();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.dxc.hlsl
index d04f2e8467..b0f013fd62 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicExchange_0a5dca() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.fxc.hlsl
index d04f2e8467..b0f013fd62 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicExchange_0a5dca() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.glsl
index 49abca3860..dbfb5eae9b 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicExchange_0a5dca() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicExchange_0a5dca();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.msl
index 4027c03177..b5629655db 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicExchange_0a5dca(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicExchange_0a5dca(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.spvasm
index 0aca328ff6..2a919c5b50 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicExchange_0a5dca "atomicExchange_0a5dca"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -44,7 +44,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %20
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %23 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.wgsl
index fb71c6d299..e52c9b7312 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicExchange_0a5dca() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicExchange_0a5dca();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.dxc.hlsl
index 3e2674ee55..14e42dd3a5 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicLoad_afcc03() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.fxc.hlsl
index 3e2674ee55..14e42dd3a5 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicLoad_afcc03() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.glsl
index 351d2dcc84..6596bb1867 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicLoad_afcc03() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicLoad_afcc03();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.msl
index 8f6ee408a4..3f9bc5f5ae 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicLoad_afcc03(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicLoad_afcc03(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.spvasm
index 829b8487e3..f4f86f8626 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicLoad_afcc03 "atomicLoad_afcc03"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -45,7 +45,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %21
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %24 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.wgsl
index af0c057346..ba60171363 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicLoad_afcc03() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicLoad_afcc03();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.dxc.hlsl
index 3aa482d1d1..2eb7c6cd6f 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicLoad_361bf1() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.fxc.hlsl
index 3aa482d1d1..2eb7c6cd6f 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicLoad_361bf1() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.glsl
index 2ad60dbb1d..b21c00a447 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicLoad_361bf1() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicLoad_361bf1();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.msl
index d7fcb6e569..c9f5cd3477 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicLoad_361bf1(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicLoad_361bf1(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.spvasm
index 7a075badba..5a8a6333dc 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicLoad_361bf1 "atomicLoad_361bf1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -43,7 +43,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %19
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %22 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.wgsl
index f132c6fa83..d9fd46d242 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicLoad_361bf1() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicLoad_361bf1();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.dxc.hlsl
index a508d4ed12..02888922b4 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicMax_a89cc3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.fxc.hlsl
index a508d4ed12..02888922b4 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicMax_a89cc3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.glsl
index f76a29722d..a33bb7576e 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicMax_a89cc3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicMax_a89cc3();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.msl
index 94213828a6..c309d8bf6b 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicMax_a89cc3(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicMax_a89cc3(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.spvasm
index 0360ae68ae..a9a61aa2d0 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicMax_a89cc3 "atomicMax_a89cc3"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.wgsl
index 0c3e2a8cbe..08ebe32bac 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicMax_a89cc3() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicMax_a89cc3();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.dxc.hlsl
index 3100cbf961..b09ef950ec 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicMax_beccfc() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.fxc.hlsl
index 3100cbf961..b09ef950ec 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicMax_beccfc() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.glsl
index 3af9a65170..c16c57cdc4 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicMax_beccfc() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicMax_beccfc();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.msl
index 200a901d1c..8519e901b1 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicMax_beccfc(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicMax_beccfc(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.spvasm
index 7f01c87162..edbea82e02 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicMax_beccfc "atomicMax_beccfc"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -44,7 +44,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %20
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %23 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.wgsl
index 39ee5df379..759d72d0ea 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicMax_beccfc() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicMax_beccfc();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.dxc.hlsl
index 69c3b10294..8ccadb6210 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicMin_278235() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.fxc.hlsl
index 69c3b10294..8ccadb6210 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicMin_278235() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.glsl
index ff9d11f2cd..ea080f7a1e 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicMin_278235() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicMin_278235();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.msl
index 3c4bd987dc..f82688aaa0 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicMin_278235(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicMin_278235(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.spvasm
index cea2249304..76eaac8d76 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicMin_278235 "atomicMin_278235"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.wgsl
index 5ddda3e92d..525b7f9cf2 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicMin_278235() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicMin_278235();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.dxc.hlsl
index 688677a1ce..ad033d3386 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicMin_69d383() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.fxc.hlsl
index 688677a1ce..ad033d3386 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicMin_69d383() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.glsl
index 9360d134a6..08336ed6d0 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicMin_69d383() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicMin_69d383();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.msl
index 226629f477..d03bb77aef 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicMin_69d383(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicMin_69d383(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.spvasm
index 475d1ce488..044c6345d8 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicMin_69d383 "atomicMin_69d383"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -44,7 +44,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %20
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %23 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.wgsl
index 8f37c6bbcb..6b2873d983 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicMin_69d383() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicMin_69d383();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.dxc.hlsl
index 85146d8d0d..7ad2a81243 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicOr_d09248() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.fxc.hlsl
index 85146d8d0d..7ad2a81243 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicOr_d09248() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.glsl
index db9f5ee5e0..f87bf7e8c9 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicOr_d09248() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicOr_d09248();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.msl
index 74c1a5852e..980a7d6703 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicOr_d09248(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicOr_d09248(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.spvasm
index 9ef589330b..d52afbd8dc 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicOr_d09248 "atomicOr_d09248"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.wgsl
index 5563b2bee9..92c3719a74 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicOr_d09248() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicOr_d09248();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.dxc.hlsl
index 178bc59670..3ba0201a5c 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicOr_5e3d61() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.fxc.hlsl
index 178bc59670..3ba0201a5c 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicOr_5e3d61() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.glsl
index 371b0f9936..13c90bac17 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicOr_5e3d61() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicOr_5e3d61();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.msl
index 2513fa7e93..1111dc3195 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicOr_5e3d61(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicOr_5e3d61(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.spvasm
index ad9af507a7..ad9b3e359d 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicOr_5e3d61 "atomicOr_5e3d61"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -44,7 +44,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %20
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %23 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.wgsl
index 2e9093ea4a..773349a04c 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicOr_5e3d61() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicOr_5e3d61();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.dxc.hlsl
index 8b0fd829ed..57d9ca32c0 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -7,7 +7,7 @@ void atomicStore_8bea94() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.fxc.hlsl
index 8b0fd829ed..57d9ca32c0 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -7,7 +7,7 @@ void atomicStore_8bea94() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.glsl
index 7804c733ed..0f4accda65 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.glsl
@@ -7,7 +7,7 @@ void atomicStore_8bea94() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicStore_8bea94();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.msl
index 78e73c54b5..fbccdc49f2 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.msl
@@ -6,7 +6,7 @@ void atomicStore_8bea94(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicStore_8bea94(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.spvasm
index 319461d46c..b694a5d63a 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.spvasm
@@ -12,7 +12,7 @@
                OpName %arg_0 "arg_0"
                OpName %atomicStore_8bea94 "atomicStore_8bea94"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -41,7 +41,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %19
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %22 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %25
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.wgsl
index 800c8fd231..08fdac1b3f 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.wgsl
@@ -7,7 +7,7 @@ fn atomicStore_8bea94() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicStore_8bea94();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.dxc.hlsl
index 55b8f78ea5..5456c6db0c 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -7,7 +7,7 @@ void atomicStore_726882() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.fxc.hlsl
index 55b8f78ea5..5456c6db0c 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -7,7 +7,7 @@ void atomicStore_726882() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.glsl
index 825825c4a8..065b6135c2 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.glsl
@@ -7,7 +7,7 @@ void atomicStore_726882() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicStore_726882();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.msl
index 1a458eb853..33849ede18 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.msl
@@ -6,7 +6,7 @@ void atomicStore_726882(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicStore_726882(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.spvasm
index 6f8e362750..6673a78740 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.spvasm
@@ -12,7 +12,7 @@
                OpName %arg_0 "arg_0"
                OpName %atomicStore_726882 "atomicStore_726882"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -39,7 +39,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %18
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %21 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.wgsl
index b90d965f68..6644f12c43 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.wgsl
@@ -7,7 +7,7 @@ fn atomicStore_726882() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicStore_726882();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.dxc.hlsl
index 4d80582dbb..f7c62c0cb2 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicSub_77883a() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.fxc.hlsl
index 4d80582dbb..f7c62c0cb2 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicSub_77883a() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.glsl
index f600cd52aa..d878b2de5b 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicSub_77883a() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicSub_77883a();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.msl
index 86f5de20a3..fcc79100d4 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicSub_77883a(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicSub_77883a(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.spvasm
index 820d0ae31f..2b3b8bac8e 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicSub_77883a "atomicSub_77883a"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.wgsl
index 56079fe943..78a324801e 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicSub_77883a() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicSub_77883a();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.dxc.hlsl
index dba0df91fb..e50da1de57 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicSub_0d26c2() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.fxc.hlsl
index dba0df91fb..e50da1de57 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicSub_0d26c2() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.glsl
index cec1ba9412..9bd1162eac 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicSub_0d26c2() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicSub_0d26c2();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.msl
index 91e3b4bdc5..a166d08c27 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicSub_0d26c2(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicSub_0d26c2(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.spvasm
index c42f0b9bac..55dfb703cf 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicSub_0d26c2 "atomicSub_0d26c2"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -44,7 +44,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %20
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %23 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.wgsl
index 2b69af66f5..cb4dbd1f2d 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicSub_0d26c2() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicSub_0d26c2();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.dxc.hlsl
index 3cec31adeb..c00f2dd8df 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicXor_75dc95() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.fxc.hlsl
index 3cec31adeb..c00f2dd8df 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicXor_75dc95() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.glsl
index cfcab07e3c..434af31807 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicXor_75dc95() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicXor_75dc95();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.msl
index b5c2e2c54b..70c0e42450 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicXor_75dc95(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicXor_75dc95(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.spvasm
index 542376de1a..d4d71ceab3 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicXor_75dc95 "atomicXor_75dc95"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.wgsl
index f14ac31618..b28291e92e 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicXor_75dc95() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicXor_75dc95();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.dxc.hlsl
index 2e953e9ae0..9195263cc4 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicXor_c8e6be() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.fxc.hlsl
index 2e953e9ae0..9195263cc4 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicXor_c8e6be() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.glsl
index 639b4ce630..59dd3a975b 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicXor_c8e6be() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicXor_c8e6be();
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.msl
index 6993e95c04..784f87007c 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicXor_c8e6be(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicXor_c8e6be(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.spvasm
index 4f19634fbf..e350d66a4b 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicXor_c8e6be "atomicXor_c8e6be"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -44,7 +44,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %20
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %23 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.wgsl
index 53f7436cb6..f8d1b77c17 100644
--- a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicXor_c8e6be() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicXor_c8e6be();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.dxc.hlsl
index 04ff6d8946..423a5642bc 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.fxc.hlsl
index 04ff6d8946..423a5642bc 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl
index c95c6a9f49..a9f59ed490 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl
index e7d19e9d5e..6e646d5ffd 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_794055(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm
index 32bc60e2a6..51c50d15a6 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicAdd_794055 "atomicAdd_794055"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl
index 6050ff2687..ff925f623d 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicAdd_794055() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.dxc.hlsl
index 88c04ad9f3..eaef5c5a68 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.fxc.hlsl
index 88c04ad9f3..eaef5c5a68 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl
index 5a5b50b48c..e0f09816ce 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl
index bd63c56854..39ec3fdba7 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_d5db1d(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm
index c50dbaef6a..ba821a0ecd 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -44,7 +44,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %20
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %23 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl
index f7f5447422..0a37a1596f 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicAdd_d5db1d() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.dxc.hlsl
index 89a6a358ba..0c494d211e 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.fxc.hlsl
index 89a6a358ba..0c494d211e 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl
index c95c6a9f49..a9f59ed490 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl
index 62639d7b4a..5f8945fc05 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_794055(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm
index 3dc0a5d301..1f62e68258 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicAdd_794055 "atomicAdd_794055"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -46,7 +46,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl
index 723a1135af..d59a523473 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicAdd_794055() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.dxc.hlsl
index d1179cc47d..99ac4aaded 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.fxc.hlsl
index d1179cc47d..99ac4aaded 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl
index 5a5b50b48c..e0f09816ce 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl
index 04a890a74c..6dab26276f 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_d5db1d(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm
index 5daee6404f..66a3661a68 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -44,7 +44,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %20
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %23 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl
index 61d34ccb7b..5a1db0ecf7 100644
--- a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicAdd_d5db1d() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.dxc.hlsl
index 35cf5f1ae2..dc1a28ca4e 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.fxc.hlsl
index 35cf5f1ae2..dc1a28ca4e 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.glsl
index aa80ede180..5f5f012e54 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.msl
index b30df095e1..19c4023dff 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_794055(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.spvasm
index 3d67dcfcfc..1d077438c1 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -51,7 +51,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %24
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %27 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.wgsl
index 27e52764a1..e7a62ef012 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicAdd_794055() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.dxc.hlsl
index 8aae75daf5..4056d79187 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.fxc.hlsl
index 8aae75daf5..4056d79187 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.glsl
index dbfc37af59..7254632a89 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.msl
index 29c6f4b3ca..9664a87297 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_d5db1d(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.spvasm
index 1cab36f0a8..1007451929 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -49,7 +49,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.wgsl
index 1ef7a33d6a..676530e715 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicAdd_d5db1d() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.dxc.hlsl
index 39a733b315..8d82cb1f3a 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicAnd_45a819() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.fxc.hlsl
index 39a733b315..8d82cb1f3a 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicAnd_45a819() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.glsl
index 564bc63017..8ff35039d3 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicAnd_45a819() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicAnd_45a819();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.msl
index 962a96cce8..a319bdbead 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicAnd_45a819(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAnd_45a819(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.spvasm
index 598acf25ac..1619f701a0 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -51,7 +51,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %24
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %27 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.wgsl
index d757c09185..7e25958a24 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicAnd_45a819() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicAnd_45a819();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.dxc.hlsl
index 81340621af..a5b66bc0a5 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicAnd_34edd3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.fxc.hlsl
index 81340621af..a5b66bc0a5 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicAnd_34edd3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.glsl
index 2c7ded032d..f0a5768e5f 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicAnd_34edd3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicAnd_34edd3();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.msl
index d1624058bc..e6c7e39321 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicAnd_34edd3(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAnd_34edd3(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.spvasm
index 0eeed44ead..8df43d3d87 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -49,7 +49,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.wgsl
index dba5360f3a..08b4866519 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicAnd_34edd3() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicAnd_34edd3();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.dxc.hlsl
index e9f292a283..f969d035d6 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -30,7 +30,7 @@ void atomicCompareExchangeWeak_e88938() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.fxc.hlsl
index e9f292a283..f969d035d6 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -30,7 +30,7 @@ void atomicCompareExchangeWeak_e88938() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl
index 14a7d5af34..bfa323328d 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl
@@ -32,7 +32,7 @@ void atomicCompareExchangeWeak_e88938() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicCompareExchangeWeak_e88938();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl
index dd319d0ad5..ce8a6a0a11 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl
@@ -33,7 +33,7 @@ void atomicCompareExchangeWeak_e88938(threadgroup atomic_int* const tint_symbol_
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_3) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_3) {
   atomic_store_explicit(tint_symbol_3, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicCompareExchangeWeak_e88938(tint_symbol_3);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm
index 2c9ca9f3c8..ab701933da 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm
@@ -21,7 +21,7 @@
                OpMemberName %__atomic_compare_exchange_resulti32 0 "old_value"
                OpMemberName %__atomic_compare_exchange_resulti32 1 "exchanged"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -76,7 +76,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %36
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %39 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl
index b091a13911..797f95b159 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl
@@ -23,7 +23,7 @@ fn atomicCompareExchangeWeak_e88938() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicCompareExchangeWeak_e88938();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.dxc.hlsl
index 419b817c9a..99e867f07e 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -30,7 +30,7 @@ void atomicCompareExchangeWeak_83580d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.fxc.hlsl
index 419b817c9a..99e867f07e 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -30,7 +30,7 @@ void atomicCompareExchangeWeak_83580d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl
index 8dd64fcf3f..aeaaf5f701 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl
@@ -32,7 +32,7 @@ void atomicCompareExchangeWeak_83580d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicCompareExchangeWeak_83580d();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl
index 4a2cafc30e..4590197c89 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl
@@ -33,7 +33,7 @@ void atomicCompareExchangeWeak_83580d(threadgroup atomic_uint* const tint_symbol
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_3) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_3) {
   atomic_store_explicit(tint_symbol_3, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicCompareExchangeWeak_83580d(tint_symbol_3);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm
index 89af02b5c8..aae3c6ca81 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm
@@ -21,7 +21,7 @@
                OpMemberName %__atomic_compare_exchange_resultu32 0 "old_value"
                OpMemberName %__atomic_compare_exchange_resultu32 1 "exchanged"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -74,7 +74,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %34
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %37 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl
index be08380ef2..e0782fce72 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl
@@ -23,7 +23,7 @@ fn atomicCompareExchangeWeak_83580d() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicCompareExchangeWeak_83580d();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.dxc.hlsl
index 18bc9ab28a..af145963d7 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicExchange_e114ba() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.fxc.hlsl
index 18bc9ab28a..af145963d7 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicExchange_e114ba() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.glsl
index 32a7fcceac..77e50efe1e 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicExchange_e114ba() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicExchange_e114ba();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.msl
index 1886d0a165..bfb645d58c 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicExchange_e114ba(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicExchange_e114ba(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.spvasm
index e72725be34..f2ba7138c2 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -51,7 +51,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %24
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %27 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.wgsl
index 555469e670..a28a09051a 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicExchange_e114ba() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicExchange_e114ba();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.dxc.hlsl
index cef446b914..6c3f1b73dc 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicExchange_0a5dca() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.fxc.hlsl
index cef446b914..6c3f1b73dc 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicExchange_0a5dca() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.glsl
index e4d06e3314..3321d928dd 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicExchange_0a5dca() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicExchange_0a5dca();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.msl
index c42c47d438..d805421de0 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicExchange_0a5dca(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicExchange_0a5dca(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.spvasm
index 697005356b..1130819d5b 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -49,7 +49,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.wgsl
index 89fff60d5c..c13602a3d0 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicExchange_0a5dca() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicExchange_0a5dca();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.dxc.hlsl
index 3e2674ee55..14e42dd3a5 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicLoad_afcc03() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.fxc.hlsl
index 3e2674ee55..14e42dd3a5 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicLoad_afcc03() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.glsl
index 351d2dcc84..6596bb1867 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicLoad_afcc03() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicLoad_afcc03();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.msl
index 8f6ee408a4..3f9bc5f5ae 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicLoad_afcc03(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicLoad_afcc03(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.spvasm
index 829b8487e3..f4f86f8626 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicLoad_afcc03 "atomicLoad_afcc03"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -45,7 +45,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %21
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %24 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.wgsl
index af0c057346..ba60171363 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicLoad_afcc03() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicLoad_afcc03();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.dxc.hlsl
index 3aa482d1d1..2eb7c6cd6f 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicLoad_361bf1() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.fxc.hlsl
index 3aa482d1d1..2eb7c6cd6f 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicLoad_361bf1() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.glsl
index 2ad60dbb1d..b21c00a447 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.glsl
@@ -9,7 +9,7 @@ void atomicLoad_361bf1() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicLoad_361bf1();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.msl
index d7fcb6e569..c9f5cd3477 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.msl
@@ -8,7 +8,7 @@ void atomicLoad_361bf1(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicLoad_361bf1(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.spvasm
index 7a075badba..5a8a6333dc 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicLoad_361bf1 "atomicLoad_361bf1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -43,7 +43,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %19
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %22 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.wgsl
index f132c6fa83..d9fd46d242 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.wgsl
@@ -9,7 +9,7 @@ fn atomicLoad_361bf1() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicLoad_361bf1();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.dxc.hlsl
index 3c35b63d47..14fdeb1991 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicMax_a89cc3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.fxc.hlsl
index 3c35b63d47..14fdeb1991 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicMax_a89cc3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.glsl
index 9d9a766b19..28a4f500e9 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicMax_a89cc3() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicMax_a89cc3();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.msl
index 7a3987d5ac..b0267331dc 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicMax_a89cc3(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicMax_a89cc3(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.spvasm
index 696868b763..6c89567323 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -51,7 +51,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %24
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %27 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.wgsl
index 9086b7426e..85bdef4ee5 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicMax_a89cc3() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicMax_a89cc3();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.dxc.hlsl
index d2eef23519..ede6d3686f 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicMax_beccfc() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.fxc.hlsl
index d2eef23519..ede6d3686f 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicMax_beccfc() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.glsl
index c060e4f550..1cce715fcf 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicMax_beccfc() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicMax_beccfc();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.msl
index edd31021e4..e8951d46b3 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicMax_beccfc(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicMax_beccfc(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.spvasm
index ad735e12c7..86df69b510 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -49,7 +49,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.wgsl
index e74059976f..fb24f1f3e5 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicMax_beccfc() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicMax_beccfc();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.dxc.hlsl
index 686e2bbff0..1daa6641ba 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicMin_278235() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.fxc.hlsl
index 686e2bbff0..1daa6641ba 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicMin_278235() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.glsl
index 9f7f34263b..91065e16af 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicMin_278235() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicMin_278235();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.msl
index 8b6eeebddf..ca77a67ce4 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicMin_278235(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicMin_278235(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.spvasm
index 564e8b7e97..edea5232c9 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -51,7 +51,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %24
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %27 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.wgsl
index e55849b691..336f3d6cdc 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicMin_278235() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicMin_278235();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.dxc.hlsl
index dab785311c..109dcd3863 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicMin_69d383() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.fxc.hlsl
index dab785311c..109dcd3863 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicMin_69d383() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.glsl
index 5dbe9c91b1..793a7ec520 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicMin_69d383() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicMin_69d383();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.msl
index 6336751508..4731075ee2 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicMin_69d383(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicMin_69d383(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.spvasm
index 8c0bfde247..45fb1c695f 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -49,7 +49,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.wgsl
index 9a15df0279..ed65056a1e 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicMin_69d383() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicMin_69d383();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.dxc.hlsl
index 2c6edf22b0..d35a39fefb 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicOr_d09248() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.fxc.hlsl
index 2c6edf22b0..d35a39fefb 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicOr_d09248() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.glsl
index b9e8b775f5..07f565a371 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicOr_d09248() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicOr_d09248();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.msl
index e262929f5c..1f405c7c1e 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicOr_d09248(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicOr_d09248(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.spvasm
index f2cdcca2b4..b7c2f0beb8 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -51,7 +51,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %24
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %27 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.wgsl
index f0329eb20e..a3edfe06b1 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicOr_d09248() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicOr_d09248();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.dxc.hlsl
index 962ffd80cd..530ca71cd3 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicOr_5e3d61() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.fxc.hlsl
index 962ffd80cd..530ca71cd3 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicOr_5e3d61() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.glsl
index 42de63e74d..a8a68933db 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicOr_5e3d61() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicOr_5e3d61();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.msl
index 4078be65eb..5079e80389 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicOr_5e3d61(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicOr_5e3d61(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.spvasm
index 437d7bf15b..be16c4ba3a 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -49,7 +49,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.wgsl
index 781ca2e3b2..4aaef480da 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicOr_5e3d61() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicOr_5e3d61();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.dxc.hlsl
index 068a48013e..136c31d9ad 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicStore_8bea94() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.fxc.hlsl
index 068a48013e..136c31d9ad 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicStore_8bea94() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.glsl
index 927d791a2f..33f270da07 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.glsl
@@ -10,7 +10,7 @@ void atomicStore_8bea94() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicStore_8bea94();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.msl
index 1e0fd57bcd..ba6fa5af88 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.msl
@@ -9,7 +9,7 @@ void atomicStore_8bea94(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicStore_8bea94(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.spvasm
index 63e93126b1..eef6685b41 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicStore_8bea94 "atomicStore_8bea94"
                OpName %arg_1 "arg_1"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -47,7 +47,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %23
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %26 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.wgsl
index 026212237f..9c22f99054 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.wgsl
@@ -10,7 +10,7 @@ fn atomicStore_8bea94() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicStore_8bea94();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.dxc.hlsl
index 177a50895f..262713619f 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -10,7 +10,7 @@ void atomicStore_726882() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.fxc.hlsl
index 177a50895f..262713619f 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -10,7 +10,7 @@ void atomicStore_726882() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.glsl
index 3b5c030991..0daf92065c 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.glsl
@@ -10,7 +10,7 @@ void atomicStore_726882() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicStore_726882();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.msl
index fd362677ce..1c721e440a 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.msl
@@ -9,7 +9,7 @@ void atomicStore_726882(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicStore_726882(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.spvasm
index 2b50c09779..d89a59b015 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.spvasm
@@ -13,7 +13,7 @@
                OpName %atomicStore_726882 "atomicStore_726882"
                OpName %arg_1 "arg_1"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -45,7 +45,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %21
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %24 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.wgsl
index fa0013aba5..8e401802d7 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.wgsl
@@ -10,7 +10,7 @@ fn atomicStore_726882() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicStore_726882();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.dxc.hlsl
index 6e2702ed28..439db079b2 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicSub_77883a() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.fxc.hlsl
index 6e2702ed28..439db079b2 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicSub_77883a() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.glsl
index d02e98d0b8..89ef3a6021 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicSub_77883a() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicSub_77883a();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.msl
index 208e18a20d..7eb4abe051 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicSub_77883a(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicSub_77883a(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.spvasm
index 9f3a0652f8..4f9ad410dd 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -51,7 +51,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %24
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %27 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.wgsl
index b2781cec60..e4b82dbac4 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicSub_77883a() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicSub_77883a();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.dxc.hlsl
index a60453f94f..90e0feb37c 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicSub_0d26c2() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.fxc.hlsl
index a60453f94f..90e0feb37c 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicSub_0d26c2() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.glsl
index 30e8f51a19..f29b9362ec 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicSub_0d26c2() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicSub_0d26c2();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.msl
index ec9661dceb..11750e7277 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicSub_0d26c2(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicSub_0d26c2(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.spvasm
index c1b5f7a3c6..341cd2d88a 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -49,7 +49,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.wgsl
index 77f25f7d70..6a118946f9 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicSub_0d26c2() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicSub_0d26c2();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.dxc.hlsl
index fc1b4cc4f0..dbe39804d7 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicXor_75dc95() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.fxc.hlsl
index fc1b4cc4f0..dbe39804d7 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicXor_75dc95() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.glsl
index bdb9b796b9..d13ec57d2d 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicXor_75dc95() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicXor_75dc95();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.msl
index 840c3182c3..75788442d2 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicXor_75dc95(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicXor_75dc95(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.spvasm
index 2bac01dfc2..9296ee7e51 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -51,7 +51,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %24
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %27 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.wgsl
index 54490e1c5f..6bf52a00a5 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicXor_75dc95() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicXor_75dc95();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.dxc.hlsl
index 21c9ae0285..32ee7a88f9 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -13,7 +13,7 @@ void atomicXor_c8e6be() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.fxc.hlsl
index 21c9ae0285..32ee7a88f9 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -13,7 +13,7 @@ void atomicXor_c8e6be() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.glsl
index ad695ee40e..b78672827b 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.glsl
@@ -12,7 +12,7 @@ void atomicXor_c8e6be() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicXor_c8e6be();
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.msl
index 3eb2509da5..6c75f1ec56 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.msl
@@ -11,7 +11,7 @@ void atomicXor_c8e6be(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicXor_c8e6be(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.spvasm
index 83c9054512..db28441aa2 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -49,7 +49,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %22
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %25 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.wgsl
index c75d80815c..be98d875c5 100644
--- a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.wgsl
@@ -12,7 +12,7 @@ fn atomicXor_c8e6be() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicXor_c8e6be();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.dxc.hlsl
index f839d4c429..71de2a2f3e 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -12,7 +12,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.fxc.hlsl
index f839d4c429..71de2a2f3e 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -12,7 +12,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl
index f0f8f83baf..56459797c3 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl
@@ -11,7 +11,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl
index 9f11082f0e..6c220f41eb 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl
@@ -10,7 +10,7 @@ void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_794055(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm
index 843bd5ae40..4263a116f1 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -50,7 +50,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %23
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %26 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl
index 540501adaf..cb88afd1f7 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl
@@ -11,7 +11,7 @@ fn atomicAdd_794055() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.dxc.hlsl
index dff6e7e189..a91fde6be5 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -12,7 +12,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.fxc.hlsl
index dff6e7e189..a91fde6be5 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -12,7 +12,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl
index a59e2dc79f..0b00772610 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl
@@ -11,7 +11,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl
index 74b7a0d727..ca9e8e5e5c 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl
@@ -10,7 +10,7 @@ void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_d5db1d(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm
index 77041b4aef..81eb6af292 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -48,7 +48,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %21
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %24 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl
index 64dabf43d1..c7c95650e8 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl
@@ -11,7 +11,7 @@ fn atomicAdd_d5db1d() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.dxc.hlsl
index 41d2c6ebd6..9ccc48ac9b 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.dxc.hlsl
@@ -12,7 +12,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.fxc.hlsl
index 41d2c6ebd6..9ccc48ac9b 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.fxc.hlsl
@@ -12,7 +12,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   int atomic_result_1 = 0;
   InterlockedExchange(arg_0, 0, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl
index f0f8f83baf..56459797c3 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl
@@ -11,7 +11,7 @@ void atomicAdd_794055() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0);
   barrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl
index dc059dd0c0..d5ea965abf 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl
@@ -10,7 +10,7 @@ void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_int* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_794055(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm
index ed49501697..e98df4a7b5 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -50,7 +50,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %23
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %26 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %14
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl
index b5076c3852..4bbcf3422e 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl
@@ -11,7 +11,7 @@ fn atomicAdd_794055() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0i);
   workgroupBarrier();
   atomicAdd_794055();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.dxc.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.dxc.hlsl
index 3824cc7b37..e86b714395 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.dxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.dxc.hlsl
@@ -12,7 +12,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.fxc.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.fxc.hlsl
index 3824cc7b37..e86b714395 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.fxc.hlsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.fxc.hlsl
@@ -12,7 +12,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   uint atomic_result_1 = 0u;
   InterlockedExchange(arg_0, 0u, atomic_result_1);
   GroupMemoryBarrierWithGroupSync();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl
index a59e2dc79f..0b00772610 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl
@@ -11,7 +11,7 @@ void atomicAdd_d5db1d() {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index) {
+void compute_main_inner(uint local_invocation_index_2) {
   atomicExchange(arg_0, 0u);
   barrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl
index 1b33ab894f..02a71ee2fa 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl
@@ -10,7 +10,7 @@ void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
   return;
 }
 
-void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+void compute_main_inner(uint local_invocation_index_2, threadgroup atomic_uint* const tint_symbol_1) {
   atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
   threadgroup_barrier(mem_flags::mem_threadgroup);
   atomicAdd_d5db1d(tint_symbol_1);
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm
index 1388894da0..c21ef7e5d9 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm
@@ -14,7 +14,7 @@
                OpName %arg_1 "arg_1"
                OpName %res "res"
                OpName %compute_main_inner "compute_main_inner"
-               OpName %local_invocation_index "local_invocation_index"
+               OpName %local_invocation_index_2 "local_invocation_index_2"
                OpName %compute_main_1 "compute_main_1"
                OpName %compute_main_inner_1 "compute_main_inner_1"
                OpName %local_invocation_index_1_param "local_invocation_index_1_param"
@@ -48,7 +48,7 @@
                OpReturn
                OpFunctionEnd
 %compute_main_inner = OpFunction %void None %21
-%local_invocation_index = OpFunctionParameter %uint
+%local_invocation_index_2 = OpFunctionParameter %uint
          %24 = OpLabel
                OpAtomicStore %arg_0 %uint_2 %uint_0 %6
                OpControlBarrier %uint_2 %uint_2 %uint_264
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl
index 7faf057482..26effa5f58 100644
--- a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl
@@ -11,7 +11,7 @@ fn atomicAdd_d5db1d() {
   return;
 }
 
-fn compute_main_inner(local_invocation_index : u32) {
+fn compute_main_inner(local_invocation_index_2 : u32) {
   atomicStore(&(arg_0), 0u);
   workgroupBarrier();
   atomicAdd_d5db1d();
diff --git a/test/tint/vk-gl-cts/binding_model/dynamic_offset/shader_reuse_differing_layout_graphics/0.wgsl b/test/tint/vk-gl-cts/binding_model/dynamic_offset/shader_reuse_differing_layout_graphics/0.wgsl
index e77dd7dca9..4f0478ec57 100644
--- a/test/tint/vk-gl-cts/binding_model/dynamic_offset/shader_reuse_differing_layout_graphics/0.wgsl
+++ b/test/tint/vk-gl-cts/binding_model/dynamic_offset/shader_reuse_differing_layout_graphics/0.wgsl
@@ -2,7 +2,7 @@ struct block0 {
   in_color : vec4<f32>,
 }
 
-var<private> position : vec4<f32>;
+var<private> pos : vec4<f32>;
 
 var<private> frag_color : vec4<f32>;
 
@@ -11,7 +11,7 @@ var<private> frag_color : vec4<f32>;
 var<private> gl_Position : vec4<f32>;
 
 fn main_1() {
-  let x_24 : vec4<f32> = position;
+  let x_24 : vec4<f32> = pos;
   gl_Position = x_24;
   let x_27 : vec4<f32> = x_8.in_color;
   frag_color = x_27;
@@ -27,7 +27,7 @@ struct main_out {
 
 @vertex
 fn main(@location(0) position_param : vec4<f32>) -> main_out {
-  position = position_param;
+  pos = position_param;
   main_1();
   return main_out(gl_Position, frag_color);
 }
diff --git a/test/tint/vk-gl-cts/combined_operations/negintdivand/0-opt.wgsl b/test/tint/vk-gl-cts/combined_operations/negintdivand/0-opt.wgsl
index 98179f874b..3f8e233db3 100644
--- a/test/tint/vk-gl-cts/combined_operations/negintdivand/0-opt.wgsl
+++ b/test/tint/vk-gl-cts/combined_operations/negintdivand/0-opt.wgsl
@@ -1,13 +1,13 @@
-var<private> position : vec4<f32>;
+var<private> pos : vec4<f32>;
 
 var<private> frag_color : vec4<f32>;
 
 var<private> gl_Position : vec4<f32>;
 
 fn main_1() {
-  let x_21 : vec4<f32> = position;
+  let x_21 : vec4<f32> = pos;
   gl_Position = x_21;
-  let x_23 : vec4<f32> = position;
+  let x_23 : vec4<f32> = pos;
   frag_color = (x_23 * 0.5);
   return;
 }
@@ -21,7 +21,7 @@ struct main_out {
 
 @vertex
 fn main(@location(0) position_param : vec4<f32>) -> main_out {
-  position = position_param;
+  pos = position_param;
   main_1();
   return main_out(gl_Position, frag_color);
 }
diff --git a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_equal/0-opt.wgsl b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_equal/0-opt.wgsl
index b3544f7ca5..6c2aa6da8d 100644
--- a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_equal/0-opt.wgsl
+++ b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_equal/0-opt.wgsl
@@ -1,9 +1,9 @@
-var<private> position : vec4<f32>;
+var<private> pos : vec4<f32>;
 
 var<private> gl_Position : vec4<f32>;
 
 fn main_1() {
-  let x_22 : vec4<f32> = position;
+  let x_22 : vec4<f32> = pos;
   let x_23 : vec2<f32> = vec2<f32>(x_22.x, x_22.y);
   gl_Position = vec4<f32>(x_23.x, x_23.y, 0.5, 1.0);
   return;
@@ -16,7 +16,7 @@ struct main_out {
 
 @vertex
 fn main(@location(0) position_param : vec4<f32>) -> main_out {
-  position = position_param;
+  pos = position_param;
   main_1();
   return main_out(gl_Position);
 }
diff --git a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_greater/0-opt.wgsl b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_greater/0-opt.wgsl
index 811fe594dd..a7b5af0fb3 100644
--- a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_greater/0-opt.wgsl
+++ b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_greater/0-opt.wgsl
@@ -1,9 +1,9 @@
-var<private> position : vec4<f32>;
+var<private> pos : vec4<f32>;
 
 var<private> gl_Position : vec4<f32>;
 
 fn main_1() {
-  let x_22 : vec4<f32> = position;
+  let x_22 : vec4<f32> = pos;
   let x_23 : vec2<f32> = vec2<f32>(x_22.x, x_22.y);
   gl_Position = vec4<f32>(x_23.x, x_23.y, 0.600000024, 1.0);
   return;
@@ -16,7 +16,7 @@ struct main_out {
 
 @vertex
 fn main(@location(0) position_param : vec4<f32>) -> main_out {
-  position = position_param;
+  pos = position_param;
   main_1();
   return main_out(gl_Position);
 }
diff --git a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_less/0-opt.wgsl b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_less/0-opt.wgsl
index ddc27e71db..f86f723500 100644
--- a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_less/0-opt.wgsl
+++ b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_less/0-opt.wgsl
@@ -1,9 +1,9 @@
-var<private> position : vec4<f32>;
+var<private> pos : vec4<f32>;
 
 var<private> gl_Position : vec4<f32>;
 
 fn main_1() {
-  let x_22 : vec4<f32> = position;
+  let x_22 : vec4<f32> = pos;
   let x_23 : vec2<f32> = vec2<f32>(x_22.x, x_22.y);
   gl_Position = vec4<f32>(x_23.x, x_23.y, 0.400000006, 1.0);
   return;
@@ -16,7 +16,7 @@ struct main_out {
 
 @vertex
 fn main(@location(0) position_param : vec4<f32>) -> main_out {
-  position = position_param;
+  pos = position_param;
   main_1();
   return main_out(gl_Position);
 }
diff --git a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_not_equal/0-opt.wgsl b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_not_equal/0-opt.wgsl
index 396a887959..1fb130c2a9 100644
--- a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_not_equal/0-opt.wgsl
+++ b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/early_fragment/depth_not_equal/0-opt.wgsl
@@ -1,9 +1,9 @@
-var<private> position : vec4<f32>;
+var<private> pos : vec4<f32>;
 
 var<private> gl_Position : vec4<f32>;
 
 fn main_1() {
-  let x_22 : vec4<f32> = position;
+  let x_22 : vec4<f32> = pos;
   let x_23 : vec2<f32> = vec2<f32>(x_22.x, x_22.y);
   gl_Position = vec4<f32>(x_23.x, x_23.y, 0.300000012, 1.0);
   return;
@@ -16,7 +16,7 @@ struct main_out {
 
 @vertex
 fn main(@location(0) position_param : vec4<f32>) -> main_out {
-  position = position_param;
+  pos = position_param;
   main_1();
   return main_out(gl_Position);
 }
diff --git a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/execution_mode/depthgreater_1/0-opt.wgsl b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/execution_mode/depthgreater_1/0-opt.wgsl
index 868da48119..5804b56e4c 100644
--- a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/execution_mode/depthgreater_1/0-opt.wgsl
+++ b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/execution_mode/depthgreater_1/0-opt.wgsl
@@ -1,9 +1,9 @@
-var<private> position : vec4<f32>;
+var<private> pos : vec4<f32>;
 
 var<private> gl_Position : vec4<f32>;
 
 fn main_1() {
-  let x_22 : vec4<f32> = position;
+  let x_22 : vec4<f32> = pos;
   let x_23 : vec2<f32> = vec2<f32>(x_22.x, x_22.y);
   gl_Position = vec4<f32>(x_23.x, x_23.y, 0.699999988, 1.0);
   return;
@@ -16,7 +16,7 @@ struct main_out {
 
 @vertex
 fn main(@location(0) position_param : vec4<f32>) -> main_out {
-  position = position_param;
+  pos = position_param;
   main_1();
   return main_out(gl_Position);
 }
diff --git a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/execution_mode/depthgreater_2/0-opt.wgsl b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/execution_mode/depthgreater_2/0-opt.wgsl
index e59c3fc75a..04923366d6 100644
--- a/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/execution_mode/depthgreater_2/0-opt.wgsl
+++ b/test/tint/vk-gl-cts/spirv_assembly/instruction/graphics/execution_mode/depthgreater_2/0-opt.wgsl
@@ -1,9 +1,9 @@
-var<private> position : vec4<f32>;
+var<private> pos : vec4<f32>;
 
 var<private> gl_Position : vec4<f32>;
 
 fn main_1() {
-  let x_22 : vec4<f32> = position;
+  let x_22 : vec4<f32> = pos;
   let x_23 : vec2<f32> = vec2<f32>(x_22.x, x_22.y);
   gl_Position = vec4<f32>(x_23.x, x_23.y, 0.200000003, 1.0);
   return;
@@ -16,7 +16,7 @@ struct main_out {
 
 @vertex
 fn main(@location(0) position_param : vec4<f32>) -> main_out {
-  position = position_param;
+  pos = position_param;
   main_1();
   return main_out(gl_Position);
 }
diff --git a/test/tint/vk-gl-cts/spirv_assembly/instruction/spirv1p4/hlsl_functionality1/decorate_string/0.wgsl b/test/tint/vk-gl-cts/spirv_assembly/instruction/spirv1p4/hlsl_functionality1/decorate_string/0.wgsl
index 330cec1d57..83223c4e31 100644
--- a/test/tint/vk-gl-cts/spirv_assembly/instruction/spirv1p4/hlsl_functionality1/decorate_string/0.wgsl
+++ b/test/tint/vk-gl-cts/spirv_assembly/instruction/spirv1p4/hlsl_functionality1/decorate_string/0.wgsl
@@ -1,11 +1,11 @@
-var<private> position : vec4<f32>;
+var<private> vert_pos : vec4<f32>;
 
 var<private> pos : u32;
 
 var<private> gl_Position : vec4<f32>;
 
 fn main_1() {
-  let x_22 : vec4<f32> = position;
+  let x_22 : vec4<f32> = vert_pos;
   gl_Position = x_22;
   pos = 0u;
   return;
@@ -20,7 +20,7 @@ struct main_out {
 
 @vertex
 fn main(@location(0) position_param : vec4<f32>) -> main_out {
-  position = position_param;
+  vert_pos = position_param;
   main_1();
   return main_out(gl_Position, pos);
 }
diff --git a/test/tint/vk-gl-cts/subgroup_uniform_control_flow/discard/subgroup_reconverge_discard00/0.wgsl b/test/tint/vk-gl-cts/subgroup_uniform_control_flow/discard/subgroup_reconverge_discard00/0.wgsl
index 162c7151c1..f7b042d7b3 100644
--- a/test/tint/vk-gl-cts/subgroup_uniform_control_flow/discard/subgroup_reconverge_discard00/0.wgsl
+++ b/test/tint/vk-gl-cts/subgroup_uniform_control_flow/discard/subgroup_reconverge_discard00/0.wgsl
@@ -1,9 +1,9 @@
-var<private> position : vec3<f32>;
+var<private> pos : vec3<f32>;
 
 var<private> gl_Position : vec4<f32>;
 
 fn main_1() {
-  let x_21 : vec3<f32> = position;
+  let x_21 : vec3<f32> = pos;
   gl_Position = vec4<f32>(x_21.x, x_21.y, x_21.z, 1.0);
   return;
 }
@@ -15,7 +15,7 @@ struct main_out {
 
 @vertex
 fn main(@location(0) position_param : vec3<f32>) -> main_out {
-  position = position_param;
+  pos = position_param;
   main_1();
   return main_out(gl_Position);
 }