[spirv-reader][ir] Adding atomic tests

Add atomic tests for the new SPIR-V IR reader. The reader support to
generate the atomic intrinsics is in place.

Bug: 404501988
Change-Id: Ia527c1375670c42af67afc07fc5c9ee6734c5a70
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/231614
Auto-Submit: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/lang/spirv/intrinsic/data.cc b/src/tint/lang/spirv/intrinsic/data.cc
index 5bd1f22..b4113b8 100644
--- a/src/tint/lang/spirv/intrinsic/data.cc
+++ b/src/tint/lang/spirv/intrinsic/data.cc
@@ -1648,12 +1648,12 @@
   {
     /* [10] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(96),
+    /* matcher_indices */ MatcherIndicesIndex(53),
   },
   {
     /* [11] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [12] */
@@ -1663,27 +1663,27 @@
   {
     /* [13] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [14] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [15] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(196),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [16] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(99),
+    /* matcher_indices */ MatcherIndicesIndex(96),
   },
   {
     /* [17] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [18] */
@@ -1708,7 +1708,7 @@
   {
     /* [22] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(102),
+    /* matcher_indices */ MatcherIndicesIndex(99),
   },
   {
     /* [23] */
@@ -1723,57 +1723,57 @@
   {
     /* [25] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [26] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [27] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(222),
+    /* matcher_indices */ MatcherIndicesIndex(196),
   },
   {
     /* [28] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(192),
+    /* matcher_indices */ MatcherIndicesIndex(102),
   },
   {
     /* [29] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [30] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [31] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [32] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [33] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(222),
   },
   {
     /* [34] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(198),
+    /* matcher_indices */ MatcherIndicesIndex(192),
   },
   {
     /* [35] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [36] */
@@ -1798,17 +1798,17 @@
   {
     /* [40] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(53),
+    /* matcher_indices */ MatcherIndicesIndex(198),
   },
   {
     /* [41] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [42] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [43] */
@@ -1818,227 +1818,227 @@
   {
     /* [44] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [45] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(192),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [46] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(192),
   },
   {
     /* [47] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [48] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [49] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(196),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [50] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(198),
+    /* matcher_indices */ MatcherIndicesIndex(196),
   },
   {
     /* [51] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(198),
   },
   {
     /* [52] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [53] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [54] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(196),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [55] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(96),
+    /* matcher_indices */ MatcherIndicesIndex(196),
   },
   {
     /* [56] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(96),
   },
   {
     /* [57] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [58] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [59] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(210),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [60] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(99),
+    /* matcher_indices */ MatcherIndicesIndex(210),
   },
   {
     /* [61] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(99),
   },
   {
     /* [62] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [63] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [64] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(212),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [65] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(96),
+    /* matcher_indices */ MatcherIndicesIndex(212),
   },
   {
     /* [66] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(96),
   },
   {
     /* [67] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [68] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [69] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(196),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [70] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(99),
+    /* matcher_indices */ MatcherIndicesIndex(196),
   },
   {
     /* [71] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(99),
   },
   {
     /* [72] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [73] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [74] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(196),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [75] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(102),
+    /* matcher_indices */ MatcherIndicesIndex(196),
   },
   {
     /* [76] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(102),
   },
   {
     /* [77] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [78] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [79] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(222),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [80] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(96),
+    /* matcher_indices */ MatcherIndicesIndex(222),
   },
   {
     /* [81] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(96),
   },
   {
     /* [82] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [83] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [84] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(196),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [85] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(105),
+    /* matcher_indices */ MatcherIndicesIndex(196),
   },
   {
     /* [86] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(105),
   },
   {
     /* [87] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [88] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [89] */
@@ -2048,22 +2048,22 @@
   {
     /* [90] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(108),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [91] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(51),
+    /* matcher_indices */ MatcherIndicesIndex(108),
   },
   {
     /* [92] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(51),
   },
   {
     /* [93] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [94] */
@@ -2073,167 +2073,167 @@
   {
     /* [95] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(192),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [96] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(192),
   },
   {
     /* [97] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [98] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [99] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [100] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(198),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [101] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(198),
   },
   {
     /* [102] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [103] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [104] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [105] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(192),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [106] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(192),
   },
   {
     /* [107] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [108] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [109] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [110] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(198),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [111] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(198),
   },
   {
     /* [112] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [113] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [114] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [115] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(200),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [116] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(200),
   },
   {
     /* [117] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [118] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [119] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [120] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(202),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [121] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(51),
+    /* matcher_indices */ MatcherIndicesIndex(202),
   },
   {
     /* [122] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(51),
   },
   {
     /* [123] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [124] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [125] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(86),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [126] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(24),
+    /* matcher_indices */ MatcherIndicesIndex(86),
   },
   {
     /* [127] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(127),
+    /* matcher_indices */ MatcherIndicesIndex(24),
   },
   {
     /* [128] */
@@ -2248,12 +2248,12 @@
   {
     /* [130] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(13),
+    /* matcher_indices */ MatcherIndicesIndex(127),
   },
   {
     /* [131] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(13),
   },
   {
     /* [132] */
@@ -2263,22 +2263,22 @@
   {
     /* [133] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [134] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(200),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [135] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(53),
   },
   {
     /* [136] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [137] */
@@ -2288,137 +2288,137 @@
   {
     /* [138] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(202),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [139] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(51),
+    /* matcher_indices */ MatcherIndicesIndex(200),
   },
   {
     /* [140] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [141] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [142] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(94),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [143] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(202),
   },
   {
     /* [144] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(51),
   },
   {
     /* [145] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(8),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [146] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(97),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [147] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(94),
   },
   {
     /* [148] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [149] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(8),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [150] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(100),
+    /* matcher_indices */ MatcherIndicesIndex(8),
   },
   {
     /* [151] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(206),
+    /* matcher_indices */ MatcherIndicesIndex(97),
   },
   {
     /* [152] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [153] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(8),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [154] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(103),
+    /* matcher_indices */ MatcherIndicesIndex(8),
   },
   {
     /* [155] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(206),
+    /* matcher_indices */ MatcherIndicesIndex(100),
   },
   {
     /* [156] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(206),
   },
   {
     /* [157] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(8),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [158] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(208),
+    /* matcher_indices */ MatcherIndicesIndex(8),
   },
   {
     /* [159] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(103),
   },
   {
     /* [160] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(206),
   },
   {
     /* [161] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(8),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [162] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(193),
+    /* matcher_indices */ MatcherIndicesIndex(8),
   },
   {
     /* [163] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(208),
   },
   {
     /* [164] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [165] */
@@ -2428,312 +2428,312 @@
   {
     /* [166] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(199),
+    /* matcher_indices */ MatcherIndicesIndex(8),
   },
   {
     /* [167] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(206),
+    /* matcher_indices */ MatcherIndicesIndex(193),
   },
   {
     /* [168] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [169] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [170] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(237),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [171] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(199),
   },
   {
     /* [172] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(206),
   },
   {
     /* [173] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [174] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(93),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [175] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(237),
   },
   {
     /* [176] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [177] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [178] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(102),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [179] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(93),
   },
   {
     /* [180] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [181] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [182] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(105),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [183] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(102),
   },
   {
     /* [184] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [185] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [186] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(108),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [187] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(51),
+    /* matcher_indices */ MatcherIndicesIndex(105),
   },
   {
     /* [188] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [189] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [190] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(96),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [191] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(108),
   },
   {
     /* [192] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(51),
   },
   {
     /* [193] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(196),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [194] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(99),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [195] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(96),
   },
   {
     /* [196] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [197] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(196),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [198] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(102),
+    /* matcher_indices */ MatcherIndicesIndex(196),
   },
   {
     /* [199] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(99),
   },
   {
     /* [200] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [201] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(222),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [202] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(105),
+    /* matcher_indices */ MatcherIndicesIndex(196),
   },
   {
     /* [203] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(102),
   },
   {
     /* [204] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [205] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [206] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(108),
+    /* matcher_indices */ MatcherIndicesIndex(222),
   },
   {
     /* [207] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(51),
+    /* matcher_indices */ MatcherIndicesIndex(105),
   },
   {
     /* [208] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [209] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [210] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(192),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [211] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(194),
+    /* matcher_indices */ MatcherIndicesIndex(108),
   },
   {
     /* [212] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(51),
   },
   {
     /* [213] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [214] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(198),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [215] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(192),
   },
   {
     /* [216] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(194),
   },
   {
     /* [217] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [218] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(200),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [219] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(17),
+    /* matcher_indices */ MatcherIndicesIndex(198),
   },
   {
     /* [220] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [221] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [222] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(202),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [223] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(51),
+    /* matcher_indices */ MatcherIndicesIndex(200),
   },
   {
     /* [224] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(17),
   },
   {
     /* [225] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [226] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(123),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [227] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(202),
   },
   {
     /* [228] */
@@ -2743,302 +2743,302 @@
   {
     /* [229] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [230] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(126),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [231] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(123),
   },
   {
     /* [232] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(218),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [233] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(51),
   },
   {
     /* [234] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(129),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [235] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(126),
   },
   {
     /* [236] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(220),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [237] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(218),
   },
   {
     /* [238] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(132),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [239] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(226),
+    /* matcher_indices */ MatcherIndicesIndex(129),
   },
   {
     /* [240] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(51),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [241] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(220),
   },
   {
     /* [242] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(135),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [243] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(226),
+    /* matcher_indices */ MatcherIndicesIndex(132),
   },
   {
     /* [244] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(218),
+    /* matcher_indices */ MatcherIndicesIndex(226),
   },
   {
     /* [245] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(51),
   },
   {
     /* [246] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(138),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [247] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(226),
+    /* matcher_indices */ MatcherIndicesIndex(135),
   },
   {
     /* [248] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(220),
+    /* matcher_indices */ MatcherIndicesIndex(226),
   },
   {
     /* [249] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(218),
   },
   {
     /* [250] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(141),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [251] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(228),
+    /* matcher_indices */ MatcherIndicesIndex(138),
   },
   {
     /* [252] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(51),
+    /* matcher_indices */ MatcherIndicesIndex(226),
   },
   {
     /* [253] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(220),
   },
   {
     /* [254] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(144),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [255] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(228),
+    /* matcher_indices */ MatcherIndicesIndex(141),
   },
   {
     /* [256] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(218),
+    /* matcher_indices */ MatcherIndicesIndex(228),
   },
   {
     /* [257] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(51),
   },
   {
     /* [258] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(147),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [259] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(228),
+    /* matcher_indices */ MatcherIndicesIndex(144),
   },
   {
     /* [260] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(220),
+    /* matcher_indices */ MatcherIndicesIndex(228),
   },
   {
     /* [261] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(218),
   },
   {
     /* [262] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(150),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [263] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(228),
+    /* matcher_indices */ MatcherIndicesIndex(147),
   },
   {
     /* [264] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(51),
+    /* matcher_indices */ MatcherIndicesIndex(228),
   },
   {
     /* [265] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(220),
   },
   {
     /* [266] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(153),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [267] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(228),
+    /* matcher_indices */ MatcherIndicesIndex(150),
   },
   {
     /* [268] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(218),
+    /* matcher_indices */ MatcherIndicesIndex(228),
   },
   {
     /* [269] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(51),
   },
   {
     /* [270] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(156),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [271] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(228),
+    /* matcher_indices */ MatcherIndicesIndex(153),
   },
   {
     /* [272] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(220),
+    /* matcher_indices */ MatcherIndicesIndex(228),
   },
   {
     /* [273] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(218),
   },
   {
     /* [274] */
-    /* usage */ core::ParameterUsage::kBase,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [275] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(156),
+  },
+  {
+    /* [276] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(228),
+  },
+  {
+    /* [277] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(220),
+  },
+  {
+    /* [278] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(3),
+  },
+  {
+    /* [279] */
+    /* usage */ core::ParameterUsage::kBase,
+    /* matcher_indices */ MatcherIndicesIndex(4),
+  },
+  {
+    /* [280] */
     /* usage */ core::ParameterUsage::kInsert,
     /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
-    /* [276] */
-    /* usage */ core::ParameterUsage::kOffset,
-    /* matcher_indices */ MatcherIndicesIndex(234),
-  },
-  {
-    /* [277] */
-    /* usage */ core::ParameterUsage::kCount,
-    /* matcher_indices */ MatcherIndicesIndex(234),
-  },
-  {
-    /* [278] */
-    /* usage */ core::ParameterUsage::kBase,
-    /* matcher_indices */ MatcherIndicesIndex(2),
-  },
-  {
-    /* [279] */
-    /* usage */ core::ParameterUsage::kInsert,
-    /* matcher_indices */ MatcherIndicesIndex(2),
-  },
-  {
-    /* [280] */
-    /* usage */ core::ParameterUsage::kOffset,
-    /* matcher_indices */ MatcherIndicesIndex(234),
-  },
-  {
     /* [281] */
-    /* usage */ core::ParameterUsage::kCount,
+    /* usage */ core::ParameterUsage::kOffset,
     /* matcher_indices */ MatcherIndicesIndex(234),
   },
   {
     /* [282] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(81),
+    /* usage */ core::ParameterUsage::kCount,
+    /* matcher_indices */ MatcherIndicesIndex(234),
   },
   {
     /* [283] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(127),
+    /* usage */ core::ParameterUsage::kBase,
+    /* matcher_indices */ MatcherIndicesIndex(2),
   },
   {
     /* [284] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(127),
+    /* usage */ core::ParameterUsage::kInsert,
+    /* matcher_indices */ MatcherIndicesIndex(2),
   },
   {
     /* [285] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(127),
+    /* usage */ core::ParameterUsage::kOffset,
+    /* matcher_indices */ MatcherIndicesIndex(234),
   },
   {
     /* [286] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(34),
+    /* usage */ core::ParameterUsage::kCount,
+    /* matcher_indices */ MatcherIndicesIndex(234),
   },
   {
     /* [287] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(39),
+    /* matcher_indices */ MatcherIndicesIndex(81),
   },
   {
     /* [288] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(29),
+    /* matcher_indices */ MatcherIndicesIndex(127),
   },
   {
     /* [289] */
@@ -3048,167 +3048,167 @@
   {
     /* [290] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(48),
+    /* matcher_indices */ MatcherIndicesIndex(127),
   },
   {
     /* [291] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(34),
   },
   {
     /* [292] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(39),
   },
   {
     /* [293] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(111),
+    /* matcher_indices */ MatcherIndicesIndex(29),
   },
   {
     /* [294] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(1),
+    /* matcher_indices */ MatcherIndicesIndex(127),
   },
   {
     /* [295] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(8),
+    /* matcher_indices */ MatcherIndicesIndex(48),
   },
   {
     /* [296] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(114),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [297] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(196),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [298] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(8),
+    /* matcher_indices */ MatcherIndicesIndex(111),
   },
   {
     /* [299] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(117),
+    /* matcher_indices */ MatcherIndicesIndex(1),
   },
   {
     /* [300] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(222),
+    /* matcher_indices */ MatcherIndicesIndex(8),
   },
   {
     /* [301] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(8),
+    /* matcher_indices */ MatcherIndicesIndex(114),
   },
   {
     /* [302] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(120),
+    /* matcher_indices */ MatcherIndicesIndex(196),
   },
   {
     /* [303] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(222),
+    /* matcher_indices */ MatcherIndicesIndex(8),
   },
   {
     /* [304] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(8),
+    /* matcher_indices */ MatcherIndicesIndex(117),
   },
   {
     /* [305] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(93),
+    /* matcher_indices */ MatcherIndicesIndex(222),
   },
   {
     /* [306] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(18),
+    /* matcher_indices */ MatcherIndicesIndex(8),
   },
   {
     /* [307] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
+    /* matcher_indices */ MatcherIndicesIndex(120),
   },
   {
     /* [308] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(45),
+    /* matcher_indices */ MatcherIndicesIndex(222),
   },
   {
     /* [309] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(8),
   },
   {
     /* [310] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(93),
   },
   {
     /* [311] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(162),
+    /* matcher_indices */ MatcherIndicesIndex(18),
   },
   {
     /* [312] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(90),
+    /* matcher_indices */ MatcherIndicesIndex(3),
   },
   {
     /* [313] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(90),
+    /* matcher_indices */ MatcherIndicesIndex(45),
   },
   {
     /* [314] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(186),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [315] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(177),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [316] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(180),
+    /* matcher_indices */ MatcherIndicesIndex(162),
   },
   {
     /* [317] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(183),
+    /* matcher_indices */ MatcherIndicesIndex(90),
   },
   {
     /* [318] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(2),
+    /* matcher_indices */ MatcherIndicesIndex(90),
   },
   {
     /* [319] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(2),
+    /* matcher_indices */ MatcherIndicesIndex(186),
   },
   {
     /* [320] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* matcher_indices */ MatcherIndicesIndex(177),
   },
   {
     /* [321] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(2),
+    /* matcher_indices */ MatcherIndicesIndex(180),
   },
   {
     /* [322] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(2),
+    /* matcher_indices */ MatcherIndicesIndex(183),
   },
   {
     /* [323] */
@@ -3218,250 +3218,275 @@
   {
     /* [324] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(65),
+    /* matcher_indices */ MatcherIndicesIndex(2),
   },
   {
     /* [325] */
-    /* usage */ core::ParameterUsage::kBase,
+    /* usage */ core::ParameterUsage::kNone,
     /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [326] */
-    /* usage */ core::ParameterUsage::kOffset,
-    /* matcher_indices */ MatcherIndicesIndex(234),
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(2),
   },
   {
     /* [327] */
-    /* usage */ core::ParameterUsage::kCount,
-    /* matcher_indices */ MatcherIndicesIndex(234),
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(2),
   },
   {
     /* [328] */
-    /* usage */ core::ParameterUsage::kBase,
+    /* usage */ core::ParameterUsage::kNone,
     /* matcher_indices */ MatcherIndicesIndex(2),
   },
   {
     /* [329] */
-    /* usage */ core::ParameterUsage::kOffset,
-    /* matcher_indices */ MatcherIndicesIndex(234),
-  },
-  {
-    /* [330] */
-    /* usage */ core::ParameterUsage::kCount,
-    /* matcher_indices */ MatcherIndicesIndex(234),
-  },
-  {
-    /* [331] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(44),
-  },
-  {
-    /* [332] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
-  },
-  {
-    /* [333] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(97),
-  },
-  {
-    /* [334] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
-  },
-  {
-    /* [335] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(100),
-  },
-  {
-    /* [336] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
-  },
-  {
-    /* [337] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(103),
-  },
-  {
-    /* [338] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
-  },
-  {
-    /* [339] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(106),
-  },
-  {
-    /* [340] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
-  },
-  {
-    /* [341] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(109),
-  },
-  {
-    /* [342] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(3),
-  },
-  {
-    /* [343] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(193),
-  },
-  {
-    /* [344] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
-  },
-  {
-    /* [345] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(199),
-  },
-  {
-    /* [346] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
-  },
-  {
-    /* [347] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(201),
-  },
-  {
-    /* [348] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
-  },
-  {
-    /* [349] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(203),
-  },
-  {
-    /* [350] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
-  },
-  {
-    /* [351] */
-    /* usage */ core::ParameterUsage::kInputAttachment,
-    /* matcher_indices */ MatcherIndicesIndex(224),
-  },
-  {
-    /* [352] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(204),
-  },
-  {
-    /* [353] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(61),
-  },
-  {
-    /* [354] */
     /* usage */ core::ParameterUsage::kNone,
     /* matcher_indices */ MatcherIndicesIndex(65),
   },
   {
+    /* [330] */
+    /* usage */ core::ParameterUsage::kBase,
+    /* matcher_indices */ MatcherIndicesIndex(4),
+  },
+  {
+    /* [331] */
+    /* usage */ core::ParameterUsage::kOffset,
+    /* matcher_indices */ MatcherIndicesIndex(234),
+  },
+  {
+    /* [332] */
+    /* usage */ core::ParameterUsage::kCount,
+    /* matcher_indices */ MatcherIndicesIndex(234),
+  },
+  {
+    /* [333] */
+    /* usage */ core::ParameterUsage::kBase,
+    /* matcher_indices */ MatcherIndicesIndex(2),
+  },
+  {
+    /* [334] */
+    /* usage */ core::ParameterUsage::kOffset,
+    /* matcher_indices */ MatcherIndicesIndex(234),
+  },
+  {
+    /* [335] */
+    /* usage */ core::ParameterUsage::kCount,
+    /* matcher_indices */ MatcherIndicesIndex(234),
+  },
+  {
+    /* [336] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(44),
+  },
+  {
+    /* [337] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(4),
+  },
+  {
+    /* [338] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(97),
+  },
+  {
+    /* [339] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(3),
+  },
+  {
+    /* [340] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(100),
+  },
+  {
+    /* [341] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(3),
+  },
+  {
+    /* [342] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(103),
+  },
+  {
+    /* [343] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(3),
+  },
+  {
+    /* [344] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(106),
+  },
+  {
+    /* [345] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(3),
+  },
+  {
+    /* [346] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(109),
+  },
+  {
+    /* [347] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(3),
+  },
+  {
+    /* [348] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(193),
+  },
+  {
+    /* [349] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(4),
+  },
+  {
+    /* [350] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(199),
+  },
+  {
+    /* [351] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(4),
+  },
+  {
+    /* [352] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(201),
+  },
+  {
+    /* [353] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(4),
+  },
+  {
+    /* [354] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(203),
+  },
+  {
     /* [355] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(69),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [356] */
-    /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(4),
+    /* usage */ core::ParameterUsage::kInputAttachment,
+    /* matcher_indices */ MatcherIndicesIndex(224),
   },
   {
     /* [357] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(69),
+    /* matcher_indices */ MatcherIndicesIndex(204),
   },
   {
     /* [358] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(2),
+    /* matcher_indices */ MatcherIndicesIndex(61),
   },
   {
     /* [359] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(159),
+    /* matcher_indices */ MatcherIndicesIndex(65),
   },
   {
     /* [360] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(9),
+    /* matcher_indices */ MatcherIndicesIndex(69),
   },
   {
     /* [361] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(168),
+    /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
     /* [362] */
     /* usage */ core::ParameterUsage::kNone,
-    /* matcher_indices */ MatcherIndicesIndex(171),
+    /* matcher_indices */ MatcherIndicesIndex(69),
   },
   {
     /* [363] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(2),
+  },
+  {
+    /* [364] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(159),
+  },
+  {
+    /* [365] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(9),
+  },
+  {
+    /* [366] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(168),
+  },
+  {
+    /* [367] */
+    /* usage */ core::ParameterUsage::kNone,
+    /* matcher_indices */ MatcherIndicesIndex(171),
+  },
+  {
+    /* [368] */
     /* usage */ core::ParameterUsage::kX,
     /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
-    /* [364] */
+    /* [369] */
     /* usage */ core::ParameterUsage::kI,
     /* matcher_indices */ MatcherIndicesIndex(73),
   },
   {
-    /* [365] */
+    /* [370] */
     /* usage */ core::ParameterUsage::kX,
     /* matcher_indices */ MatcherIndicesIndex(2),
   },
   {
-    /* [366] */
+    /* [371] */
     /* usage */ core::ParameterUsage::kI,
     /* matcher_indices */ MatcherIndicesIndex(0),
   },
   {
-    /* [367] */
+    /* [372] */
     /* usage */ core::ParameterUsage::kX,
     /* matcher_indices */ MatcherIndicesIndex(4),
   },
   {
-    /* [368] */
+    /* [373] */
     /* usage */ core::ParameterUsage::kI,
     /* matcher_indices */ MatcherIndicesIndex(77),
   },
   {
-    /* [369] */
+    /* [374] */
     /* usage */ core::ParameterUsage::kX,
     /* matcher_indices */ MatcherIndicesIndex(159),
   },
   {
-    /* [370] */
+    /* [375] */
     /* usage */ core::ParameterUsage::kI,
     /* matcher_indices */ MatcherIndicesIndex(7),
   },
   {
-    /* [371] */
+    /* [376] */
     /* usage */ core::ParameterUsage::kNone,
     /* matcher_indices */ MatcherIndicesIndex(5),
   },
   {
-    /* [372] */
+    /* [377] */
     /* usage */ core::ParameterUsage::kNone,
     /* matcher_indices */ MatcherIndicesIndex(230),
   },
   {
-    /* [373] */
+    /* [378] */
     /* usage */ core::ParameterUsage::kNone,
     /* matcher_indices */ MatcherIndicesIndex(232),
   },
@@ -4060,7 +4085,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(305),
+    /* parameters */ ParameterIndex(310),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4071,7 +4096,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(10),
+    /* parameters */ ParameterIndex(16),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4082,7 +4107,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(65),
+    /* parameters */ ParameterIndex(66),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4093,7 +4118,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(65),
+    /* parameters */ ParameterIndex(66),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4104,7 +4129,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(190),
+    /* parameters */ ParameterIndex(195),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4115,7 +4140,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(16),
+    /* parameters */ ParameterIndex(22),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4126,7 +4151,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(70),
+    /* parameters */ ParameterIndex(71),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4137,7 +4162,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(194),
+    /* parameters */ ParameterIndex(199),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4148,7 +4173,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(70),
+    /* parameters */ ParameterIndex(71),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4159,7 +4184,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(22),
+    /* parameters */ ParameterIndex(28),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4170,7 +4195,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(75),
+    /* parameters */ ParameterIndex(76),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4181,7 +4206,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(75),
+    /* parameters */ ParameterIndex(76),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4192,7 +4217,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(198),
+    /* parameters */ ParameterIndex(203),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4203,7 +4228,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(85),
+    /* parameters */ ParameterIndex(86),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4214,7 +4239,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(202),
+    /* parameters */ ParameterIndex(207),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4225,7 +4250,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(90),
+    /* parameters */ ParameterIndex(91),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4236,7 +4261,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(206),
+    /* parameters */ ParameterIndex(211),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4247,7 +4272,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(45),
+    /* parameters */ ParameterIndex(46),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4258,7 +4283,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(210),
+    /* parameters */ ParameterIndex(215),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4269,7 +4294,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(134),
+    /* parameters */ ParameterIndex(139),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4280,7 +4305,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(50),
+    /* parameters */ ParameterIndex(51),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4291,7 +4316,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(214),
+    /* parameters */ ParameterIndex(219),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4302,7 +4327,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(138),
+    /* parameters */ ParameterIndex(143),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4313,7 +4338,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(65),
+    /* parameters */ ParameterIndex(66),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4324,7 +4349,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(10),
+    /* parameters */ ParameterIndex(16),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4335,7 +4360,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(65),
+    /* parameters */ ParameterIndex(66),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4346,7 +4371,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(80),
+    /* parameters */ ParameterIndex(81),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4357,7 +4382,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(10),
+    /* parameters */ ParameterIndex(16),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4368,7 +4393,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(70),
+    /* parameters */ ParameterIndex(71),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4379,7 +4404,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(16),
+    /* parameters */ ParameterIndex(22),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4390,7 +4415,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(70),
+    /* parameters */ ParameterIndex(71),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4401,7 +4426,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(16),
+    /* parameters */ ParameterIndex(22),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4412,7 +4437,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(75),
+    /* parameters */ ParameterIndex(76),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4423,7 +4448,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(22),
+    /* parameters */ ParameterIndex(28),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4434,7 +4459,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(75),
+    /* parameters */ ParameterIndex(76),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4445,7 +4470,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(64),
-    /* parameters */ ParameterIndex(22),
+    /* parameters */ ParameterIndex(28),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4456,7 +4481,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(202),
+    /* parameters */ ParameterIndex(207),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4467,7 +4492,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(85),
+    /* parameters */ ParameterIndex(86),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4478,7 +4503,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(206),
+    /* parameters */ ParameterIndex(211),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4489,7 +4514,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(90),
+    /* parameters */ ParameterIndex(91),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4500,7 +4525,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(95),
+    /* parameters */ ParameterIndex(96),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4511,7 +4536,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(95),
+    /* parameters */ ParameterIndex(96),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4522,7 +4547,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(100),
+    /* parameters */ ParameterIndex(101),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4533,7 +4558,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(100),
+    /* parameters */ ParameterIndex(101),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4544,7 +4569,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(218),
+    /* parameters */ ParameterIndex(223),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4555,7 +4580,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(222),
+    /* parameters */ ParameterIndex(227),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4566,7 +4591,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(142),
+    /* parameters */ ParameterIndex(147),
     /* return_matcher_indices */ MatcherIndicesIndex(127),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4577,7 +4602,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(146),
+    /* parameters */ ParameterIndex(151),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4588,7 +4613,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(150),
+    /* parameters */ ParameterIndex(155),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4599,7 +4624,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(154),
+    /* parameters */ ParameterIndex(159),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4610,7 +4635,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(339),
+    /* parameters */ ParameterIndex(344),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4621,7 +4646,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(341),
+    /* parameters */ ParameterIndex(346),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4632,7 +4657,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(158),
+    /* parameters */ ParameterIndex(163),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4643,7 +4668,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 0,
     /* templates */ TemplateIndex(/* invalid */),
-    /* parameters */ ParameterIndex(162),
+    /* parameters */ ParameterIndex(167),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4654,7 +4679,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 0,
     /* templates */ TemplateIndex(/* invalid */),
-    /* parameters */ ParameterIndex(166),
+    /* parameters */ ParameterIndex(171),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4665,7 +4690,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 0,
     /* templates */ TemplateIndex(/* invalid */),
-    /* parameters */ ParameterIndex(347),
+    /* parameters */ ParameterIndex(352),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4676,7 +4701,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 0,
     /* templates */ TemplateIndex(/* invalid */),
-    /* parameters */ ParameterIndex(349),
+    /* parameters */ ParameterIndex(354),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4687,7 +4712,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 0,
     /* templates */ TemplateIndex(/* invalid */),
-    /* parameters */ ParameterIndex(170),
+    /* parameters */ ParameterIndex(175),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4698,7 +4723,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(90),
-    /* parameters */ ParameterIndex(293),
+    /* parameters */ ParameterIndex(298),
     /* return_matcher_indices */ MatcherIndicesIndex(127),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4709,7 +4734,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(90),
-    /* parameters */ ParameterIndex(296),
+    /* parameters */ ParameterIndex(301),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4720,7 +4745,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(90),
-    /* parameters */ ParameterIndex(299),
+    /* parameters */ ParameterIndex(304),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4731,7 +4756,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(90),
-    /* parameters */ ParameterIndex(302),
+    /* parameters */ ParameterIndex(307),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4742,7 +4767,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(174),
+    /* parameters */ ParameterIndex(179),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4753,7 +4778,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(55),
+    /* parameters */ ParameterIndex(56),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4764,7 +4789,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(55),
+    /* parameters */ ParameterIndex(56),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4775,7 +4800,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(60),
+    /* parameters */ ParameterIndex(61),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4786,7 +4811,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(60),
+    /* parameters */ ParameterIndex(61),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4797,7 +4822,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(178),
+    /* parameters */ ParameterIndex(183),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4808,7 +4833,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(182),
+    /* parameters */ ParameterIndex(187),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4819,7 +4844,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(186),
+    /* parameters */ ParameterIndex(191),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4830,7 +4855,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(22),
-    /* parameters */ ParameterIndex(45),
+    /* parameters */ ParameterIndex(46),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4841,7 +4866,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(22),
-    /* parameters */ ParameterIndex(45),
+    /* parameters */ ParameterIndex(46),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4852,7 +4877,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(22),
-    /* parameters */ ParameterIndex(50),
+    /* parameters */ ParameterIndex(51),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4863,7 +4888,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(22),
-    /* parameters */ ParameterIndex(50),
+    /* parameters */ ParameterIndex(51),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4874,7 +4899,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(22),
-    /* parameters */ ParameterIndex(134),
+    /* parameters */ ParameterIndex(139),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4885,7 +4910,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(22),
-    /* parameters */ ParameterIndex(138),
+    /* parameters */ ParameterIndex(143),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4896,7 +4921,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(26),
-    /* parameters */ ParameterIndex(293),
+    /* parameters */ ParameterIndex(298),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4907,7 +4932,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(30),
-    /* parameters */ ParameterIndex(293),
+    /* parameters */ ParameterIndex(298),
     /* return_matcher_indices */ MatcherIndicesIndex(218),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4918,7 +4943,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(34),
-    /* parameters */ ParameterIndex(293),
+    /* parameters */ ParameterIndex(298),
     /* return_matcher_indices */ MatcherIndicesIndex(220),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4929,7 +4954,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(26),
-    /* parameters */ ParameterIndex(296),
+    /* parameters */ ParameterIndex(301),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4940,7 +4965,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(30),
-    /* parameters */ ParameterIndex(296),
+    /* parameters */ ParameterIndex(301),
     /* return_matcher_indices */ MatcherIndicesIndex(218),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4951,7 +4976,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(34),
-    /* parameters */ ParameterIndex(296),
+    /* parameters */ ParameterIndex(301),
     /* return_matcher_indices */ MatcherIndicesIndex(220),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4962,7 +4987,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(26),
-    /* parameters */ ParameterIndex(299),
+    /* parameters */ ParameterIndex(304),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4973,7 +4998,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(30),
-    /* parameters */ ParameterIndex(299),
+    /* parameters */ ParameterIndex(304),
     /* return_matcher_indices */ MatcherIndicesIndex(218),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4984,7 +5009,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(34),
-    /* parameters */ ParameterIndex(299),
+    /* parameters */ ParameterIndex(304),
     /* return_matcher_indices */ MatcherIndicesIndex(220),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -4995,7 +5020,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(26),
-    /* parameters */ ParameterIndex(302),
+    /* parameters */ ParameterIndex(307),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5006,7 +5031,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(30),
-    /* parameters */ ParameterIndex(302),
+    /* parameters */ ParameterIndex(307),
     /* return_matcher_indices */ MatcherIndicesIndex(218),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5017,7 +5042,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(34),
-    /* parameters */ ParameterIndex(302),
+    /* parameters */ ParameterIndex(307),
     /* return_matcher_indices */ MatcherIndicesIndex(220),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5028,7 +5053,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(351),
+    /* parameters */ ParameterIndex(356),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5039,7 +5064,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(226),
+    /* parameters */ ParameterIndex(231),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5050,7 +5075,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(230),
+    /* parameters */ ParameterIndex(235),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5061,7 +5086,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(234),
+    /* parameters */ ParameterIndex(239),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5072,7 +5097,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(238),
+    /* parameters */ ParameterIndex(243),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5083,7 +5108,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(242),
+    /* parameters */ ParameterIndex(247),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5094,7 +5119,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(246),
+    /* parameters */ ParameterIndex(251),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5105,7 +5130,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(250),
+    /* parameters */ ParameterIndex(255),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5116,7 +5141,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(254),
+    /* parameters */ ParameterIndex(259),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5127,7 +5152,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(258),
+    /* parameters */ ParameterIndex(263),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5138,7 +5163,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(262),
+    /* parameters */ ParameterIndex(267),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5149,7 +5174,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(266),
+    /* parameters */ ParameterIndex(271),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5160,7 +5185,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(270),
+    /* parameters */ ParameterIndex(275),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5171,7 +5196,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(142),
+    /* parameters */ ParameterIndex(147),
     /* return_matcher_indices */ MatcherIndicesIndex(127),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5182,7 +5207,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(333),
+    /* parameters */ ParameterIndex(338),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5193,7 +5218,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(335),
+    /* parameters */ ParameterIndex(340),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5204,7 +5229,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(337),
+    /* parameters */ ParameterIndex(342),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5215,7 +5240,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(339),
+    /* parameters */ ParameterIndex(344),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5226,7 +5251,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(21),
-    /* parameters */ ParameterIndex(341),
+    /* parameters */ ParameterIndex(346),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5237,7 +5262,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(22),
-    /* parameters */ ParameterIndex(343),
+    /* parameters */ ParameterIndex(348),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5248,7 +5273,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(22),
-    /* parameters */ ParameterIndex(345),
+    /* parameters */ ParameterIndex(350),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5259,7 +5284,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(22),
-    /* parameters */ ParameterIndex(347),
+    /* parameters */ ParameterIndex(352),
     /* return_matcher_indices */ MatcherIndicesIndex(214),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5270,7 +5295,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(22),
-    /* parameters */ ParameterIndex(349),
+    /* parameters */ ParameterIndex(354),
     /* return_matcher_indices */ MatcherIndicesIndex(216),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5281,7 +5306,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(92),
-    /* parameters */ ParameterIndex(142),
+    /* parameters */ ParameterIndex(147),
     /* return_matcher_indices */ MatcherIndicesIndex(93),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5292,7 +5317,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(92),
-    /* parameters */ ParameterIndex(333),
+    /* parameters */ ParameterIndex(338),
     /* return_matcher_indices */ MatcherIndicesIndex(96),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5303,7 +5328,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(92),
-    /* parameters */ ParameterIndex(335),
+    /* parameters */ ParameterIndex(340),
     /* return_matcher_indices */ MatcherIndicesIndex(99),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5314,7 +5339,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(92),
-    /* parameters */ ParameterIndex(337),
+    /* parameters */ ParameterIndex(342),
     /* return_matcher_indices */ MatcherIndicesIndex(102),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5325,7 +5350,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(92),
-    /* parameters */ ParameterIndex(339),
+    /* parameters */ ParameterIndex(344),
     /* return_matcher_indices */ MatcherIndicesIndex(105),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5336,7 +5361,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(92),
-    /* parameters */ ParameterIndex(341),
+    /* parameters */ ParameterIndex(346),
     /* return_matcher_indices */ MatcherIndicesIndex(108),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5347,7 +5372,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(93),
-    /* parameters */ ParameterIndex(343),
+    /* parameters */ ParameterIndex(348),
     /* return_matcher_indices */ MatcherIndicesIndex(192),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5358,7 +5383,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(93),
-    /* parameters */ ParameterIndex(345),
+    /* parameters */ ParameterIndex(350),
     /* return_matcher_indices */ MatcherIndicesIndex(198),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5369,7 +5394,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(93),
-    /* parameters */ ParameterIndex(347),
+    /* parameters */ ParameterIndex(352),
     /* return_matcher_indices */ MatcherIndicesIndex(200),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5380,7 +5405,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(93),
-    /* parameters */ ParameterIndex(349),
+    /* parameters */ ParameterIndex(354),
     /* return_matcher_indices */ MatcherIndicesIndex(202),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5391,7 +5416,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(142),
+    /* parameters */ ParameterIndex(147),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5402,7 +5427,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(146),
+    /* parameters */ ParameterIndex(151),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5413,7 +5438,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(150),
+    /* parameters */ ParameterIndex(155),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5424,7 +5449,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(154),
+    /* parameters */ ParameterIndex(159),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5435,7 +5460,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(17),
-    /* parameters */ ParameterIndex(158),
+    /* parameters */ ParameterIndex(163),
     /* return_matcher_indices */ MatcherIndicesIndex(84),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5446,7 +5471,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(61),
-    /* parameters */ ParameterIndex(162),
+    /* parameters */ ParameterIndex(167),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5457,7 +5482,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(61),
-    /* parameters */ ParameterIndex(166),
+    /* parameters */ ParameterIndex(171),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5468,7 +5493,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(61),
-    /* parameters */ ParameterIndex(170),
+    /* parameters */ ParameterIndex(175),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5479,7 +5504,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(58),
-    /* parameters */ ParameterIndex(45),
+    /* parameters */ ParameterIndex(46),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5490,7 +5515,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(58),
-    /* parameters */ ParameterIndex(45),
+    /* parameters */ ParameterIndex(46),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5501,7 +5526,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(58),
-    /* parameters */ ParameterIndex(50),
+    /* parameters */ ParameterIndex(51),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5512,7 +5537,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(58),
-    /* parameters */ ParameterIndex(50),
+    /* parameters */ ParameterIndex(51),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5523,7 +5548,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(58),
-    /* parameters */ ParameterIndex(134),
+    /* parameters */ ParameterIndex(139),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5534,7 +5559,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(58),
-    /* parameters */ ParameterIndex(138),
+    /* parameters */ ParameterIndex(143),
     /* return_matcher_indices */ MatcherIndicesIndex(51),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5545,7 +5570,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(28),
+    /* parameters */ ParameterIndex(34),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5556,7 +5581,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(105),
+    /* parameters */ ParameterIndex(106),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5567,7 +5592,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(34),
+    /* parameters */ ParameterIndex(40),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5578,7 +5603,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(110),
+    /* parameters */ ParameterIndex(111),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5589,7 +5614,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(115),
+    /* parameters */ ParameterIndex(116),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5600,7 +5625,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(120),
+    /* parameters */ ParameterIndex(121),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5611,7 +5636,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(28),
+    /* parameters */ ParameterIndex(34),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5622,7 +5647,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(28),
+    /* parameters */ ParameterIndex(34),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5633,7 +5658,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(34),
+    /* parameters */ ParameterIndex(40),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5644,7 +5669,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(24),
-    /* parameters */ ParameterIndex(34),
+    /* parameters */ ParameterIndex(40),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5655,7 +5680,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(115),
+    /* parameters */ ParameterIndex(116),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5666,7 +5691,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(18),
-    /* parameters */ ParameterIndex(120),
+    /* parameters */ ParameterIndex(121),
     /* return_matcher_indices */ MatcherIndicesIndex(18),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5677,7 +5702,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(5),
-    /* parameters */ ParameterIndex(371),
+    /* parameters */ ParameterIndex(376),
     /* return_matcher_indices */ MatcherIndicesIndex(5),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5688,7 +5713,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(5),
-    /* parameters */ ParameterIndex(372),
+    /* parameters */ ParameterIndex(377),
     /* return_matcher_indices */ MatcherIndicesIndex(230),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5699,7 +5724,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(5),
-    /* parameters */ ParameterIndex(373),
+    /* parameters */ ParameterIndex(378),
     /* return_matcher_indices */ MatcherIndicesIndex(232),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5721,7 +5746,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(55),
-    /* parameters */ ParameterIndex(290),
+    /* parameters */ ParameterIndex(295),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5732,7 +5757,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(55),
-    /* parameters */ ParameterIndex(130),
+    /* parameters */ ParameterIndex(131),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5743,7 +5768,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(55),
-    /* parameters */ ParameterIndex(40),
+    /* parameters */ ParameterIndex(135),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5754,7 +5779,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(55),
-    /* parameters */ ParameterIndex(130),
+    /* parameters */ ParameterIndex(131),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5765,7 +5790,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(55),
-    /* parameters */ ParameterIndex(40),
+    /* parameters */ ParameterIndex(135),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5783,11 +5808,11 @@
   {
     /* [157] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
-    /* num_parameters */ 5,
+    /* num_parameters */ 6,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(55),
-    /* parameters */ ParameterIndex(40),
+    /* parameters */ ParameterIndex(10),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5798,7 +5823,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(46),
-    /* parameters */ ParameterIndex(308),
+    /* parameters */ ParameterIndex(313),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5809,7 +5834,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(45),
-    /* parameters */ ParameterIndex(311),
+    /* parameters */ ParameterIndex(316),
     /* return_matcher_indices */ MatcherIndicesIndex(90),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5831,7 +5856,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(4),
-    /* parameters */ ParameterIndex(312),
+    /* parameters */ ParameterIndex(317),
     /* return_matcher_indices */ MatcherIndicesIndex(90),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5853,7 +5878,7 @@
     /* num_explicit_templates */ 1,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(70),
-    /* parameters */ ParameterIndex(360),
+    /* parameters */ ParameterIndex(365),
     /* return_matcher_indices */ MatcherIndicesIndex(159),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5875,7 +5900,7 @@
     /* num_explicit_templates */ 1,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(42),
-    /* parameters */ ParameterIndex(361),
+    /* parameters */ ParameterIndex(366),
     /* return_matcher_indices */ MatcherIndicesIndex(165),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5897,7 +5922,7 @@
     /* num_explicit_templates */ 1,
     /* num_templates   */ 5,
     /* templates */ TemplateIndex(0),
-    /* parameters */ ParameterIndex(315),
+    /* parameters */ ParameterIndex(320),
     /* return_matcher_indices */ MatcherIndicesIndex(174),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5919,7 +5944,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(67),
-    /* parameters */ ParameterIndex(318),
+    /* parameters */ ParameterIndex(323),
     /* return_matcher_indices */ MatcherIndicesIndex(2),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5941,7 +5966,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(67),
-    /* parameters */ ParameterIndex(318),
+    /* parameters */ ParameterIndex(323),
     /* return_matcher_indices */ MatcherIndicesIndex(2),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5963,7 +5988,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(67),
-    /* parameters */ ParameterIndex(321),
+    /* parameters */ ParameterIndex(326),
     /* return_matcher_indices */ MatcherIndicesIndex(2),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5985,7 +6010,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(4),
-    /* parameters */ ParameterIndex(313),
+    /* parameters */ ParameterIndex(318),
     /* return_matcher_indices */ MatcherIndicesIndex(90),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -5996,7 +6021,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(94),
-    /* parameters */ ParameterIndex(363),
+    /* parameters */ ParameterIndex(368),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6007,7 +6032,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(73),
-    /* parameters */ ParameterIndex(365),
+    /* parameters */ ParameterIndex(370),
     /* return_matcher_indices */ MatcherIndicesIndex(2),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6018,7 +6043,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(76),
-    /* parameters */ ParameterIndex(367),
+    /* parameters */ ParameterIndex(372),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6029,7 +6054,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(47),
-    /* parameters */ ParameterIndex(369),
+    /* parameters */ ParameterIndex(374),
     /* return_matcher_indices */ MatcherIndicesIndex(159),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6040,7 +6065,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(1),
-    /* parameters */ ParameterIndex(274),
+    /* parameters */ ParameterIndex(279),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6051,7 +6076,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(71),
-    /* parameters */ ParameterIndex(278),
+    /* parameters */ ParameterIndex(283),
     /* return_matcher_indices */ MatcherIndicesIndex(2),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6062,7 +6087,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
     /* templates */ TemplateIndex(1),
-    /* parameters */ ParameterIndex(325),
+    /* parameters */ ParameterIndex(330),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6073,7 +6098,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(71),
-    /* parameters */ ParameterIndex(328),
+    /* parameters */ ParameterIndex(333),
     /* return_matcher_indices */ MatcherIndicesIndex(2),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6095,7 +6120,7 @@
     /* num_explicit_templates */ 1,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(51),
-    /* parameters */ ParameterIndex(361),
+    /* parameters */ ParameterIndex(366),
     /* return_matcher_indices */ MatcherIndicesIndex(165),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6117,7 +6142,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(52),
-    /* parameters */ ParameterIndex(359),
+    /* parameters */ ParameterIndex(364),
     /* return_matcher_indices */ MatcherIndicesIndex(189),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6139,7 +6164,7 @@
     /* num_explicit_templates */ 1,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(79),
-    /* parameters */ ParameterIndex(360),
+    /* parameters */ ParameterIndex(365),
     /* return_matcher_indices */ MatcherIndicesIndex(159),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6161,7 +6186,7 @@
     /* num_explicit_templates */ 1,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(82),
-    /* parameters */ ParameterIndex(360),
+    /* parameters */ ParameterIndex(365),
     /* return_matcher_indices */ MatcherIndicesIndex(159),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6183,7 +6208,7 @@
     /* num_explicit_templates */ 1,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(85),
-    /* parameters */ ParameterIndex(360),
+    /* parameters */ ParameterIndex(365),
     /* return_matcher_indices */ MatcherIndicesIndex(159),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6194,7 +6219,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(88),
-    /* parameters */ ParameterIndex(331),
+    /* parameters */ ParameterIndex(336),
     /* return_matcher_indices */ MatcherIndicesIndex(127),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6205,7 +6230,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(55),
-    /* parameters */ ParameterIndex(40),
+    /* parameters */ ParameterIndex(10),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6216,7 +6241,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(4),
-    /* parameters */ ParameterIndex(312),
+    /* parameters */ ParameterIndex(317),
     /* return_matcher_indices */ MatcherIndicesIndex(3),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6227,7 +6252,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(38),
-    /* parameters */ ParameterIndex(353),
+    /* parameters */ ParameterIndex(358),
     /* return_matcher_indices */ MatcherIndicesIndex(57),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6238,7 +6263,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(67),
-    /* parameters */ ParameterIndex(355),
+    /* parameters */ ParameterIndex(360),
     /* return_matcher_indices */ MatcherIndicesIndex(69),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6249,7 +6274,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(67),
-    /* parameters */ ParameterIndex(357),
+    /* parameters */ ParameterIndex(362),
     /* return_matcher_indices */ MatcherIndicesIndex(159),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6260,7 +6285,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(67),
-    /* parameters */ ParameterIndex(323),
+    /* parameters */ ParameterIndex(328),
     /* return_matcher_indices */ MatcherIndicesIndex(159),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6271,7 +6296,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
     /* templates */ TemplateIndex(67),
-    /* parameters */ ParameterIndex(319),
+    /* parameters */ ParameterIndex(324),
     /* return_matcher_indices */ MatcherIndicesIndex(2),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6282,7 +6307,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 3,
     /* templates */ TemplateIndex(67),
-    /* parameters */ ParameterIndex(358),
+    /* parameters */ ParameterIndex(363),
     /* return_matcher_indices */ MatcherIndicesIndex(65),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6293,7 +6318,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 0,
     /* templates */ TemplateIndex(/* invalid */),
-    /* parameters */ ParameterIndex(127),
+    /* parameters */ ParameterIndex(128),
     /* return_matcher_indices */ MatcherIndicesIndex(124),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6304,7 +6329,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 0,
     /* templates */ TemplateIndex(/* invalid */),
-    /* parameters */ ParameterIndex(127),
+    /* parameters */ ParameterIndex(128),
     /* return_matcher_indices */ MatcherIndicesIndex(127),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6315,7 +6340,7 @@
     /* num_explicit_templates */ 1,
     /* num_templates   */ 5,
     /* templates */ TemplateIndex(7),
-    /* parameters */ ParameterIndex(282),
+    /* parameters */ ParameterIndex(287),
     /* return_matcher_indices */ MatcherIndicesIndex(4),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6326,7 +6351,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 4,
     /* templates */ TemplateIndex(8),
-    /* parameters */ ParameterIndex(125),
+    /* parameters */ ParameterIndex(126),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6337,7 +6362,7 @@
     /* num_explicit_templates */ 0,
     /* num_templates   */ 5,
     /* templates */ TemplateIndex(12),
-    /* parameters */ ParameterIndex(286),
+    /* parameters */ ParameterIndex(291),
     /* return_matcher_indices */ MatcherIndicesIndex(29),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
@@ -6377,7 +6402,7 @@
   {
     /* [4] */
     /* fn atomic_compare_exchange[T : iu32, U : u32, S : workgroup_or_storage](ptr<S, atomic<T>, read_write>, U, U, U, T, T) -> T */
-    /* fn atomic_compare_exchange[T : iu32, U : u32, S : workgroup_or_storage](ptr<S, T, writable>, U, U, T, T) -> T */
+    /* fn atomic_compare_exchange[T : iu32, U : u32, S : workgroup_or_storage](ptr<S, T, writable>, U, U, U, T, T) -> T */
     /* num overloads */ 2,
     /* overloads */ OverloadIndex(156),
   },
diff --git a/src/tint/lang/spirv/reader/lower/BUILD.bazel b/src/tint/lang/spirv/reader/lower/BUILD.bazel
index 217b833..6c481e8 100644
--- a/src/tint/lang/spirv/reader/lower/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/lower/BUILD.bazel
@@ -39,12 +39,14 @@
 cc_library(
   name = "lower",
   srcs = [
+    "atomics.cc",
     "builtins.cc",
     "lower.cc",
     "shader_io.cc",
     "vector_element_pointer.cc",
   ],
   hdrs = [
+    "atomics.h",
     "builtins.h",
     "lower.h",
     "shader_io.h",
@@ -80,6 +82,7 @@
   name = "test",
   alwayslink = True,
   srcs = [
+    "atomics_test.cc",
     "builtins_test.cc",
     "shader_io_test.cc",
     "vector_element_pointer_test.cc",
diff --git a/src/tint/lang/spirv/reader/lower/BUILD.cmake b/src/tint/lang/spirv/reader/lower/BUILD.cmake
index 2138699..f9bf58d 100644
--- a/src/tint/lang/spirv/reader/lower/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/lower/BUILD.cmake
@@ -39,6 +39,8 @@
 # Kind:      lib
 ################################################################################
 tint_add_target(tint_lang_spirv_reader_lower lib
+  lang/spirv/reader/lower/atomics.cc
+  lang/spirv/reader/lower/atomics.h
   lang/spirv/reader/lower/builtins.cc
   lang/spirv/reader/lower/builtins.h
   lang/spirv/reader/lower/lower.cc
@@ -81,6 +83,7 @@
 # Kind:      test
 ################################################################################
 tint_add_target(tint_lang_spirv_reader_lower_test test
+  lang/spirv/reader/lower/atomics_test.cc
   lang/spirv/reader/lower/builtins_test.cc
   lang/spirv/reader/lower/shader_io_test.cc
   lang/spirv/reader/lower/vector_element_pointer_test.cc
diff --git a/src/tint/lang/spirv/reader/lower/BUILD.gn b/src/tint/lang/spirv/reader/lower/BUILD.gn
index 3a039ca..e301b31 100644
--- a/src/tint/lang/spirv/reader/lower/BUILD.gn
+++ b/src/tint/lang/spirv/reader/lower/BUILD.gn
@@ -45,6 +45,8 @@
 
 libtint_source_set("lower") {
   sources = [
+    "atomics.cc",
+    "atomics.h",
     "builtins.cc",
     "builtins.h",
     "lower.cc",
@@ -81,6 +83,7 @@
 if (tint_build_unittests) {
   tint_unittests_source_set("unittests") {
     sources = [
+      "atomics_test.cc",
       "builtins_test.cc",
       "shader_io_test.cc",
       "vector_element_pointer_test.cc",
diff --git a/src/tint/lang/spirv/reader/lower/atomics.cc b/src/tint/lang/spirv/reader/lower/atomics.cc
new file mode 100644
index 0000000..c8dbe9c
--- /dev/null
+++ b/src/tint/lang/spirv/reader/lower/atomics.cc
@@ -0,0 +1,71 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/spirv/reader/lower/atomics.h"
+
+#include "src/tint/lang/core/ir/builder.h"
+#include "src/tint/lang/core/ir/module.h"
+#include "src/tint/lang/core/ir/validator.h"
+
+namespace tint::spirv::reader::lower {
+namespace {
+
+using namespace tint::core::fluent_types;     // NOLINT
+using namespace tint::core::number_suffixes;  // NOLINT
+
+/// PIMPL state for the transform.
+struct State {
+    /// The IR module.
+    core::ir::Module& ir;
+
+    /// The IR builder.
+    core::ir::Builder b{ir};
+
+    /// The type manager.
+    core::type::Manager& ty{ir.Types()};
+
+    /// Process the module.
+    void Process() {}
+};
+
+}  // namespace
+
+Result<SuccessType> Atomics(core::ir::Module& ir) {
+    auto result = ValidateAndDumpIfNeeded(ir, "spirv.Atomics",
+                                          core::ir::Capabilities{
+                                              core::ir::Capability::kAllowOverrides,
+                                          });
+    if (result != Success) {
+        return result.Failure();
+    }
+
+    State{ir}.Process();
+
+    return Success;
+}
+
+}  // namespace tint::spirv::reader::lower
diff --git a/src/tint/lang/spirv/reader/lower/atomics.h b/src/tint/lang/spirv/reader/lower/atomics.h
new file mode 100644
index 0000000..ee21c99
--- /dev/null
+++ b/src/tint/lang/spirv/reader/lower/atomics.h
@@ -0,0 +1,48 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_LANG_SPIRV_READER_LOWER_ATOMICS_H_
+#define SRC_TINT_LANG_SPIRV_READER_LOWER_ATOMICS_H_
+
+#include "src/tint/utils/result.h"
+
+// Forward declarations.
+namespace tint::core::ir {
+class Module;
+}
+
+namespace tint::spirv::reader::lower {
+
+/// Atomics is a transform that converts SPIR-V atomic methods into the form expected by Tint's
+/// core IR.
+/// @param module the module to transform
+/// @returns success or failure
+Result<SuccessType> Atomics(core::ir::Module& module);
+
+}  // namespace tint::spirv::reader::lower
+
+#endif  // SRC_TINT_LANG_SPIRV_READER_LOWER_ATOMICS_H_
diff --git a/src/tint/lang/spirv/reader/lower/atomics_test.cc b/src/tint/lang/spirv/reader/lower/atomics_test.cc
new file mode 100644
index 0000000..5450a7e
--- /dev/null
+++ b/src/tint/lang/spirv/reader/lower/atomics_test.cc
@@ -0,0 +1,1962 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/spirv/reader/lower/atomics.h"
+
+#include "src/tint/lang/core/ir/transform/helper_test.h"
+#include "src/tint/lang/spirv/ir/builtin_call.h"
+
+namespace tint::spirv::reader::lower {
+namespace {
+
+using namespace tint::core::fluent_types;     // NOLINT
+using namespace tint::core::number_suffixes;  // NOLINT
+
+using SpirvReader_AtomicsTest = core::ir::transform::TransformTest;
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ArrayStore) {
+    auto* f = b.ComputeFunction("main");
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block,
+             [&] { wg = b.Var("wg", ty.ptr<workgroup, array<u32, 4>, read_write>()); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a, 1_u, 0_u,
+                                       0_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+$B1: {  # root
+  %wg:ptr<workgroup, array<u32, 4>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, u32, read_write> = access %wg, 1i
+    %4:void = spirv.atomic_store %3, 1u, 0u, 0u
+    ret
+  }
+}
+)";
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ArrayStore_CopiedObject) {
+    auto* f = b.ComputeFunction("main");
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block,
+             [&] { wg = b.Var("wg", ty.ptr<workgroup, array<u32, 4>, read_write>()); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* l = b.Let(wg);
+        auto* a = b.Access(ty.ptr<workgroup, u32, read_write>(), l, 1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a, 1_u, 0_u,
+                                       2_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+$B1: {  # root
+  %wg:ptr<workgroup, array<u32, 4>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, array<u32, 4>, read_write> = let %wg
+    %4:ptr<workgroup, u32, read_write> = access %3, 1i
+    %5:void = spirv.atomic_store %4, 1u, 0u, 2u
+    ret
+  }
+}
+)";
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ArrayNested) {
+    auto* f = b.ComputeFunction("main");
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] {
+        wg = b.Var("wg", ty.ptr<workgroup, array<array<array<u32, 1>, 2>, 3>, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 2_i, 1_i, 0_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a, 2_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+    auto* src = R"(
+$B1: {  # root
+  %wg:ptr<workgroup, array<array<array<u32, 1>, 2>, 3>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, u32, read_write> = access %wg, 2i, 1i, 0i
+    %4:void = spirv.atomic_store %3, 2u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_FlatSingleAtomic) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("x"), ty.i32()},
+                                                   {mod.symbols.New("a"), ty.u32()},
+                                                   {mod.symbols.New("y"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] { wg = b.Var("wg", ty.ptr(workgroup, sb, read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<workgroup, i32, read_write>(), wg, 0_u);
+        b.Store(a0, 0_i);
+        auto* a1 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a1, 2_u, 0_u,
+                                       0_u);
+        auto* a2 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 2_u);
+        b.Store(a2, 0_u);
+        b.Return(f);
+    });
+    auto* src = R"(
+S = struct @align(4) {
+  x:i32 @offset(0)
+  a:u32 @offset(4)
+  y:u32 @offset(8)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, i32, read_write> = access %wg, 0u
+    store %3, 0i
+    %4:ptr<workgroup, u32, read_write> = access %wg, 1u
+    %5:void = spirv.atomic_store %4, 2u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 2u
+    store %6, 0u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_FlatMultipleAtomics) {
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("x"), ty.i32()},
+                                                   {mod.symbols.New("a"), ty.u32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] { wg = b.Var("wg", ty.ptr(workgroup, sb, read_write)); });
+
+    auto* f = b.ComputeFunction("main");
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<workgroup, i32, read_write>(), wg, 0_u);
+        b.Store(a0, 0_i);
+        auto* a1 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a1, 2_u, 0_u,
+                                       0_u);
+        auto* a2 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 2_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a2, 2_u, 0_u,
+                                       0_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  x:i32 @offset(0)
+  a:u32 @offset(4)
+  b:u32 @offset(8)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, i32, read_write> = access %wg, 0u
+    store %3, 0i
+    %4:ptr<workgroup, u32, read_write> = access %wg, 1u
+    %5:void = spirv.atomic_store %4, 2u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 2u
+    %7:void = spirv.atomic_store %6, 2u, 0u, 0u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_Nested) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* s0 = ty.Struct(mod.symbols.New("S0"), {
+                                                    {mod.symbols.New("x"), ty.i32()},
+                                                    {mod.symbols.New("a"), ty.u32()},
+                                                    {mod.symbols.New("y"), ty.i32()},
+                                                    {mod.symbols.New("z"), ty.i32()},
+                                                });
+    auto* s1 = ty.Struct(mod.symbols.New("S1"), {
+                                                    {mod.symbols.New("x"), ty.i32()},
+                                                    {mod.symbols.New("a"), s0},
+                                                    {mod.symbols.New("y"), ty.i32()},
+                                                    {mod.symbols.New("z"), ty.i32()},
+                                                });
+    auto* s2 = ty.Struct(mod.symbols.New("S2"), {
+                                                    {mod.symbols.New("x"), ty.i32()},
+                                                    {mod.symbols.New("y"), ty.i32()},
+                                                    {mod.symbols.New("z"), ty.i32()},
+                                                    {mod.symbols.New("a"), s1},
+                                                });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] { wg = b.Var("wg", ty.ptr(workgroup, s2, read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<workgroup, i32, read_write>(), wg, 3_u, 1_u, 0_u);
+        b.Store(a0, 0_i);
+
+        auto* a1 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 3_u, 1_u, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a1, 2_u, 0_u,
+                                       0_u);
+
+        auto* a2 = b.Access(ty.ptr<workgroup, i32, read_write>(), wg, 3_u, 1_u, 2_u);
+        b.Store(a2, 0_i);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S0 = struct @align(4) {
+  x:i32 @offset(0)
+  a:u32 @offset(4)
+  y:i32 @offset(8)
+  z:i32 @offset(12)
+}
+
+S1 = struct @align(4) {
+  x_1:i32 @offset(0)
+  a_1:S0 @offset(4)
+  y_1:i32 @offset(20)
+  z_1:i32 @offset(24)
+}
+
+S2 = struct @align(4) {
+  x_2:i32 @offset(0)
+  y_2:i32 @offset(4)
+  z_2:i32 @offset(8)
+  a_2:S1 @offset(12)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S2, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, i32, read_write> = access %wg, 3u, 1u, 0u
+    store %3, 0i
+    %4:ptr<workgroup, u32, read_write> = access %wg, 3u, 1u, 1u
+    %5:void = spirv.atomic_store %4, 2u, 0u, 0u
+    %6:ptr<workgroup, i32, read_write> = access %wg, 3u, 1u, 2u
+    store %6, 0i
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ArrayOfStruct) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("x"), ty.i32()},
+                                                   {mod.symbols.New("a"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block,
+             [&] { wg = b.Var("wg", ty.ptr(workgroup, ty.array(sb, 10), read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 4_i, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a, 2_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  x:i32 @offset(0)
+  a:u32 @offset(4)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, array<S, 10>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, u32, read_write> = access %wg, 4i, 1u
+    %4:void = spirv.atomic_store %3, 2u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_StructOfArray) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("x"), ty.i32()},
+                                                   {mod.symbols.New("a"), ty.array(ty.u32(), 10)},
+                                                   {mod.symbols.New("y"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] { wg = b.Var("wg", ty.ptr(workgroup, sb, read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_u, 4_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a, 2_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+    auto* src = R"(
+S = struct @align(4) {
+  x:i32 @offset(0)
+  a:array<u32, 10> @offset(4)
+  y:u32 @offset(44)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, u32, read_write> = access %wg, 1u, 4i
+    %4:void = spirv.atomic_store %3, 2u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicAdd) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicIAdd, a0, 1_u, 0_u, 1_i);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, a1, 1_u, 0_u, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicIAdd, wg_i32, 1_u, 0_u,
+                                       1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, wg_u32, 1_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_i_add %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_i_add %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_i_add %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_i_add %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicSub) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicISub, a0, 1_u, 0_u, 1_i);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicISub, a1, 1_u, 0_u, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicISub, wg_i32, 1_u, 0_u,
+                                       1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicISub, wg_u32, 1_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_i_sub %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_i_sub %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_i_sub %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_i_sub %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicAnd) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicAnd, a0, 1_u, 0_u, 1_i);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicAnd, a1, 1_u, 0_u, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicAnd, wg_i32, 1_u, 0_u,
+                                       1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicAnd, wg_u32, 1_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_and %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_and %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_and %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_and %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicOr) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicOr, a0, 1_u, 0_u, 1_i);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicOr, a1, 1_u, 0_u, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicOr, wg_i32, 1_u, 0_u,
+                                       1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicOr, wg_u32, 1_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_or %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_or %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_or %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_or %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicXor) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicXor, a0, 1_u, 0_u, 1_i);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicXor, a1, 1_u, 0_u, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicXor, wg_i32, 1_u, 0_u,
+                                       1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicXor, wg_u32, 1_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_xor %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_xor %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_xor %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_xor %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicMax) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicSMax, a0, 1_u, 0_u, 1_i);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicUMax, a1, 1_u, 0_u, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicSMax, wg_i32, 1_u, 0_u,
+                                       1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicUMax, wg_u32, 1_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_s_max %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_u_max %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_s_max %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_u_max %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicMin) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicSMin, a0, 1_u, 0_u, 1_i);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicUMin, a1, 1_u, 0_u, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicSMin, wg_i32, 1_u, 0_u,
+                                       1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicUMin, wg_u32, 1_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_s_min %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_u_min %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_s_min %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_u_min %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicExchange) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicExchange, a0, 1_u, 0_u,
+                                       1_i);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicExchange, a1, 1_u, 0_u,
+                                       1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicExchange, wg_i32, 1_u,
+                                       0_u, 1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicExchange, wg_u32, 1_u,
+                                       0_u, 1_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_exchange %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_exchange %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_exchange %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_exchange %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicCompareExchange) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicCompareExchange, a0, 1_u,
+                                       0_u, 0_u, 1_i, 1_i);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicCompareExchange, a1, 1_u,
+                                       0_u, 0_u, 1_u, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicCompareExchange, wg_i32,
+                                       1_u, 0_u, 0_u, 1_i, 1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicCompareExchange, wg_u32,
+                                       1_u, 0_u, 0_u, 1_u, 1_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_compare_exchange %5, 1u, 0u, 0u, 1i, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_compare_exchange %7, 1u, 0u, 0u, 1u, 1u
+    %9:i32 = spirv.atomic_compare_exchange %wg_i32, 1u, 0u, 0u, 1i, 1i
+    %10:u32 = spirv.atomic_compare_exchange %wg_u32, 1u, 0u, 0u, 1u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicLoad) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicLoad, a0, 1_u, 0_u);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicLoad, a1, 1_u, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicLoad, wg_i32, 1_u, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicLoad, wg_u32, 1_u, 0_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_load %5, 1u, 0u
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_load %7, 1u, 0u
+    %9:i32 = spirv.atomic_load %wg_i32, 1u, 0u
+    %10:u32 = spirv.atomic_load %wg_u32, 1u, 0u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicStore) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a0, 1_u, 0_u,
+                                       1_i);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, a1, 1_u, 0_u,
+                                       1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, wg_i32, 1_u, 0_u,
+                                       1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.void_(), spirv::BuiltinFn::kAtomicStore, wg_u32, 1_u, 0_u,
+                                       1_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:void = spirv.atomic_store %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:void = spirv.atomic_store %7, 1u, 0u, 1u
+    %9:void = spirv.atomic_store %wg_i32, 1u, 0u, 1i
+    %10:void = spirv.atomic_store %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicDecrement) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicIDecrement, a0, 1_u, 0_u);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIDecrement, a1, 1_u, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicIDecrement, wg_i32, 1_u,
+                                       0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIDecrement, wg_u32, 1_u,
+                                       0_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_i_decrement %5, 1u, 0u
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_i_decrement %7, 1u, 0u
+    %9:i32 = spirv.atomic_i_decrement %wg_i32, 1u, 0u
+    %10:u32 = spirv.atomic_i_decrement %wg_u32, 1u, 0u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_AtomicIncrement) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.i32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg_u32 = nullptr;
+    core::ir::Var* wg_i32 = nullptr;
+    core::ir::Var* sg = nullptr;
+    b.Append(mod.root_block, [&] {
+        sg = b.Var("sb", ty.ptr(storage, sb, read_write));
+        sg->SetBindingPoint(0, 0);
+
+        wg_i32 = b.Var("wg_i32", ty.ptr<workgroup, i32, read_write>());
+        wg_u32 = b.Var("wg_u32", ty.ptr<workgroup, u32, read_write>());
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* a0 = b.Access(ty.ptr<storage, i32, read_write>(), sg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicIIncrement, a0, 1_u, 0_u);
+
+        auto* a1 = b.Access(ty.ptr<storage, u32, read_write>(), sg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIIncrement, a1, 1_u, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kAtomicIIncrement, wg_i32, 1_u,
+                                       0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIIncrement, wg_u32, 1_u,
+                                       0_u);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_i_increment %5, 1u, 0u
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_i_increment %7, 1u, 0u
+    %9:i32 = spirv.atomic_i_increment %wg_i32, 1u, 0u
+    %10:u32 = spirv.atomic_i_increment %wg_u32, 1u, 0u
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceAssignsAndDecls_Scalar) {
+    auto* f = b.ComputeFunction("main");
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] { wg = b.Var("wg", ty.ptr(workgroup, ty.u32(), read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* v = b.Var("b", ty.ptr(function, ty.u32(), read_write));
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, wg, 1_u, 0_u, 0_u);
+        b.Store(wg, 0_u);
+        auto* l0 = b.Load(wg);
+        b.Let(l0);
+        auto* l1 = b.Load(wg);
+        b.Store(v, l1);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+$B1: {  # root
+  %wg:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:u32 = spirv.atomic_i_add %wg, 1u, 0u, 0u
+    store %wg, 0u
+    %5:u32 = load %wg
+    %6:u32 = let %5
+    %7:u32 = load %wg
+    store %b, %7
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceAssignsAndDecls_Struct) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] { wg = b.Var("wg", ty.ptr(workgroup, sb, read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* b_ = b.Var("b", ty.ptr<function, u32, read_write>());
+        auto* l1 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, l1, 1_u, 0_u, 0_u);
+
+        auto* l2 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        b.Store(l2, 0_u);
+
+        auto* l3 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        auto* v1 = b.Load(l3);
+        b.Let(v1);
+
+        auto* l4 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        auto* v2 = b.Load(l4);
+        b.Store(b_, v2);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:u32 @offset(0)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 0u
+    store %6, 0u
+    %7:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %8:u32 = load %7
+    %9:u32 = let %8
+    %10:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %11:u32 = load %10
+    store %b, %11
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceAssignsAndDecls_NestedStruct) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* s0 = ty.Struct(mod.symbols.New("S0"), {
+                                                    {mod.symbols.New("a"), ty.u32()},
+                                                });
+    auto* s1 = ty.Struct(mod.symbols.New("S1"), {
+                                                    {mod.symbols.New("s0"), s0},
+                                                });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] { wg = b.Var("wg", ty.ptr(workgroup, s1, read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* b_ = b.Var("b", ty.ptr<function, u32, read_write>());
+
+        auto* l1 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, l1, 1_u, 0_u, 0_u);
+        auto* l2 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u, 0_u);
+        b.Store(l2, 0_u);
+
+        auto* l3 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u, 0_u);
+        auto* v1 = b.Load(l3);
+        b.Let(v1);
+
+        auto* l4 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u, 0_u);
+        auto* v2 = b.Load(l4);
+        b.Store(b_, v2);
+
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S0 = struct @align(4) {
+  a:u32 @offset(0)
+}
+
+S1 = struct @align(4) {
+  s0:S0 @offset(0)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S1, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<workgroup, u32, read_write> = access %wg, 0u, 0u
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 0u, 0u
+    store %6, 0u
+    %7:ptr<workgroup, u32, read_write> = access %wg, 0u, 0u
+    %8:u32 = load %7
+    %9:u32 = let %8
+    %10:ptr<workgroup, u32, read_write> = access %wg, 0u, 0u
+    %11:u32 = load %10
+    store %b, %11
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceAssignsAndDecls_StructMultipleAtomics) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.u32()},
+                                                   {mod.symbols.New("b"), ty.u32()},
+                                                   {mod.symbols.New("c"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] { wg = b.Var("wg", ty.ptr(workgroup, sb, read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* d_ = b.Var("d", ty.ptr<function, u32, read_write>());
+        auto* e = b.Var("e", ty.ptr<function, u32, read_write>());
+        auto* f_1 = b.Var("f", ty.ptr<function, u32, read_write>());
+
+        auto* l1 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, l1, 1_u, 0_u, 0_u);
+        auto* l2 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, l2, 1_u, 0_u, 0_u);
+        auto* l3 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        b.Store(l3, 0_u);
+
+        auto* l4 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        auto* v1 = b.Load(l4);
+        b.Let(v1);
+
+        auto* l5 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        auto* v2 = b.Load(l5);
+        b.Store(d_, v2);
+
+        auto* l6 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        b.Store(l6, 0_u);
+
+        auto* l7 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_u);
+        auto* v3 = b.Load(l7);
+        b.Let(v3);
+
+        auto* l8 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_u);
+        auto* v4 = b.Load(l8);
+        b.Store(e, v4);
+
+        auto* l9 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 2_u);
+        b.Store(l9, 0_u);
+
+        auto* l10 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 2_u);
+        auto* v5 = b.Load(l10);
+        b.Let(v5);
+
+        auto* l11 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 2_u);
+        auto* v6 = b.Load(l11);
+        b.Store(f_1, v6);
+
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:u32 @offset(0)
+  b:u32 @offset(4)
+  c:u32 @offset(8)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %d:ptr<function, u32, read_write> = var undef
+    %e:ptr<function, u32, read_write> = var undef
+    %f:ptr<function, u32, read_write> = var undef
+    %6:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %7:u32 = spirv.atomic_i_add %6, 1u, 0u, 0u
+    %8:ptr<workgroup, u32, read_write> = access %wg, 1u
+    %9:u32 = spirv.atomic_i_add %8, 1u, 0u, 0u
+    %10:ptr<workgroup, u32, read_write> = access %wg, 0u
+    store %10, 0u
+    %11:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %12:u32 = load %11
+    %13:u32 = let %12
+    %14:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %15:u32 = load %14
+    store %d, %15
+    %16:ptr<workgroup, u32, read_write> = access %wg, 0u
+    store %16, 0u
+    %17:ptr<workgroup, u32, read_write> = access %wg, 1u
+    %18:u32 = load %17
+    %19:u32 = let %18
+    %20:ptr<workgroup, u32, read_write> = access %wg, 1u
+    %21:u32 = load %20
+    store %e, %21
+    %22:ptr<workgroup, u32, read_write> = access %wg, 2u
+    store %22, 0u
+    %23:ptr<workgroup, u32, read_write> = access %wg, 2u
+    %24:u32 = load %23
+    %25:u32 = let %24
+    %26:ptr<workgroup, u32, read_write> = access %wg, 2u
+    %27:u32 = load %26
+    store %f, %27
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceAssignsAndDecls_ArrayOfScalar) {
+    auto* f = b.ComputeFunction("main");
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block,
+             [&] { wg = b.Var("wg", ty.ptr<workgroup, array<u32, 4>, read_write>()); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* b_ = b.Var("b", ty.ptr<function, u32, read_write>());
+
+        auto* l1 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, l1, 1_u, 0_u, 0_u);
+        auto* l2 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_i);
+        b.Store(l2, 0_u);
+
+        auto* l3 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_i);
+        auto* v1 = b.Load(l3);
+        b.Let(v1);
+
+        auto* l4 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_i);
+        auto* v2 = b.Load(l4);
+        b.Store(b_, v2);
+
+        b.Return(f);
+    });
+
+    auto* src = R"(
+$B1: {  # root
+  %wg:ptr<workgroup, array<u32, 4>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<workgroup, u32, read_write> = access %wg, 1i
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 1i
+    store %6, 0u
+    %7:ptr<workgroup, u32, read_write> = access %wg, 1i
+    %8:u32 = load %7
+    %9:u32 = let %8
+    %10:ptr<workgroup, u32, read_write> = access %wg, 1i
+    %11:u32 = load %10
+    store %b, %11
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceAssignsAndDecls_ArrayOfStruct) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block,
+             [&] { wg = b.Var("wg", ty.ptr(workgroup, ty.array(sb, 4), read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* b_ = b.Var("b", ty.ptr<function, u32, read_write>());
+
+        auto* l1 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_i, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, l1, 1_u, 0_u, 0_u);
+        auto* l2 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_i, 0_u);
+        b.Store(l2, 0_u);
+
+        auto* l3 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_i, 0_u);
+        auto* v1 = b.Load(l3);
+        b.Let(v1);
+
+        auto* l4 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 1_i, 0_u);
+        auto* v2 = b.Load(l4);
+        b.Store(b_, v2);
+
+        b.Return(f);
+    });
+    auto* src = R"(
+S = struct @align(4) {
+  a:u32 @offset(0)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, array<S, 4>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<workgroup, u32, read_write> = access %wg, 1i, 0u
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 1i, 0u
+    store %6, 0u
+    %7:ptr<workgroup, u32, read_write> = access %wg, 1i, 0u
+    %8:u32 = load %7
+    %9:u32 = let %8
+    %10:ptr<workgroup, u32, read_write> = access %wg, 1i, 0u
+    %11:u32 = load %10
+    store %b, %11
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceAssignsAndDecls_StructOfArray) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb =
+        ty.Struct(mod.symbols.New("S"), {
+                                            {mod.symbols.New("a"), ty.runtime_array(ty.u32())},
+                                        });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] {
+        wg = b.Var("sg", ty.ptr(storage, sb, read_write));
+        wg->SetBindingPoint(0, 1);
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* b_ = b.Var("b", ty.ptr<function, u32, read_write>());
+
+        auto* l1 = b.Access(ty.ptr<storage, u32, read_write>(), wg, 0_u, 4_i);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, l1, 1_u, 0_u, 0_u);
+        auto* l2 = b.Access(ty.ptr<storage, u32, read_write>(), wg, 0_u, 4_i);
+        b.Store(l2, 0_u);
+
+        auto* l3 = b.Access(ty.ptr<storage, u32, read_write>(), wg, 0_u, 4_i);
+        auto* v1 = b.Load(l3);
+        b.Let(v1);
+
+        auto* l4 = b.Access(ty.ptr<storage, u32, read_write>(), wg, 0_u, 4_i);
+        auto* v2 = b.Load(l4);
+        b.Store(b_, v2);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:array<u32> @offset(0)
+}
+
+$B1: {  # root
+  %sg:ptr<storage, S, read_write> = var undef @binding_point(0, 1)
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<storage, u32, read_write> = access %sg, 0u, 4i
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<storage, u32, read_write> = access %sg, 0u, 4i
+    store %6, 0u
+    %7:ptr<storage, u32, read_write> = access %sg, 0u, 4i
+    %8:u32 = load %7
+    %9:u32 = let %8
+    %10:ptr<storage, u32, read_write> = access %sg, 0u, 4i
+    %11:u32 = load %10
+    store %b, %11
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceAssignsAndDecls_Let) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("i"), ty.u32()},
+                                               });
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] {
+        wg = b.Var("s", ty.ptr(storage, sb, read_write));
+        wg->SetBindingPoint(0, 1);
+    });
+
+    b.Append(f->Block(), [&] {  //
+        auto* b_ = b.Var("b", ty.ptr<function, u32, read_write>());
+
+        auto* p0 = b.Let(wg);
+        auto* a = b.Access(ty.ptr<storage, u32, read_write>(), p0, 0_u);
+        auto* p1 = b.Let(a);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, p1, 1_u, 0_u, 0_u);
+        b.Store(p1, 0_u);
+
+        auto* v1 = b.Load(p1);
+        b.Let(v1);
+
+        auto* v2 = b.Load(p1);
+        b.Store(b_, v2);
+
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  i:u32 @offset(0)
+}
+
+$B1: {  # root
+  %s:ptr<storage, S, read_write> = var undef @binding_point(0, 1)
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<storage, S, read_write> = let %s
+    %5:ptr<storage, u32, read_write> = access %4, 0u
+    %6:ptr<storage, u32, read_write> = let %5
+    %7:u32 = spirv.atomic_i_add %6, 1u, 0u, 0u
+    store %6, 0u
+    %8:u32 = load %6
+    %9:u32 = let %8
+    %10:u32 = load %6
+    store %b, %10
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceBitcastArgument_Scalar) {
+    auto* f = b.ComputeFunction("main");
+
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] { wg = b.Var("wg", ty.ptr(workgroup, ty.u32(), read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* b_ = b.Var("b", ty.ptr<function, f32, read_write>());
+
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, wg, 1_u, 0_u, 0_u);
+        b.Store(wg, 0_u);
+
+        auto* v1 = b.Load(wg);
+        auto* bc = b.Bitcast(ty.f32(), v1);
+        b.Store(b_, bc);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+$B1: {  # root
+  %wg:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, f32, read_write> = var undef
+    %4:u32 = spirv.atomic_i_add %wg, 1u, 0u, 0u
+    store %wg, 0u
+    %5:u32 = load %wg
+    %6:f32 = bitcast %5
+    store %b, %6
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceBitcastArgument_Struct) {
+    auto* f = b.ComputeFunction("main");
+
+    auto* sb = ty.Struct(mod.symbols.New("S"), {
+                                                   {mod.symbols.New("a"), ty.u32()},
+                                               });
+    core::ir::Var* wg = nullptr;
+    b.Append(mod.root_block, [&] { wg = b.Var("wg", ty.ptr(workgroup, sb, read_write)); });
+
+    b.Append(f->Block(), [&] {  //
+        auto* b_ = b.Var("b", ty.ptr<function, f32, read_write>());
+
+        auto* a0 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        b.Call<spirv::ir::BuiltinCall>(ty.u32(), spirv::BuiltinFn::kAtomicIAdd, a0, 1_u, 0_u, 0_u);
+
+        auto* a1 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        b.Store(a1, 0_u);
+
+        auto* a2 = b.Access(ty.ptr<workgroup, u32, read_write>(), wg, 0_u);
+        auto* v1 = b.Load(a2);
+        auto* bc = b.Bitcast(ty.f32(), v1);
+        b.Store(b_, bc);
+        b.Return(f);
+    });
+
+    auto* src = R"(
+S = struct @align(4) {
+  a:u32 @offset(0)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, f32, read_write> = var undef
+    %4:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 0u
+    store %6, 0u
+    %7:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %8:u32 = load %7
+    %9:f32 = bitcast %8
+    store %b, %9
+    ret
+  }
+}
+)";
+
+    ASSERT_EQ(src, str());
+    Run(Atomics);
+
+    auto* expect = R"(
+UNIMPLEMENTED
+)";
+    ASSERT_EQ(expect, str());
+}
+
+}  // namespace
+}  // namespace tint::spirv::reader::lower
diff --git a/src/tint/lang/spirv/reader/parser/BUILD.bazel b/src/tint/lang/spirv/reader/parser/BUILD.bazel
index 501029c..699fe19 100644
--- a/src/tint/lang/spirv/reader/parser/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/parser/BUILD.bazel
@@ -80,6 +80,7 @@
   name = "test",
   alwayslink = True,
   srcs = [
+    "atomics_test.cc",
     "binary_test.cc",
     "bit_test.cc",
     "branch_test.cc",
diff --git a/src/tint/lang/spirv/reader/parser/BUILD.cmake b/src/tint/lang/spirv/reader/parser/BUILD.cmake
index e37ddd6..da6f3f8 100644
--- a/src/tint/lang/spirv/reader/parser/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/parser/BUILD.cmake
@@ -89,6 +89,7 @@
 # Condition: TINT_BUILD_SPV_READER
 ################################################################################
 tint_add_target(tint_lang_spirv_reader_parser_test test
+  lang/spirv/reader/parser/atomics_test.cc
   lang/spirv/reader/parser/binary_test.cc
   lang/spirv/reader/parser/bit_test.cc
   lang/spirv/reader/parser/branch_test.cc
diff --git a/src/tint/lang/spirv/reader/parser/BUILD.gn b/src/tint/lang/spirv/reader/parser/BUILD.gn
index 9782c8f..3e05963 100644
--- a/src/tint/lang/spirv/reader/parser/BUILD.gn
+++ b/src/tint/lang/spirv/reader/parser/BUILD.gn
@@ -88,6 +88,7 @@
   if (tint_build_spv_reader) {
     tint_unittests_source_set("unittests") {
       sources = [
+        "atomics_test.cc",
         "binary_test.cc",
         "bit_test.cc",
         "branch_test.cc",
diff --git a/src/tint/lang/spirv/reader/parser/atomics_test.cc b/src/tint/lang/spirv/reader/parser/atomics_test.cc
new file mode 100644
index 0000000..5e71efc
--- /dev/null
+++ b/src/tint/lang/spirv/reader/parser/atomics_test.cc
@@ -0,0 +1,2216 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/spirv/reader/parser/helper_test.h"
+
+namespace tint::spirv::reader {
+namespace {
+
+using SpirvParser_AtomicsTest = SpirvParserTest;
+
+TEST_F(SpirvParserDeathTest, AtomicLoad_float) {
+    auto src = R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+        %i32 = OpTypeInt 32 1
+        %f32 = OpTypeFloat 32
+      %int_0 = OpConstant %i32 0
+      %int_1 = OpConstant %i32 1
+      %int_2 = OpConstant %i32 2
+      %int_4 = OpConstant %i32 4
+        %arr = OpTypeArray %f32 %int_4
+    %ptr_arr = OpTypePointer Workgroup %arr
+    %ptr_f32 = OpTypePointer Workgroup %f32
+       %void = OpTypeVoid
+         %wg = OpVariable %ptr_arr Workgroup
+    %ep_type = OpTypeFunction %void
+       %main = OpFunction %void None %ep_type
+         %10 = OpLabel
+         %42 = OpAccessChain %ptr_f32 %wg %int_1
+         %50 = OpAtomicLoad %f32 %42 %int_2 %int_0
+               OpReturn
+               OpFunctionEnd
+)";
+    EXPECT_DEATH_IF_SUPPORTED({ auto _ = Run(src); }, "internal compiler error");
+}
+
+TEST_F(SpirvParserDeathTest, AtomicStore_float) {
+    auto src = R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+        %i32 = OpTypeInt 32 1
+        %f32 = OpTypeFloat 32
+      %int_0 = OpConstant %i32 0
+      %int_1 = OpConstant %i32 1
+      %int_2 = OpConstant %i32 2
+      %int_4 = OpConstant %i32 4
+      %f32_1 = OpConstant %f32 1
+        %arr = OpTypeArray %f32 %int_4
+    %ptr_arr = OpTypePointer Workgroup %arr
+    %ptr_f32 = OpTypePointer Workgroup %f32
+       %void = OpTypeVoid
+         %wg = OpVariable %ptr_arr Workgroup
+    %ep_type = OpTypeFunction %void
+       %main = OpFunction %void None %ep_type
+         %10 = OpLabel
+         %42 = OpAccessChain %ptr_f32 %wg %int_1
+               OpAtomicStore %42 %int_2 %int_0 %f32_1
+               OpReturn
+               OpFunctionEnd
+)";
+    EXPECT_DEATH_IF_SUPPORTED({ auto _ = Run(src); }, "internal compiler error");
+}
+
+TEST_F(SpirvParserDeathTest, AtomicExchange_float) {
+    auto src = R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+        %i32 = OpTypeInt 32 1
+        %f32 = OpTypeFloat 32
+      %int_0 = OpConstant %i32 0
+      %int_1 = OpConstant %i32 1
+      %int_4 = OpConstant %i32 4
+      %f32_1 = OpConstant %f32 1
+        %arr = OpTypeArray %f32 %int_4
+    %ptr_arr = OpTypePointer Workgroup %arr
+    %ptr_f32 = OpTypePointer Workgroup %f32
+       %void = OpTypeVoid
+         %wg = OpVariable %ptr_arr Workgroup
+    %ep_type = OpTypeFunction %void
+       %main = OpFunction %void None %ep_type
+         %10 = OpLabel
+         %42 = OpAccessChain %ptr_f32 %wg %int_1
+         %16 = OpAtomicExchange %f32 %42 %int_1 %int_0 %f32_1
+               OpReturn
+               OpFunctionEnd
+)";
+    EXPECT_DEATH_IF_SUPPORTED({ auto _ = Run(src); }, "internal compiler error");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ArrayStore) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+        %int = OpTypeInt 32 1
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_4 = OpConstant %uint 4
+      %int_1 = OpConstant %int 1
+        %arr = OpTypeArray %uint %uint_4
+    %ptr_arr = OpTypePointer Workgroup %arr
+   %ptr_uint = OpTypePointer Workgroup %uint
+       %void = OpTypeVoid
+         %wg = OpVariable %ptr_arr Workgroup
+         %43 = OpTypeFunction %void
+       %main = OpFunction %void None %43
+         %45 = OpLabel
+         %42 = OpAccessChain %ptr_uint %wg %int_1
+               OpAtomicStore %42 %uint_2 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+$B1: {  # root
+  %wg:ptr<workgroup, array<u32, 4>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, u32, read_write> = access %wg, 1i
+    %4:void = spirv.atomic_store %3, 2u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ArrayStore_CopiedObject) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+        %int = OpTypeInt 32 1
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_4 = OpConstant %uint 4
+      %int_1 = OpConstant %int 1
+        %arr = OpTypeArray %uint %uint_4
+    %ptr_arr = OpTypePointer Workgroup %arr
+   %ptr_uint = OpTypePointer Workgroup %uint
+       %void = OpTypeVoid
+         %wg = OpVariable %ptr_arr Workgroup
+         %43 = OpTypeFunction %void
+       %main = OpFunction %void None %43
+         %45 = OpLabel
+         %41 = OpCopyObject %ptr_arr %wg
+         %42 = OpAccessChain %ptr_uint %41 %int_1
+               OpAtomicStore %42 %uint_2 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+$B1: {  # root
+  %wg:ptr<workgroup, array<u32, 4>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, array<u32, 4>, read_write> = let %wg
+    %4:ptr<workgroup, u32, read_write> = access %3, 1i
+    %5:void = spirv.atomic_store %4, 2u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ArrayNested) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+       %void = OpTypeVoid
+        %int = OpTypeInt 32 1
+       %uint = OpTypeInt 32 0
+      %int_1 = OpConstant %int 1
+      %int_2 = OpConstant %int 2
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+        %arr = OpTypeArray %uint %uint_1
+    %arr_arr = OpTypeArray %arr %uint_2
+%arr_arr_arr = OpTypeArray %arr_arr %uint_3
+%ptr_arr_arr_arr = OpTypePointer Workgroup %arr_arr_arr
+         %wg = OpVariable %ptr_arr_arr_arr Workgroup
+   %ptr_uint = OpTypePointer Workgroup %uint
+         %51 = OpConstantNull %int
+         %53 = OpTypeFunction %void
+       %main = OpFunction %void None %53
+         %55 = OpLabel
+         %52 = OpAccessChain %ptr_uint %wg %int_2 %int_1 %51
+               OpAtomicStore %52 %uint_2 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+$B1: {  # root
+  %wg:ptr<workgroup, array<array<array<u32, 1>, 2>, 3>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, u32, read_write> = access %wg, 2i, 1i, 0i
+    %4:void = spirv.atomic_store %3, 2u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, FlatSingleAtomic) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpMemberName %S 0 "x"
+               OpMemberName %S 1 "a"
+               OpMemberName %S 2 "y"
+               OpName %wg "wg"
+               OpName %main "main"
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+          %S = OpTypeStruct %int %uint %uint
+      %ptr_s = OpTypePointer Workgroup %S
+         %wg = OpVariable %ptr_s Workgroup
+    %ptr_int = OpTypePointer Workgroup %int
+   %ptr_uint = OpTypePointer Workgroup %uint
+         %16 = OpConstantNull %int
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+         %23 = OpConstantNull %uint
+         %31 = OpTypeFunction %void
+       %main = OpFunction %void None %31
+         %33 = OpLabel
+         %15 = OpAccessChain %ptr_int %wg %uint_0
+               OpStore %15 %16
+         %22 = OpAccessChain %ptr_uint %wg %uint_1
+               OpAtomicStore %22 %uint_2 %uint_0 %23
+         %25 = OpAccessChain %ptr_uint %wg %uint_2
+               OpStore %25 %23
+               OpReturn
+               OpFunctionEnd
+
+)",
+              R"(
+S = struct @align(4) {
+  x:i32 @offset(0)
+  a:u32 @offset(4)
+  y:u32 @offset(8)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, i32, read_write> = access %wg, 0u
+    store %3, 0i
+    %4:ptr<workgroup, u32, read_write> = access %wg, 1u
+    %5:void = spirv.atomic_store %4, 2u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 2u
+    store %6, 0u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, FlatMultipleAtomics) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpMemberName %S 0 "x"
+               OpMemberName %S 1 "a"
+               OpMemberName %S 2 "b"
+               OpName %wg "wg"
+               OpName %main "main"
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+          %S = OpTypeStruct %int %uint %uint
+      %ptr_s = OpTypePointer Workgroup %S
+         %wg = OpVariable %ptr_s Workgroup
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+    %ptr_int = OpTypePointer Workgroup %int
+   %ptr_uint = OpTypePointer Workgroup %uint
+         %16 = OpConstantNull %int
+         %23 = OpConstantNull %uint
+         %35 = OpTypeFunction %void
+       %main = OpFunction %void None %35
+         %37 = OpLabel
+         %15 = OpAccessChain %ptr_int %wg %uint_0
+               OpStore %15 %16
+         %22 = OpAccessChain %ptr_uint %wg %uint_1
+               OpAtomicStore %22 %uint_2 %uint_0 %23
+         %24 = OpAccessChain %ptr_uint %wg %uint_2
+               OpAtomicStore %24 %uint_2 %uint_0 %23
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  x:i32 @offset(0)
+  a:u32 @offset(4)
+  b:u32 @offset(8)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, i32, read_write> = access %wg, 0u
+    store %3, 0i
+    %4:ptr<workgroup, u32, read_write> = access %wg, 1u
+    %5:void = spirv.atomic_store %4, 2u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 2u
+    %7:void = spirv.atomic_store %6, 2u, 0u, 0u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, Nested) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S2 "S2"
+               OpMemberName %S2 0 "x"
+               OpMemberName %S2 1 "y"
+               OpMemberName %S2 2 "z"
+               OpMemberName %S2 3 "a"
+               OpName %S1 "S1"
+               OpMemberName %S1 0 "x"
+               OpMemberName %S1 1 "a"
+               OpName %S0 "S0"
+               OpMemberName %S0 0 "x"
+               OpMemberName %S0 1 "a"
+               OpMemberName %S0 2 "y"
+               OpMemberName %S0 3 "z"
+               OpMemberName %S1 2 "y"
+               OpMemberName %S1 3 "z"
+               OpName %wg "wg"
+               OpName %main "main"
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+         %S0 = OpTypeStruct %int %uint %int %int
+         %S1 = OpTypeStruct %int %S0 %int %int
+         %S2 = OpTypeStruct %int %int %int %S1
+%_ptr_Workgroup_S2 = OpTypePointer Workgroup %S2
+         %wg = OpVariable %_ptr_Workgroup_S2 Workgroup
+       %void = OpTypeVoid
+         %10 = OpTypeFunction %void %uint
+     %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+         %18 = OpConstantNull %int
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+         %30 = OpConstantNull %uint
+   %uint_264 = OpConstant %uint 264
+         %40 = OpTypeFunction %void
+       %main = OpFunction %void None %40
+         %42 = OpLabel
+         %25 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_0
+               OpStore %25 %18
+         %29 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_3 %uint_1 %uint_1
+               OpAtomicStore %29 %uint_2 %uint_0 %30
+         %31 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_2
+               OpStore %31 %18
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S0 = struct @align(4) {
+  x:i32 @offset(0)
+  a:u32 @offset(4)
+  y:i32 @offset(8)
+  z:i32 @offset(12)
+}
+
+S1 = struct @align(4) {
+  x:i32 @offset(0)
+  a:S0 @offset(4)
+  y:i32 @offset(20)
+  z:i32 @offset(24)
+}
+
+S2 = struct @align(4) {
+  x:i32 @offset(0)
+  y:i32 @offset(4)
+  z:i32 @offset(8)
+  a:S1 @offset(12)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S2, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, i32, read_write> = access %wg, 3u, 1u, 0u
+    store %3, 0i
+    %4:ptr<workgroup, u32, read_write> = access %wg, 3u, 1u, 1u
+    %5:void = spirv.atomic_store %4, 2u, 0u, 0u
+    %6:ptr<workgroup, i32, read_write> = access %wg, 3u, 1u, 2u
+    store %6, 0i
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ArrayOfStruct) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpMemberName %S 0 "x"
+               OpMemberName %S 1 "a"
+               OpName %wg "wg"
+               OpName %main "main"
+       %void = OpTypeVoid
+        %int = OpTypeInt 32 1
+       %uint = OpTypeInt 32 0
+      %int_4 = OpConstant %int 4
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+    %uint_10 = OpConstant %uint 10
+          %S = OpTypeStruct %int %uint
+        %arr = OpTypeArray %S %uint_10
+    %ptr_arr = OpTypePointer Workgroup %arr
+   %ptr_uint = OpTypePointer Workgroup %uint
+         %wg = OpVariable %ptr_arr Workgroup
+         %49 = OpTypeFunction %void
+       %main = OpFunction %void None %49
+         %51 = OpLabel
+         %48 = OpAccessChain %ptr_uint %wg %int_4 %uint_1
+               OpAtomicStore %48 %uint_2 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+
+)",
+              R"(
+S = struct @align(4) {
+  x:i32 @offset(0)
+  a:u32 @offset(4)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, array<S, 10>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, u32, read_write> = access %wg, 4i, 1u
+    %4:void = spirv.atomic_store %3, 2u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, StructOfArray) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpMemberName %S 0 "x"
+               OpMemberName %S 1 "a"
+               OpMemberName %S 2 "y"
+               OpName %wg "wg"
+               OpName %main "main"
+       %void = OpTypeVoid
+        %int = OpTypeInt 32 1
+       %uint = OpTypeInt 32 0
+      %int_4 = OpConstant %int 4
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+    %uint_10 = OpConstant %uint 10
+        %arr = OpTypeArray %uint %uint_10
+          %S = OpTypeStruct %int %arr %uint
+      %ptr_s = OpTypePointer Workgroup %S
+   %ptr_uint = OpTypePointer Workgroup %uint
+         %wg = OpVariable %ptr_s Workgroup
+         %49 = OpTypeFunction %void
+       %main = OpFunction %void None %49
+         %51 = OpLabel
+         %48 = OpAccessChain %ptr_uint %wg %uint_1 %int_4
+               OpAtomicStore %48 %uint_2 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  x:i32 @offset(0)
+  a:array<u32, 10> @offset(4)
+  y:u32 @offset(44)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:ptr<workgroup, u32, read_write> = access %wg, 1u, 4i
+    %4:void = spirv.atomic_store %3, 2u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicAdd) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicIAdd %int %15 %uint_1 %uint_0 %int_1
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicIAdd %uint %17 %uint_1 %uint_0 %uint_1
+         %19 = OpAtomicIAdd %int %wg_int %uint_1 %uint_0 %int_1
+         %20 = OpAtomicIAdd %uint %wg_uint %uint_1 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_i_add %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_i_add %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_i_add %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_i_add %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicSub) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicISub %int %15 %uint_1 %uint_0 %int_1
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicISub %uint %17 %uint_1 %uint_0 %uint_1
+         %19 = OpAtomicISub %int %wg_int %uint_1 %uint_0 %int_1
+         %20 = OpAtomicISub %uint %wg_uint %uint_1 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_i_sub %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_i_sub %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_i_sub %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_i_sub %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicAnd) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicAnd %int %15 %uint_1 %uint_0 %int_1
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicAnd %uint %17 %uint_1 %uint_0 %uint_1
+         %19 = OpAtomicAnd %int %wg_int %uint_1 %uint_0 %int_1
+         %20 = OpAtomicAnd %uint %wg_uint %uint_1 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_and %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_and %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_and %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_and %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicOr) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicOr %int %15 %uint_1 %uint_0 %int_1
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicOr %uint %17 %uint_1 %uint_0 %uint_1
+         %19 = OpAtomicOr %int %wg_int %uint_1 %uint_0 %int_1
+         %20 = OpAtomicOr %uint %wg_uint %uint_1 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_or %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_or %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_or %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_or %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicXor) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicXor %int %15 %uint_1 %uint_0 %int_1
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicXor %uint %17 %uint_1 %uint_0 %uint_1
+         %19 = OpAtomicXor %int %wg_int %uint_1 %uint_0 %int_1
+         %20 = OpAtomicXor %uint %wg_uint %uint_1 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_xor %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_xor %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_xor %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_xor %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicMax) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicSMax %int %15 %uint_1 %uint_0 %int_1
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicUMax %uint %17 %uint_1 %uint_0 %uint_1
+         %19 = OpAtomicSMax %int %wg_int %uint_1 %uint_0 %int_1
+         %20 = OpAtomicUMax %uint %wg_uint %uint_1 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_s_max %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_u_max %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_s_max %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_u_max %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicMin) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicSMin %int %15 %uint_1 %uint_0 %int_1
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicUMin %uint %17 %uint_1 %uint_0 %uint_1
+         %19 = OpAtomicSMin %int %wg_int %uint_1 %uint_0 %int_1
+         %20 = OpAtomicUMin %uint %wg_uint %uint_1 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_s_min %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_u_min %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_s_min %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_u_min %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicExchange) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicExchange %int %15 %uint_1 %uint_0 %int_1
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicExchange %uint %17 %uint_1 %uint_0 %uint_1
+         %19 = OpAtomicExchange %int %wg_int %uint_1 %uint_0 %int_1
+         %20 = OpAtomicExchange %uint %wg_uint %uint_1 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_exchange %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_exchange %7, 1u, 0u, 1u
+    %9:i32 = spirv.atomic_exchange %wg_i32, 1u, 0u, 1i
+    %10:u32 = spirv.atomic_exchange %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicCompareExchange) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicCompareExchange %int %15 %uint_1 %uint_0 %uint_0 %int_1 %int_1
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicCompareExchange %uint %17 %uint_1 %uint_0 %uint_0 %uint_1 %uint_1
+         %19 = OpAtomicCompareExchange %int %wg_int %uint_1 %uint_0 %uint_0 %int_1 %int_1
+         %20 = OpAtomicCompareExchange %uint %wg_uint %uint_1 %uint_0 %uint_0 %uint_1 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_compare_exchange %5, 1u, 0u, 0u, 1i, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_compare_exchange %7, 1u, 0u, 0u, 1u, 1u
+    %9:i32 = spirv.atomic_compare_exchange %wg_i32, 1u, 0u, 0u, 1i, 1i
+    %10:u32 = spirv.atomic_compare_exchange %wg_u32, 1u, 0u, 0u, 1u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicLoad) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicLoad %int %15 %uint_1 %uint_0
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicLoad %uint %17 %uint_1 %uint_0
+         %19 = OpAtomicLoad %int %wg_int %uint_1 %uint_0
+         %20 = OpAtomicLoad %uint %wg_uint %uint_1 %uint_0
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_load %5, 1u, 0u
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_load %7, 1u, 0u
+    %9:i32 = spirv.atomic_load %wg_i32, 1u, 0u
+    %10:u32 = spirv.atomic_load %wg_u32, 1u, 0u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicStore) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+               OpAtomicStore %15 %uint_1 %uint_0 %int_1
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+               OpAtomicStore %17 %uint_1 %uint_0 %uint_1
+               OpAtomicStore %wg_int %uint_1 %uint_0 %int_1
+               OpAtomicStore %wg_uint %uint_1 %uint_0 %uint_1
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:void = spirv.atomic_store %5, 1u, 0u, 1i
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:void = spirv.atomic_store %7, 1u, 0u, 1u
+    %9:void = spirv.atomic_store %wg_i32, 1u, 0u, 1i
+    %10:void = spirv.atomic_store %wg_u32, 1u, 0u, 1u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicDecrement) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicIDecrement %int %15 %uint_1 %uint_0
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicIDecrement %uint %17 %uint_1 %uint_0
+         %19 = OpAtomicIDecrement %int %wg_int %uint_1 %uint_0
+         %20 = OpAtomicIDecrement %uint %wg_uint %uint_1 %uint_0
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_i_decrement %5, 1u, 0u
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_i_decrement %7, 1u, 0u
+    %9:i32 = spirv.atomic_i_decrement %wg_i32, 1u, 0u
+    %10:u32 = spirv.atomic_i_decrement %wg_u32, 1u, 0u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, AtomicIncrement) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %S "S"
+               OpName %wg_int "wg_i32"
+               OpName %wg_uint "wg_u32"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpName %sb "sb"
+               OpName %main "main"
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+               OpMemberDecorate %S 1 Offset 4
+               OpDecorate %sb DescriptorSet 0
+               OpDecorate %sb Binding 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %int %uint
+      %ptr_s = OpTypePointer StorageBuffer %S
+          %5 = OpTypeFunction %void
+%ptr_int_storage = OpTypePointer StorageBuffer %int
+%ptr_uint_storage = OpTypePointer StorageBuffer %uint
+%ptr_int_workgroup = OpTypePointer Workgroup %int
+%ptr_uint_workgroup = OpTypePointer Workgroup %uint
+         %sb = OpVariable %ptr_s StorageBuffer
+     %wg_int = OpVariable %ptr_int_workgroup Workgroup
+    %wg_uint = OpVariable %ptr_uint_workgroup Workgroup
+    %ptr_int = OpTypePointer Function %int
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+         %15 = OpAccessChain %ptr_int_storage %sb %uint_0
+         %16 = OpAtomicIIncrement %int %15 %uint_1 %uint_0
+         %17 = OpAccessChain %ptr_uint_storage %sb %uint_1
+         %18 = OpAtomicIIncrement %uint %17 %uint_1 %uint_0
+         %19 = OpAtomicIIncrement %int %wg_int %uint_1 %uint_0
+         %20 = OpAtomicIIncrement %uint %wg_uint %uint_1 %uint_0
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:i32 @offset(0)
+  b:u32 @offset(4)
+}
+
+$B1: {  # root
+  %sb:ptr<storage, S, read_write> = var undef @binding_point(0, 0)
+  %wg_i32:ptr<workgroup, i32, read_write> = var undef
+  %wg_u32:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %5:ptr<storage, i32, read_write> = access %sb, 0u
+    %6:i32 = spirv.atomic_i_increment %5, 1u, 0u
+    %7:ptr<storage, u32, read_write> = access %sb, 1u
+    %8:u32 = spirv.atomic_i_increment %7, 1u, 0u
+    %9:i32 = spirv.atomic_i_increment %wg_i32, 1u, 0u
+    %10:u32 = spirv.atomic_i_increment %wg_u32, 1u, 0u
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ReplaceAssignsAndDecls_Scalar) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+               OpName %b "b"
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %5 = OpTypeFunction %void
+   %ptr_uint = OpTypePointer Workgroup %uint
+         %wg = OpVariable %ptr_uint Workgroup
+%ptr_uint_fn = OpTypePointer Function %uint
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+          %b = OpVariable %ptr_uint_fn Function
+         %11 = OpAtomicIAdd %uint %wg %uint_1 %uint_0 %uint_0
+               OpStore %wg %uint_0
+         %15 = OpLoad %uint %wg
+         %16 = OpCopyObject %uint %15
+         %18 = OpLoad %uint %wg
+               OpStore %b %18
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+$B1: {  # root
+  %wg:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:u32 = spirv.atomic_i_add %wg, 1u, 0u, 0u
+    store %wg, 0u
+    %5:u32 = load %wg
+    %6:u32 = let %5
+    %7:u32 = load %wg
+    store %b, %7
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ReplaceAssignsAndDecls_Struct) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+               OpName %S "S"
+               OpName %b "b"
+               OpMemberName %S 0 "a"
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %uint
+          %5 = OpTypeFunction %void
+      %ptr_s = OpTypePointer Workgroup %S
+         %wg = OpVariable %ptr_s Workgroup
+   %ptr_uint = OpTypePointer Workgroup %uint
+%ptr_uint_fn = OpTypePointer Function %uint
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+          %b = OpVariable %ptr_uint_fn Function
+          %9 = OpAccessChain %ptr_uint %wg %uint_0
+         %11 = OpAtomicIAdd %uint %9 %uint_1 %uint_0 %uint_0
+         %12 = OpAccessChain %ptr_uint %wg %uint_0
+               OpStore %12 %uint_0
+         %14 = OpAccessChain %ptr_uint %wg %uint_0
+         %15 = OpLoad %uint %14
+         %16 = OpCopyObject %uint %15
+         %17 = OpAccessChain %ptr_uint %wg %uint_0
+         %18 = OpLoad %uint %17
+               OpStore %b %18
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:u32 @offset(0)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 0u
+    store %6, 0u
+    %7:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %8:u32 = load %7
+    %9:u32 = let %8
+    %10:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %11:u32 = load %10
+    store %b, %11
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ReplaceAssignsAndDecls_NestedStruct) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+               OpName %S0 "S0"
+               OpName %S1 "S1"
+               OpName %b "b"
+               OpMemberName %S0 0 "a"
+               OpMemberName %S1 0 "s0"
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %uint
+          %5 = OpTypeFunction %void
+         %S0 = OpTypeStruct %uint
+         %S1 = OpTypeStruct %S0
+      %ptr_s = OpTypePointer Workgroup %S1
+         %wg = OpVariable %ptr_s Workgroup
+   %ptr_uint = OpTypePointer Workgroup %uint
+%ptr_uint_fn = OpTypePointer Function %uint
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+          %b = OpVariable %ptr_uint_fn Function
+          %9 = OpAccessChain %ptr_uint %wg %uint_0 %uint_0
+         %11 = OpAtomicIAdd %uint %9 %uint_1 %uint_0 %uint_0
+         %12 = OpAccessChain %ptr_uint %wg %uint_0 %uint_0
+               OpStore %12 %uint_0
+         %14 = OpAccessChain %ptr_uint %wg %uint_0 %uint_0
+         %15 = OpLoad %uint %14
+         %16 = OpCopyObject %uint %15
+         %17 = OpAccessChain %ptr_uint %wg %uint_0 %uint_0
+         %18 = OpLoad %uint %17
+               OpStore %b %18
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S0 = struct @align(4) {
+  a:u32 @offset(0)
+}
+
+S1 = struct @align(4) {
+  s0:S0 @offset(0)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S1, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<workgroup, u32, read_write> = access %wg, 0u, 0u
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 0u, 0u
+    store %6, 0u
+    %7:ptr<workgroup, u32, read_write> = access %wg, 0u, 0u
+    %8:u32 = load %7
+    %9:u32 = let %8
+    %10:ptr<workgroup, u32, read_write> = access %wg, 0u, 0u
+    %11:u32 = load %10
+    store %b, %11
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ReplaceAssignsAndDecls_StructMultipleAtomics) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+               OpName %S "S"
+               OpName %d "d"
+               OpName %e "e"
+               OpName %f "f"
+               OpMemberName %S 0 "a"
+               OpMemberName %S 1 "b"
+               OpMemberName %S 2 "c"
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+          %S = OpTypeStruct %uint %uint %uint
+          %5 = OpTypeFunction %void
+      %ptr_s = OpTypePointer Workgroup %S
+         %wg = OpVariable %ptr_s Workgroup
+   %ptr_uint = OpTypePointer Workgroup %uint
+%ptr_uint_fn = OpTypePointer Function %uint
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+          %d = OpVariable %ptr_uint_fn Function
+          %e = OpVariable %ptr_uint_fn Function
+          %f = OpVariable %ptr_uint_fn Function
+          %9 = OpAccessChain %ptr_uint %wg %uint_0
+         %11 = OpAtomicIAdd %uint %9 %uint_1 %uint_0 %uint_0
+         %12 = OpAccessChain %ptr_uint %wg %uint_1
+         %13 = OpAtomicIAdd %uint %12 %uint_1 %uint_0 %uint_0
+         %14 = OpAccessChain %ptr_uint %wg %uint_0
+               OpStore %14 %uint_0
+         %15 = OpAccessChain %ptr_uint %wg %uint_0
+         %16 = OpLoad %uint %15
+         %17 = OpCopyObject %uint %16
+         %18 = OpAccessChain %ptr_uint %wg %uint_0
+         %19 = OpLoad %uint %18
+               OpStore %d %19
+         %20 = OpAccessChain %ptr_uint %wg %uint_0
+               OpStore %20 %uint_0
+         %21 = OpAccessChain %ptr_uint %wg %uint_1
+         %22 = OpLoad %uint %21
+         %99 = OpCopyObject %uint %22
+         %23 = OpAccessChain %ptr_uint %wg %uint_1
+         %24 = OpLoad %uint %23
+               OpStore %e %24
+         %25 = OpAccessChain %ptr_uint %wg %uint_2
+               OpStore %25 %uint_0
+         %26 = OpAccessChain %ptr_uint %wg %uint_2
+         %27 = OpLoad %uint %26
+         %98 = OpCopyObject %uint %27
+         %28 = OpAccessChain %ptr_uint %wg %uint_2
+         %29 = OpLoad %uint %28
+               OpStore %f %29
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:u32 @offset(0)
+  b:u32 @offset(4)
+  c:u32 @offset(8)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %d:ptr<function, u32, read_write> = var undef
+    %e:ptr<function, u32, read_write> = var undef
+    %f:ptr<function, u32, read_write> = var undef
+    %6:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %7:u32 = spirv.atomic_i_add %6, 1u, 0u, 0u
+    %8:ptr<workgroup, u32, read_write> = access %wg, 1u
+    %9:u32 = spirv.atomic_i_add %8, 1u, 0u, 0u
+    %10:ptr<workgroup, u32, read_write> = access %wg, 0u
+    store %10, 0u
+    %11:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %12:u32 = load %11
+    %13:u32 = let %12
+    %14:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %15:u32 = load %14
+    store %d, %15
+    %16:ptr<workgroup, u32, read_write> = access %wg, 0u
+    store %16, 0u
+    %17:ptr<workgroup, u32, read_write> = access %wg, 1u
+    %18:u32 = load %17
+    %19:u32 = let %18
+    %20:ptr<workgroup, u32, read_write> = access %wg, 1u
+    %21:u32 = load %20
+    store %e, %21
+    %22:ptr<workgroup, u32, read_write> = access %wg, 2u
+    store %22, 0u
+    %23:ptr<workgroup, u32, read_write> = access %wg, 2u
+    %24:u32 = load %23
+    %25:u32 = let %24
+    %26:ptr<workgroup, u32, read_write> = access %wg, 2u
+    %27:u32 = load %26
+    store %f, %27
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ReplaceAssignsAndDecls_ArrayOfScalar) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+               OpName %S "S"
+               OpName %b "b"
+               OpMemberName %S 0 "a"
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_4 = OpConstant %uint 4
+          %S = OpTypeStruct %uint
+          %5 = OpTypeFunction %void
+        %arr = OpTypeArray %uint %uint_4
+      %ptr_s = OpTypePointer Workgroup %arr
+         %wg = OpVariable %ptr_s Workgroup
+   %ptr_uint = OpTypePointer Workgroup %uint
+%ptr_uint_fn = OpTypePointer Function %uint
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+          %b = OpVariable %ptr_uint_fn Function
+          %9 = OpAccessChain %ptr_uint %wg %int_1
+         %11 = OpAtomicIAdd %uint %9 %uint_1 %uint_0 %uint_0
+         %12 = OpAccessChain %ptr_uint %wg %int_1
+               OpStore %12 %uint_0
+         %14 = OpAccessChain %ptr_uint %wg %int_1
+         %15 = OpLoad %uint %14
+         %16 = OpCopyObject %uint %15
+         %17 = OpAccessChain %ptr_uint %wg %int_1
+         %18 = OpLoad %uint %17
+               OpStore %b %18
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+$B1: {  # root
+  %wg:ptr<workgroup, array<u32, 4>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<workgroup, u32, read_write> = access %wg, 1i
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 1i
+    store %6, 0u
+    %7:ptr<workgroup, u32, read_write> = access %wg, 1i
+    %8:u32 = load %7
+    %9:u32 = let %8
+    %10:ptr<workgroup, u32, read_write> = access %wg, 1i
+    %11:u32 = load %10
+    store %b, %11
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ReplaceAssignsAndDecls_ArrayOfStruct) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+               OpName %S "S"
+               OpName %b "b"
+               OpMemberName %S 0 "a"
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_1 = OpConstant %int 1
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_4 = OpConstant %uint 4
+          %S = OpTypeStruct %uint
+        %arr = OpTypeArray %S %uint_4
+          %5 = OpTypeFunction %void
+      %ptr_s = OpTypePointer Workgroup %arr
+         %wg = OpVariable %ptr_s Workgroup
+   %ptr_uint = OpTypePointer Workgroup %uint
+%ptr_uint_fn = OpTypePointer Function %uint
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+          %b = OpVariable %ptr_uint_fn Function
+          %9 = OpAccessChain %ptr_uint %wg %int_1 %uint_0
+         %11 = OpAtomicIAdd %uint %9 %uint_1 %uint_0 %uint_0
+         %12 = OpAccessChain %ptr_uint %wg %int_1 %uint_0
+               OpStore %12 %uint_0
+         %14 = OpAccessChain %ptr_uint %wg %int_1 %uint_0
+         %15 = OpLoad %uint %14
+         %16 = OpCopyObject %uint %15
+         %17 = OpAccessChain %ptr_uint %wg %int_1 %uint_0
+         %18 = OpLoad %uint %17
+               OpStore %b %18
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:u32 @offset(0)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, array<S, 4>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<workgroup, u32, read_write> = access %wg, 1i, 0u
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 1i, 0u
+    store %6, 0u
+    %7:ptr<workgroup, u32, read_write> = access %wg, 1i, 0u
+    %8:u32 = load %7
+    %9:u32 = let %8
+    %10:ptr<workgroup, u32, read_write> = access %wg, 1i, 0u
+    %11:u32 = load %10
+    store %b, %11
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ReplaceAssignsAndDecls_StructOfArray) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %sg "sg"
+               OpName %main "main"
+               OpName %S "S"
+               OpName %b "b"
+               OpMemberName %S 0 "a"
+               OpDecorate %sg DescriptorSet 0
+               OpDecorate %sg Binding 1
+               OpDecorate %S Block
+               OpDecorate %arr ArrayStride 4
+               OpMemberDecorate %S 0 Offset 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %int = OpTypeInt 32 1
+      %int_4 = OpConstant %int 4
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_4 = OpConstant %uint 4
+        %arr = OpTypeRuntimeArray %uint
+          %S = OpTypeStruct %arr
+          %5 = OpTypeFunction %void
+      %ptr_s = OpTypePointer StorageBuffer %S
+         %sg = OpVariable %ptr_s StorageBuffer
+   %ptr_uint = OpTypePointer StorageBuffer %uint
+%ptr_uint_fn = OpTypePointer Function %uint
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+          %b = OpVariable %ptr_uint_fn Function
+          %9 = OpAccessChain %ptr_uint %sg %uint_0 %int_4
+         %11 = OpAtomicIAdd %uint %9 %uint_1 %uint_0 %uint_0
+         %12 = OpAccessChain %ptr_uint %sg %uint_0 %int_4
+               OpStore %12 %uint_0
+         %14 = OpAccessChain %ptr_uint %sg %uint_0 %int_4
+         %15 = OpLoad %uint %14
+         %16 = OpCopyObject %uint %15
+         %17 = OpAccessChain %ptr_uint %sg %uint_0 %int_4
+         %18 = OpLoad %uint %17
+               OpStore %b %18
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:array<u32> @offset(0)
+}
+
+$B1: {  # root
+  %sg:ptr<storage, S, read_write> = var undef @binding_point(0, 1)
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<storage, u32, read_write> = access %sg, 0u, 4i
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<storage, u32, read_write> = access %sg, 0u, 4i
+    store %6, 0u
+    %7:ptr<storage, u32, read_write> = access %sg, 0u, 4i
+    %8:u32 = load %7
+    %9:u32 = let %8
+    %10:ptr<storage, u32, read_write> = access %sg, 0u, 4i
+    %11:u32 = load %10
+    store %b, %11
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ReplaceAssignsAndDecls_Let) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpExtension "SPV_KHR_storage_buffer_storage_class"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %sg "s"
+               OpName %main "main"
+               OpName %S "S"
+               OpName %b "b"
+               OpMemberName %S 0 "a"
+               OpDecorate %sg DescriptorSet 0
+               OpDecorate %sg Binding 1
+               OpDecorate %S Block
+               OpMemberDecorate %S 0 Offset 0
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %uint
+          %5 = OpTypeFunction %void
+      %ptr_s = OpTypePointer StorageBuffer %S
+         %sg = OpVariable %ptr_s StorageBuffer
+   %ptr_uint = OpTypePointer StorageBuffer %uint
+%ptr_uint_fn = OpTypePointer Function %uint
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+          %b = OpVariable %ptr_uint_fn Function
+          %9 = OpCopyObject %ptr_s %sg
+         %10 = OpAccessChain %ptr_uint %9 %uint_0
+         %11 = OpCopyObject %ptr_uint %10
+         %12 = OpAtomicIAdd %uint %11 %uint_1 %uint_0 %uint_0
+               OpStore %11 %uint_0
+         %13 = OpLoad %uint %11
+         %14 = OpCopyObject %uint %13
+         %15 = OpLoad %uint %11
+               OpStore %b %15
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:u32 @offset(0)
+}
+
+$B1: {  # root
+  %s:ptr<storage, S, read_write> = var undef @binding_point(0, 1)
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, u32, read_write> = var undef
+    %4:ptr<storage, S, read_write> = let %s
+    %5:ptr<storage, u32, read_write> = access %4, 0u
+    %6:ptr<storage, u32, read_write> = let %5
+    %7:u32 = spirv.atomic_i_add %6, 1u, 0u, 0u
+    store %6, 0u
+    %8:u32 = load %6
+    %9:u32 = let %8
+    %10:u32 = load %6
+    store %b, %10
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ReplaceBitcastArgument_Scalar) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+               OpName %b "b"
+       %void = OpTypeVoid
+        %f32 = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %5 = OpTypeFunction %void
+    %ptr_f32 = OpTypePointer Function %f32
+   %ptr_uint = OpTypePointer Workgroup %uint
+         %wg = OpVariable %ptr_uint Workgroup
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+          %b = OpVariable %ptr_f32 Function
+         %11 = OpAtomicIAdd %uint %wg %uint_1 %uint_0 %uint_0
+               OpStore %wg %uint_0
+         %12 = OpLoad %uint %wg
+         %13 = OpBitcast %f32 %12
+               OpStore %b %13
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+$B1: {  # root
+  %wg:ptr<workgroup, u32, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, f32, read_write> = var undef
+    %4:u32 = spirv.atomic_i_add %wg, 1u, 0u, 0u
+    store %wg, 0u
+    %5:u32 = load %wg
+    %6:f32 = bitcast %5
+    store %b, %6
+    ret
+  }
+}
+)");
+}
+
+TEST_F(SpirvParser_AtomicsTest, ReplaceBitcastArgument_Struct) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %wg "wg"
+               OpName %main "main"
+               OpName %S "S"
+               OpName %b "b"
+               OpMemberName %S 0 "a"
+       %void = OpTypeVoid
+       %uint = OpTypeInt 32 0
+        %f32 = OpTypeFloat 32
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+          %S = OpTypeStruct %uint
+          %5 = OpTypeFunction %void
+      %ptr_s = OpTypePointer Workgroup %S
+         %wg = OpVariable %ptr_s Workgroup
+   %ptr_uint = OpTypePointer Workgroup %uint
+ %ptr_f32_fn = OpTypePointer Function %f32
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+          %b = OpVariable %ptr_f32_fn Function
+          %9 = OpAccessChain %ptr_uint %wg %uint_0
+         %11 = OpAtomicIAdd %uint %9 %uint_1 %uint_0 %uint_0
+         %12 = OpAccessChain %ptr_uint %wg %uint_0
+               OpStore %12 %uint_0
+         %14 = OpAccessChain %ptr_uint %wg %uint_0
+         %15 = OpLoad %uint %14
+         %16 = OpBitcast %f32 %15
+               OpStore %b %16
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+S = struct @align(4) {
+  a:u32 @offset(0)
+}
+
+$B1: {  # root
+  %wg:ptr<workgroup, S, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %b:ptr<function, f32, read_write> = var undef
+    %4:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %5:u32 = spirv.atomic_i_add %4, 1u, 0u, 0u
+    %6:ptr<workgroup, u32, read_write> = access %wg, 0u
+    store %6, 0u
+    %7:ptr<workgroup, u32, read_write> = access %wg, 0u
+    %8:u32 = load %7
+    %9:f32 = bitcast %8
+    store %b, %9
+    ret
+  }
+}
+)");
+}
+
+}  // namespace
+}  // namespace tint::spirv::reader
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index 800af32..cbd9a5b 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -262,6 +262,8 @@
                 return core::AddressSpace::kUniform;
             case spv::StorageClass::UniformConstant:
                 return core::AddressSpace::kHandle;
+            case spv::StorageClass::Workgroup:
+                return core::AddressSpace::kWorkgroup;
             default:
                 TINT_UNIMPLEMENTED()
                     << "unhandled SPIR-V storage class: " << static_cast<uint32_t>(sc);
@@ -1141,6 +1143,53 @@
                 case spv::Op::OpOuterProduct:
                     EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kOuterProduct);
                     break;
+                case spv::Op::OpAtomicStore:
+                    EmitAtomicStore(inst);
+                    break;
+                case spv::Op::OpAtomicLoad:
+                    CheckAtomicNotFloat(inst);
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicLoad);
+                    break;
+                case spv::Op::OpAtomicIAdd:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicIAdd);
+                    break;
+                case spv::Op::OpAtomicISub:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicISub);
+                    break;
+                case spv::Op::OpAtomicAnd:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicAnd);
+                    break;
+                case spv::Op::OpAtomicOr:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicOr);
+                    break;
+                case spv::Op::OpAtomicXor:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicXor);
+                    break;
+                case spv::Op::OpAtomicSMin:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicSMin);
+                    break;
+                case spv::Op::OpAtomicUMin:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicUMin);
+                    break;
+                case spv::Op::OpAtomicSMax:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicSMax);
+                    break;
+                case spv::Op::OpAtomicUMax:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicUMax);
+                    break;
+                case spv::Op::OpAtomicExchange:
+                    CheckAtomicNotFloat(inst);
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicExchange);
+                    break;
+                case spv::Op::OpAtomicCompareExchange:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicCompareExchange);
+                    break;
+                case spv::Op::OpAtomicIIncrement:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicIIncrement);
+                    break;
+                case spv::Op::OpAtomicIDecrement:
+                    EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicIDecrement);
+                    break;
                 default:
                     TINT_UNIMPLEMENTED()
                         << "unhandled SPIR-V instruction: " << static_cast<uint32_t>(inst.opcode());
@@ -1166,6 +1215,24 @@
         }
     }
 
+    void CheckAtomicNotFloat(const spvtools::opt::Instruction& inst) {
+        auto* ty = Type(inst.type_id());
+        if (ty->IsFloatScalar()) {
+            TINT_ICE() << "Atomic operations on floating point values not supported.";
+        }
+    }
+
+    void EmitAtomicStore(const spvtools::opt::Instruction& inst) {
+        auto* v = Value(inst.GetSingleWordInOperand(0));
+        auto* ty = v->Type()->UnwrapPtr();
+        if (ty->IsFloatScalar()) {
+            TINT_ICE() << "Atomic operations on floating point values not supported.";
+        }
+
+        EmitWithoutSpvResult(b_.Call<spirv::ir::BuiltinCall>(
+            ty_.void_(), spirv::BuiltinFn::kAtomicStore, Args(inst, 0)));
+    }
+
     void EmitBitcast(const spvtools::opt::Instruction& inst) {
         auto val = Value(inst.GetSingleWordInOperand(0));
         auto ty = Type(inst.type_id());
diff --git a/src/tint/lang/spirv/spirv.def b/src/tint/lang/spirv/spirv.def
index 242bf4f..5689529 100644
--- a/src/tint/lang/spirv/spirv.def
+++ b/src/tint/lang/spirv/spirv.def
@@ -168,7 +168,7 @@
 @stage("fragment", "compute") implicit(T: iu32, U: u32, S: workgroup_or_storage) fn atomic_load(ptr<S, T, readable>, U, U) -> T
 @stage("fragment", "compute") implicit(T: iu32, U: u32, S: workgroup_or_storage) fn atomic_store(ptr<S, T, writable>, U, U, T)
 @stage("fragment", "compute") implicit(T: iu32, U: u32, S: workgroup_or_storage) fn atomic_exchange(ptr<S, T, writable>, U, U, T) -> T
-@stage("fragment", "compute") implicit(T: iu32, U: u32, S: workgroup_or_storage) fn atomic_compare_exchange(ptr<S, T, writable>, U, U, T, T) -> T
+@stage("fragment", "compute") implicit(T: iu32, U: u32, S: workgroup_or_storage) fn atomic_compare_exchange(ptr<S, T, writable>, U, U, U, T, T) -> T
 @stage("fragment", "compute") implicit(T: iu32, U: u32, S: workgroup_or_storage) fn atomic_i_increment(ptr<S, T, writable>, U, U) -> T
 @stage("fragment", "compute") implicit(T: iu32, U: u32, S: workgroup_or_storage) fn atomic_i_decrement(ptr<S, T, writable>, U, U) -> T
 @stage("fragment", "compute") implicit(T: iu32, U: u32, S: workgroup_or_storage) fn atomic_i_add(ptr<S, T, writable>, U, U, T) -> T