[glsl][ir] Add polyfill for `abs`

This CL adds the `abs` polyfill for the GLSL IR backend. GLSL does not
support `abs` on unsigned values.

Bug: 42251044
Change-Id: I80f123f4421a813b60d92c2fed417896cd2dfa32
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/208114
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/glsl/builtin_fn.cc b/src/tint/lang/glsl/builtin_fn.cc
index 4c21465..09492c5 100644
--- a/src/tint/lang/glsl/builtin_fn.cc
+++ b/src/tint/lang/glsl/builtin_fn.cc
@@ -72,6 +72,8 @@
             return "packFloat2x16";
         case BuiltinFn::kUnpackFloat2X16:
             return "unpackFloat2x16";
+        case BuiltinFn::kAbs:
+            return "abs";
         case BuiltinFn::kAny:
             return "any";
         case BuiltinFn::kAll:
diff --git a/src/tint/lang/glsl/builtin_fn.h b/src/tint/lang/glsl/builtin_fn.h
index c4bb90b..a4416d9 100644
--- a/src/tint/lang/glsl/builtin_fn.h
+++ b/src/tint/lang/glsl/builtin_fn.h
@@ -62,6 +62,7 @@
     kBitfieldInsert,
     kPackFloat2X16,
     kUnpackFloat2X16,
+    kAbs,
     kAny,
     kAll,
     kDot,
diff --git a/src/tint/lang/glsl/glsl.def b/src/tint/lang/glsl/glsl.def
index d68bcd8..7b7826b 100644
--- a/src/tint/lang/glsl/glsl.def
+++ b/src/tint/lang/glsl/glsl.def
@@ -81,6 +81,7 @@
 
 match iu32: i32 | u32
 match fiu32: f32 | i32 | u32
+match fi32_f16: f32 | i32 | f16
 match fiu32_f16: f32 | i32 | u32 | f16
 match fiu32_f16_bool: f32 | i32 | u32 | f16 | bool
 match f32_f16: f32 | f16
@@ -167,6 +168,9 @@
 fn packFloat2x16(value: vec2<f16>) -> u32
 fn unpackFloat2x16(value: u32) -> vec2<f16>
 
+implicit(T: fi32_f16) fn abs(T) -> T
+implicit(T: fi32_f16, N: num) fn abs(vec<N, T>) -> vec<N, T>
+
 implicit(N: num) fn any(vec<N, bool>) -> bool
 implicit(N: num) fn all(vec<N, bool>) -> bool
 implicit(T: f32_f16, N: num) fn dot(vec<N, T>, vec<N, T>) -> T
diff --git a/src/tint/lang/glsl/intrinsic/data.cc b/src/tint/lang/glsl/intrinsic/data.cc
index c02e72e..2945a37 100644
--- a/src/tint/lang/glsl/intrinsic/data.cc
+++ b/src/tint/lang/glsl/intrinsic/data.cc
@@ -653,6 +653,26 @@
  kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);}
 };
 
+/// TypeMatcher for 'match fi32_f16'
+constexpr TypeMatcher kFi32F16Matcher {
+/* match */ [](MatchState& state, const Type* ty) -> const Type* {
+    if (MatchF32(state, ty)) {
+      return BuildF32(state, ty);
+    }
+    if (MatchI32(state, ty)) {
+      return BuildI32(state, ty);
+    }
+    if (MatchF16(state, ty)) {
+      return BuildF16(state, ty);
+    }
+    return nullptr;
+  },
+/* print */ [](MatchState*, StyledText& out) {
+    // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
+    // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+ kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);}
+};
+
 /// TypeMatcher for 'match fiu32_f16'
 constexpr TypeMatcher kFiu32F16Matcher {
 /* match */ [](MatchState& state, const Type* ty) -> const Type* {
@@ -902,9 +922,10 @@
   /* [29] */ kTextureStorage3DMatcher,
   /* [30] */ kIu32Matcher,
   /* [31] */ kFiu32Matcher,
-  /* [32] */ kFiu32F16Matcher,
-  /* [33] */ kFiu32F16BoolMatcher,
-  /* [34] */ kF32F16Matcher,
+  /* [32] */ kFi32F16Matcher,
+  /* [33] */ kFiu32F16Matcher,
+  /* [34] */ kFiu32F16BoolMatcher,
+  /* [35] */ kF32F16Matcher,
 };
 
 /// The template numbers, and number matchers
@@ -1057,15 +1078,16 @@
   /* [131] */ MatcherIndex(10),
   /* [132] */ MatcherIndex(0),
   /* [133] */ MatcherIndex(30),
-  /* [134] */ MatcherIndex(34),
-  /* [135] */ MatcherIndex(31),
-  /* [136] */ MatcherIndex(21),
-  /* [137] */ MatcherIndex(22),
-  /* [138] */ MatcherIndex(23),
-  /* [139] */ MatcherIndex(24),
-  /* [140] */ MatcherIndex(25),
-  /* [141] */ MatcherIndex(32),
+  /* [134] */ MatcherIndex(32),
+  /* [135] */ MatcherIndex(35),
+  /* [136] */ MatcherIndex(31),
+  /* [137] */ MatcherIndex(21),
+  /* [138] */ MatcherIndex(22),
+  /* [139] */ MatcherIndex(23),
+  /* [140] */ MatcherIndex(24),
+  /* [141] */ MatcherIndex(25),
   /* [142] */ MatcherIndex(33),
+  /* [143] */ MatcherIndex(34),
 };
 
 static_assert(MatcherIndicesIndex::CanIndex(kMatcherIndices),
@@ -1530,7 +1552,7 @@
   {
     /* [91] */
     /* usage */ core::ParameterUsage::kTexture,
-    /* matcher_indices */ MatcherIndicesIndex(136),
+    /* matcher_indices */ MatcherIndicesIndex(137),
   },
   {
     /* [92] */
@@ -1540,7 +1562,7 @@
   {
     /* [93] */
     /* usage */ core::ParameterUsage::kTexture,
-    /* matcher_indices */ MatcherIndicesIndex(137),
+    /* matcher_indices */ MatcherIndicesIndex(138),
   },
   {
     /* [94] */
@@ -1550,7 +1572,7 @@
   {
     /* [95] */
     /* usage */ core::ParameterUsage::kTexture,
-    /* matcher_indices */ MatcherIndicesIndex(138),
+    /* matcher_indices */ MatcherIndicesIndex(139),
   },
   {
     /* [96] */
@@ -1560,7 +1582,7 @@
   {
     /* [97] */
     /* usage */ core::ParameterUsage::kTexture,
-    /* matcher_indices */ MatcherIndicesIndex(139),
+    /* matcher_indices */ MatcherIndicesIndex(140),
   },
   {
     /* [98] */
@@ -1655,7 +1677,7 @@
   {
     /* [116] */
     /* usage */ core::ParameterUsage::kTexture,
-    /* matcher_indices */ MatcherIndicesIndex(140),
+    /* matcher_indices */ MatcherIndicesIndex(141),
   },
 };
 
@@ -1702,7 +1724,7 @@
   {
     /* [6] */
     /* name */ "T",
-    /* matcher_indices */ MatcherIndicesIndex(134),
+    /* matcher_indices */ MatcherIndicesIndex(135),
     /* kind */ TemplateInfo::Kind::kType,
   },
   {
@@ -1713,32 +1735,32 @@
   },
   {
     /* [8] */
-    /* name */ "F",
-    /* matcher_indices */ MatcherIndicesIndex(/* invalid */),
-    /* kind */ TemplateInfo::Kind::kNumber,
+    /* name */ "T",
+    /* matcher_indices */ MatcherIndicesIndex(134),
+    /* kind */ TemplateInfo::Kind::kType,
   },
   {
     /* [9] */
-    /* name */ "A",
+    /* name */ "N",
     /* matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* kind */ TemplateInfo::Kind::kNumber,
   },
   {
     /* [10] */
     /* name */ "F",
-    /* matcher_indices */ MatcherIndicesIndex(0),
+    /* matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* kind */ TemplateInfo::Kind::kNumber,
   },
   {
     /* [11] */
     /* name */ "A",
-    /* matcher_indices */ MatcherIndicesIndex(102),
+    /* matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* kind */ TemplateInfo::Kind::kNumber,
   },
   {
     /* [12] */
     /* name */ "F",
-    /* matcher_indices */ MatcherIndicesIndex(66),
+    /* matcher_indices */ MatcherIndicesIndex(0),
     /* kind */ TemplateInfo::Kind::kNumber,
   },
   {
@@ -1750,7 +1772,7 @@
   {
     /* [14] */
     /* name */ "F",
-    /* matcher_indices */ MatcherIndicesIndex(69),
+    /* matcher_indices */ MatcherIndicesIndex(66),
     /* kind */ TemplateInfo::Kind::kNumber,
   },
   {
@@ -1761,14 +1783,14 @@
   },
   {
     /* [16] */
-    /* name */ "T",
-    /* matcher_indices */ MatcherIndicesIndex(141),
-    /* kind */ TemplateInfo::Kind::kType,
+    /* name */ "F",
+    /* matcher_indices */ MatcherIndicesIndex(69),
+    /* kind */ TemplateInfo::Kind::kNumber,
   },
   {
     /* [17] */
-    /* name */ "N",
-    /* matcher_indices */ MatcherIndicesIndex(/* invalid */),
+    /* name */ "A",
+    /* matcher_indices */ MatcherIndicesIndex(102),
     /* kind */ TemplateInfo::Kind::kNumber,
   },
   {
@@ -1786,11 +1808,23 @@
   {
     /* [20] */
     /* name */ "T",
-    /* matcher_indices */ MatcherIndicesIndex(135),
+    /* matcher_indices */ MatcherIndicesIndex(143),
     /* kind */ TemplateInfo::Kind::kType,
   },
   {
     /* [21] */
+    /* name */ "N",
+    /* matcher_indices */ MatcherIndicesIndex(/* invalid */),
+    /* kind */ TemplateInfo::Kind::kNumber,
+  },
+  {
+    /* [22] */
+    /* name */ "T",
+    /* matcher_indices */ MatcherIndicesIndex(136),
+    /* kind */ TemplateInfo::Kind::kType,
+  },
+  {
+    /* [23] */
     /* name */ "C",
     /* matcher_indices */ MatcherIndicesIndex(133),
     /* kind */ TemplateInfo::Kind::kType,
@@ -1815,7 +1849,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(79),
     /* return_matcher_indices */ MatcherIndicesIndex(10),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1826,7 +1860,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(81),
     /* return_matcher_indices */ MatcherIndicesIndex(105),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1837,7 +1871,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(83),
     /* return_matcher_indices */ MatcherIndicesIndex(109),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1848,7 +1882,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(85),
     /* return_matcher_indices */ MatcherIndicesIndex(109),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1859,7 +1893,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(87),
     /* return_matcher_indices */ MatcherIndicesIndex(105),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1870,7 +1904,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(89),
     /* return_matcher_indices */ MatcherIndicesIndex(109),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1925,7 +1959,7 @@
     /* num_parameters */ 1,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(25),
     /* return_matcher_indices */ MatcherIndicesIndex(105),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1947,7 +1981,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(10),
+    /* templates */ TemplateIndex(12),
     /* parameters */ ParameterIndex(99),
     /* return_matcher_indices */ MatcherIndicesIndex(123),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1958,7 +1992,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(10),
+    /* templates */ TemplateIndex(12),
     /* parameters */ ParameterIndex(101),
     /* return_matcher_indices */ MatcherIndicesIndex(123),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1969,7 +2003,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(10),
+    /* templates */ TemplateIndex(12),
     /* parameters */ ParameterIndex(103),
     /* return_matcher_indices */ MatcherIndicesIndex(123),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1980,7 +2014,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(10),
+    /* templates */ TemplateIndex(12),
     /* parameters */ ParameterIndex(105),
     /* return_matcher_indices */ MatcherIndicesIndex(123),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -1991,7 +2025,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(12),
+    /* templates */ TemplateIndex(14),
     /* parameters */ ParameterIndex(99),
     /* return_matcher_indices */ MatcherIndicesIndex(125),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2002,7 +2036,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(12),
+    /* templates */ TemplateIndex(14),
     /* parameters */ ParameterIndex(101),
     /* return_matcher_indices */ MatcherIndicesIndex(125),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2013,7 +2047,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(12),
+    /* templates */ TemplateIndex(14),
     /* parameters */ ParameterIndex(103),
     /* return_matcher_indices */ MatcherIndicesIndex(125),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2024,7 +2058,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(12),
+    /* templates */ TemplateIndex(14),
     /* parameters */ ParameterIndex(105),
     /* return_matcher_indices */ MatcherIndicesIndex(125),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2035,7 +2069,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(14),
+    /* templates */ TemplateIndex(16),
     /* parameters */ ParameterIndex(99),
     /* return_matcher_indices */ MatcherIndicesIndex(127),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2046,7 +2080,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(14),
+    /* templates */ TemplateIndex(16),
     /* parameters */ ParameterIndex(101),
     /* return_matcher_indices */ MatcherIndicesIndex(127),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2057,7 +2091,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(14),
+    /* templates */ TemplateIndex(16),
     /* parameters */ ParameterIndex(103),
     /* return_matcher_indices */ MatcherIndicesIndex(127),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2068,7 +2102,7 @@
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(14),
+    /* templates */ TemplateIndex(16),
     /* parameters */ ParameterIndex(105),
     /* return_matcher_indices */ MatcherIndicesIndex(127),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2079,7 +2113,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(31),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2090,7 +2124,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(34),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2101,7 +2135,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(37),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2112,7 +2146,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(40),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2123,7 +2157,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(43),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2134,7 +2168,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(46),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2145,7 +2179,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(49),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2156,7 +2190,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(52),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2167,7 +2201,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(55),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2178,7 +2212,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(58),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2189,7 +2223,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(61),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2200,7 +2234,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(21),
+    /* templates */ TemplateIndex(23),
     /* parameters */ ParameterIndex(64),
     /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2211,7 +2245,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(16),
     /* return_matcher_indices */ MatcherIndicesIndex(121),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2222,7 +2256,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(19),
     /* return_matcher_indices */ MatcherIndicesIndex(121),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2233,7 +2267,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(22),
     /* return_matcher_indices */ MatcherIndicesIndex(121),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2244,7 +2278,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(25),
     /* return_matcher_indices */ MatcherIndicesIndex(121),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2255,7 +2289,7 @@
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 1,
-    /* templates */ TemplateIndex(20),
+    /* templates */ TemplateIndex(22),
     /* parameters */ ParameterIndex(28),
     /* return_matcher_indices */ MatcherIndicesIndex(121),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2266,7 +2300,7 @@
     /* num_parameters */ 1,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(8),
+    /* templates */ TemplateIndex(10),
     /* parameters */ ParameterIndex(99),
     /* return_matcher_indices */ MatcherIndicesIndex(10),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2277,7 +2311,7 @@
     /* num_parameters */ 1,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(8),
+    /* templates */ TemplateIndex(10),
     /* parameters */ ParameterIndex(101),
     /* return_matcher_indices */ MatcherIndicesIndex(105),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2288,7 +2322,7 @@
     /* num_parameters */ 1,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(8),
+    /* templates */ TemplateIndex(10),
     /* parameters */ ParameterIndex(103),
     /* return_matcher_indices */ MatcherIndicesIndex(109),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2299,7 +2333,7 @@
     /* num_parameters */ 1,
     /* num_explicit_templates */ 0,
     /* num_templates   */ 2,
-    /* templates */ TemplateIndex(8),
+    /* templates */ TemplateIndex(10),
     /* parameters */ ParameterIndex(105),
     /* return_matcher_indices */ MatcherIndicesIndex(109),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
@@ -2460,6 +2494,28 @@
   },
   {
     /* [59] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_explicit_templates */ 0,
+    /* num_templates   */ 1,
+    /* templates */ TemplateIndex(8),
+    /* parameters */ ParameterIndex(68),
+    /* return_matcher_indices */ MatcherIndicesIndex(3),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [60] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 1,
+    /* num_explicit_templates */ 0,
+    /* num_templates   */ 2,
+    /* templates */ TemplateIndex(8),
+    /* parameters */ ParameterIndex(69),
+    /* return_matcher_indices */ MatcherIndicesIndex(44),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
+  {
+    /* [61] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
@@ -2470,7 +2526,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(0),
   },
   {
-    /* [60] */
+    /* [62] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
@@ -2481,7 +2537,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(0),
   },
   {
-    /* [61] */
+    /* [63] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
@@ -2492,7 +2548,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(1),
   },
   {
-    /* [62] */
+    /* [64] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse),
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
@@ -2503,7 +2559,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(1),
   },
   {
-    /* [63] */
+    /* [65] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse, OverloadFlag::kMemberFunction),
     /* num_parameters */ 1,
     /* num_explicit_templates */ 0,
@@ -2514,7 +2570,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [64] */
+    /* [66] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 0,
     /* num_explicit_templates */ 0,
@@ -2525,7 +2581,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [65] */
+    /* [67] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 3,
     /* num_explicit_templates */ 0,
@@ -2536,7 +2592,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [66] */
+    /* [68] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
@@ -2547,7 +2603,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [67] */
+    /* [69] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 1,
     /* num_explicit_templates */ 0,
@@ -2558,7 +2614,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [68] */
+    /* [70] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 1,
     /* num_explicit_templates */ 0,
@@ -2569,7 +2625,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [69] */
+    /* [71] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 1,
     /* num_explicit_templates */ 0,
@@ -2580,7 +2636,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [70] */
+    /* [72] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
@@ -2591,18 +2647,7 @@
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
   {
-    /* [71] */
-    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
-    /* num_parameters */ 2,
-    /* num_explicit_templates */ 0,
-    /* num_templates   */ 2,
-    /* templates */ TemplateIndex(16),
-    /* parameters */ ParameterIndex(69),
-    /* return_matcher_indices */ MatcherIndicesIndex(98),
-    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
-  },
-  {
-    /* [72] */
+    /* [73] */
     /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
     /* num_parameters */ 2,
     /* num_explicit_templates */ 0,
@@ -2612,6 +2657,17 @@
     /* return_matcher_indices */ MatcherIndicesIndex(98),
     /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
   },
+  {
+    /* [74] */
+    /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
+    /* num_parameters */ 2,
+    /* num_explicit_templates */ 0,
+    /* num_templates   */ 2,
+    /* templates */ TemplateIndex(20),
+    /* parameters */ ParameterIndex(69),
+    /* return_matcher_indices */ MatcherIndicesIndex(98),
+    /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */),
+  },
 };
 
 static_assert(OverloadIndex::CanIndex(kOverloads),
@@ -2622,37 +2678,37 @@
     /* [0] */
     /* fn length[T, A : access](ptr<storage, array<T>, A>) -> i32 */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(63),
+    /* overloads */ OverloadIndex(65),
   },
   {
     /* [1] */
     /* fn barrier() */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(64),
+    /* overloads */ OverloadIndex(66),
   },
   {
     /* [2] */
     /* fn memoryBarrierBuffer() */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(64),
+    /* overloads */ OverloadIndex(66),
   },
   {
     /* [3] */
     /* fn memoryBarrierImage() */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(64),
+    /* overloads */ OverloadIndex(66),
   },
   {
     /* [4] */
     /* fn atomicCompSwap[T : iu32](ptr<workgroup_or_storage, atomic<T>, read_write>, compare_value: T, value: T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(65),
+    /* overloads */ OverloadIndex(67),
   },
   {
     /* [5] */
     /* fn atomicSub[T : iu32, S : workgroup_or_storage](ptr<S, atomic<T>, read_write>, T) -> T */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(66),
+    /* overloads */ OverloadIndex(68),
   },
   {
     /* [6] */
@@ -2707,48 +2763,55 @@
     /* [13] */
     /* fn packFloat2x16(value: vec2<f16>) -> u32 */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(67),
+    /* overloads */ OverloadIndex(69),
   },
   {
     /* [14] */
     /* fn unpackFloat2x16(value: u32) -> vec2<f16> */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(68),
-  },
-  {
-    /* [15] */
-    /* fn any[N : num](vec<N, bool>) -> bool */
-    /* num overloads */ 1,
-    /* overloads */ OverloadIndex(69),
-  },
-  {
-    /* [16] */
-    /* fn all[N : num](vec<N, bool>) -> bool */
-    /* num overloads */ 1,
-    /* overloads */ OverloadIndex(69),
-  },
-  {
-    /* [17] */
-    /* fn dot[T : f32_f16, N : num](vec<N, T>, vec<N, T>) -> T */
-    /* num overloads */ 1,
     /* overloads */ OverloadIndex(70),
   },
   {
-    /* [18] */
-    /* fn modf[T : f32_f16](value: T, result: ptr<function, T, read_write>) -> T */
-    /* fn modf[N : num, T : f32_f16](value: vec<N, T>, result: ptr<function, vec<N, T>, read_write>) -> vec<N, T> */
+    /* [15] */
+    /* fn abs[T : fi32_f16](T) -> T */
+    /* fn abs[T : fi32_f16, N : num](vec<N, T>) -> vec<N, T> */
     /* num overloads */ 2,
     /* overloads */ OverloadIndex(59),
   },
   {
+    /* [16] */
+    /* fn any[N : num](vec<N, bool>) -> bool */
+    /* num overloads */ 1,
+    /* overloads */ OverloadIndex(71),
+  },
+  {
+    /* [17] */
+    /* fn all[N : num](vec<N, bool>) -> bool */
+    /* num overloads */ 1,
+    /* overloads */ OverloadIndex(71),
+  },
+  {
+    /* [18] */
+    /* fn dot[T : f32_f16, N : num](vec<N, T>, vec<N, T>) -> T */
+    /* num overloads */ 1,
+    /* overloads */ OverloadIndex(72),
+  },
+  {
     /* [19] */
-    /* fn frexp[T : f32_f16](value: T, exp: ptr<function, i32, read_write>) -> T */
-    /* fn frexp[N : num, T : f32_f16](value: vec<N, T>, exp: ptr<function, vec<N, i32>, read_write>) -> vec<N, T> */
+    /* fn modf[T : f32_f16](value: T, result: ptr<function, T, read_write>) -> T */
+    /* fn modf[N : num, T : f32_f16](value: vec<N, T>, result: ptr<function, vec<N, T>, read_write>) -> vec<N, T> */
     /* num overloads */ 2,
     /* overloads */ OverloadIndex(61),
   },
   {
     /* [20] */
+    /* fn frexp[T : f32_f16](value: T, exp: ptr<function, i32, read_write>) -> T */
+    /* fn frexp[N : num, T : f32_f16](value: vec<N, T>, exp: ptr<function, vec<N, i32>, read_write>) -> vec<N, T> */
+    /* num overloads */ 2,
+    /* overloads */ OverloadIndex(63),
+  },
+  {
+    /* [21] */
     /* fn textureSize[T : fiu32](texture: texture_1d<T>, level: i32) -> i32 */
     /* fn textureSize[T : fiu32](texture: texture_2d<T>, level: i32) -> vec2<i32> */
     /* fn textureSize[T : fiu32](texture: texture_2d_array<T>, level: i32) -> vec3<i32> */
@@ -2765,7 +2828,7 @@
     /* overloads */ OverloadIndex(0),
   },
   {
-    /* [21] */
+    /* [22] */
     /* fn imageSize[F : texel_format, A : access](texture: texture_storage_1d<F, A>) -> i32 */
     /* fn imageSize[F : texel_format, A : access](texture: texture_storage_2d<F, A>) -> vec2<i32> */
     /* fn imageSize[F : texel_format, A : access](texture: texture_storage_2d_array<F, A>) -> vec3<i32> */
@@ -2774,7 +2837,7 @@
     /* overloads */ OverloadIndex(41),
   },
   {
-    /* [22] */
+    /* [23] */
     /* fn texelFetch[T : fiu32](texture: texture_1d<T>, location: i32, level: i32) -> vec4<T> */
     /* fn texelFetch[T : fiu32](texture: texture_2d<T>, location: vec2<i32>, level: i32) -> vec4<T> */
     /* fn texelFetch[T : fiu32](texture: texture_2d_array<T>, location: vec3<i32>, level: i32) -> vec4<T> */
@@ -2784,7 +2847,7 @@
     /* overloads */ OverloadIndex(36),
   },
   {
-    /* [23] */
+    /* [24] */
     /* fn imageLoad[F : f32_texel_format, A : readable](texture: texture_storage_1d<F, A>, coords: i32) -> vec4<f32> */
     /* fn imageLoad[F : f32_texel_format, A : readable](texture: texture_storage_2d<F, A>, coords: vec2<i32>) -> vec4<f32> */
     /* fn imageLoad[F : f32_texel_format, A : readable](texture: texture_storage_2d_array<F, A>, coords: vec3<i32>) -> vec4<f32> */
@@ -2801,7 +2864,7 @@
     /* overloads */ OverloadIndex(12),
   },
   {
-    /* [24] */
+    /* [25] */
     /* fn imageStore[C : iu32](texture: texture_storage_1d<f32_texel_format, writable>, coords: C, value: vec4<f32>) */
     /* fn imageStore[C : iu32](texture: texture_storage_1d<i32_texel_format, writable>, coords: C, value: vec4<i32>) */
     /* fn imageStore[C : iu32](texture: texture_storage_1d<u32_texel_format, writable>, coords: C, value: vec4<u32>) */
@@ -2818,40 +2881,40 @@
     /* overloads */ OverloadIndex(24),
   },
   {
-    /* [25] */
+    /* [26] */
     /* fn lessThan[T : fiu32_f16, N : num](vec<N, T>, vec<N, T>) -> vec<N, bool> */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(71),
-  },
-  {
-    /* [26] */
-    /* fn lessThanEqual[T : fiu32_f16, N : num](vec<N, T>, vec<N, T>) -> vec<N, bool> */
-    /* num overloads */ 1,
-    /* overloads */ OverloadIndex(71),
+    /* overloads */ OverloadIndex(73),
   },
   {
     /* [27] */
-    /* fn greaterThan[T : fiu32_f16, N : num](vec<N, T>, vec<N, T>) -> vec<N, bool> */
+    /* fn lessThanEqual[T : fiu32_f16, N : num](vec<N, T>, vec<N, T>) -> vec<N, bool> */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(71),
+    /* overloads */ OverloadIndex(73),
   },
   {
     /* [28] */
-    /* fn greaterThanEqual[T : fiu32_f16, N : num](vec<N, T>, vec<N, T>) -> vec<N, bool> */
+    /* fn greaterThan[T : fiu32_f16, N : num](vec<N, T>, vec<N, T>) -> vec<N, bool> */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(71),
+    /* overloads */ OverloadIndex(73),
   },
   {
     /* [29] */
-    /* fn equal[T : fiu32_f16_bool, N : num](vec<N, T>, vec<N, T>) -> vec<N, bool> */
+    /* fn greaterThanEqual[T : fiu32_f16, N : num](vec<N, T>, vec<N, T>) -> vec<N, bool> */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(72),
+    /* overloads */ OverloadIndex(73),
   },
   {
     /* [30] */
+    /* fn equal[T : fiu32_f16_bool, N : num](vec<N, T>, vec<N, T>) -> vec<N, bool> */
+    /* num overloads */ 1,
+    /* overloads */ OverloadIndex(74),
+  },
+  {
+    /* [31] */
     /* fn notEqual[T : fiu32_f16_bool, N : num](vec<N, T>, vec<N, T>) -> vec<N, bool> */
     /* num overloads */ 1,
-    /* overloads */ OverloadIndex(72),
+    /* overloads */ OverloadIndex(74),
   },
 };
 
diff --git a/src/tint/lang/glsl/writer/builtin_test.cc b/src/tint/lang/glsl/writer/builtin_test.cc
index 529f8c3..d2d0045 100644
--- a/src/tint/lang/glsl/writer/builtin_test.cc
+++ b/src/tint/lang/glsl/writer/builtin_test.cc
@@ -1662,5 +1662,39 @@
 )");
 }
 
+TEST_F(GlslWriterTest, AbsScalar) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        b.Let("x", b.Call(ty.u32(), core::BuiltinFn::kAbs, 2_u));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(precision highp float;
+precision highp int;
+
+void main() {
+  uint x = 2u;
+}
+)");
+}
+
+TEST_F(GlslWriterTest, AbsVector) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        b.Let("x", b.Call(ty.vec2<u32>(), core::BuiltinFn::kAbs, b.Splat<vec2<u32>>(2_u)));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(precision highp float;
+precision highp int;
+
+void main() {
+  uvec2 x = uvec2(2u);
+}
+)");
+}
+
 }  // namespace
 }  // namespace tint::glsl::writer
diff --git a/src/tint/lang/glsl/writer/raise/builtin_polyfill.cc b/src/tint/lang/glsl/writer/raise/builtin_polyfill.cc
index d2ce2a7..cff2d85 100644
--- a/src/tint/lang/glsl/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/glsl/writer/raise/builtin_polyfill.cc
@@ -71,6 +71,7 @@
         for (auto* inst : ir.Instructions()) {
             if (auto* call = inst->As<core::ir::CoreBuiltinCall>()) {
                 switch (call->Func()) {
+                    case core::BuiltinFn::kAbs:
                     case core::BuiltinFn::kAll:
                     case core::BuiltinFn::kAny:
                     case core::BuiltinFn::kArrayLength:
@@ -104,6 +105,9 @@
         // Replace the builtin calls that we found
         for (auto* call : call_worklist) {
             switch (call->Func()) {
+                case core::BuiltinFn::kAbs:
+                    Abs(call);
+                    break;
                 case core::BuiltinFn::kAll:
                     All(call);
                     break;
@@ -169,6 +173,21 @@
         }
     }
 
+    void Abs(core::ir::BuiltinCall* call) {
+        auto args = call->Args();
+
+        if (args[0]->Type()->DeepestElement()->IsUnsignedIntegerScalarOrVector()) {
+            // GLSL does not support `abs` on unsigned arguments, replace it with the arg.
+            call->Result(0)->ReplaceAllUsesWith(args[0]);
+        } else {
+            b.InsertBefore(call, [&] {
+                b.CallWithResult<glsl::ir::BuiltinCall>(call->DetachResult(), glsl::BuiltinFn::kAbs,
+                                                        args[0]);
+            });
+        }
+        call->Destroy();
+    }
+
     void Any(core::ir::BuiltinCall* call) {
         auto args = call->Args();
 
diff --git a/src/tint/lang/glsl/writer/raise/builtin_polyfill_test.cc b/src/tint/lang/glsl/writer/raise/builtin_polyfill_test.cc
index 351ba86..0e233a6 100644
--- a/src/tint/lang/glsl/writer/raise/builtin_polyfill_test.cc
+++ b/src/tint/lang/glsl/writer/raise/builtin_polyfill_test.cc
@@ -1927,5 +1927,67 @@
     EXPECT_EQ(expect, str());
 }
 
+TEST_F(GlslWriter_BuiltinPolyfillTest, AbsScalar) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        b.Let("x", b.Call(ty.u32(), core::BuiltinFn::kAbs, 2_u));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:u32 = abs 2u
+    %x:u32 = let %2
+    ret
+  }
+}
+)";
+    ASSERT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %x:u32 = let 2u
+    ret
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(GlslWriter_BuiltinPolyfillTest, AbsVector) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+    b.Append(func->Block(), [&] {
+        b.Let("x", b.Call(ty.vec2<u32>(), core::BuiltinFn::kAbs, b.Splat<vec2<u32>>(2_u)));
+        b.Return(func);
+    });
+
+    auto* src = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %2:vec2<u32> = abs vec2<u32>(2u)
+    %x:vec2<u32> = let %2
+    ret
+  }
+}
+)";
+    ASSERT_EQ(src, str());
+
+    auto* expect = R"(
+%foo = @fragment func():void {
+  $B1: {
+    %x:vec2<u32> = let vec2<u32>(2u)
+    ret
+  }
+}
+)";
+
+    Run(BuiltinPolyfill);
+    EXPECT_EQ(expect, str());
+}
+
 }  // namespace
 }  // namespace tint::glsl::writer::raise
diff --git a/src/tint/lang/glsl/writer/raise/raise.cc b/src/tint/lang/glsl/writer/raise/raise.cc
index cb64e23..e67e469 100644
--- a/src/tint/lang/glsl/writer/raise/raise.cc
+++ b/src/tint/lang/glsl/writer/raise/raise.cc
@@ -124,6 +124,9 @@
         RUN_TRANSFORM(core::ir::transform::ZeroInitWorkgroupMemory, module);
     }
 
+    // DemoteToHelper must come before any transform that introduces non-core instructions.
+    RUN_TRANSFORM(core::ir::transform::DemoteToHelper, module);
+
     RUN_TRANSFORM(raise::BinaryPolyfill, module);
     // Must come after zero-init as it will add builtins
     RUN_TRANSFORM(raise::BuiltinPolyfill, module);
@@ -134,9 +137,6 @@
     RUN_TRANSFORM(core::ir::transform::VectorizeScalarMatrixConstructors, module);
     RUN_TRANSFORM(core::ir::transform::RemoveContinueInSwitch, module);
 
-    // DemoteToHelper must come before any transform that introduces non-core instructions.
-    RUN_TRANSFORM(core::ir::transform::DemoteToHelper, module);
-
     RUN_TRANSFORM(core::ir::transform::AddEmptyEntryPoint, module);
 
     RUN_TRANSFORM(raise::ShaderIO, module, raise::ShaderIOConfig{options.depth_range_offsets});
diff --git a/test/tint/bug/tint/2147.wgsl.expected.ir.glsl b/test/tint/bug/tint/2147.wgsl.expected.ir.glsl
index 4fd7f3d..a48caf2 100644
--- a/test/tint/bug/tint/2147.wgsl.expected.ir.glsl
+++ b/test/tint/bug/tint/2147.wgsl.expected.ir.glsl
@@ -1,11 +1,35 @@
-SKIP: FAILED
+#version 310 es
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/core/ir/transform/demote_to_helper.cc:208 internal compiler error: TINT_UNREACHABLE unexpected non-core instruction
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
 
-tint executable returned error: signal: trace/BPT trap
+struct atomic_compare_exchange_result_i32 {
+  int old_value;
+  bool exchanged;
+};
+
+layout(binding = 0, std430)
+buffer tint_symbol_2_1_ssbo {
+  int tint_symbol_1;
+} v;
+bool continue_execution = true;
+layout(location = 0) out vec4 tint_symbol_loc0_Output;
+vec4 tint_symbol_inner() {
+  if (false) {
+    continue_execution = false;
+  }
+  atomic_compare_exchange_result_i32 v_1 = atomic_compare_exchange_result_i32(0, false);
+  if (continue_execution) {
+    int v_2 = atomicCompSwap(v.tint_symbol_1, 0, 1);
+    v_1 = atomic_compare_exchange_result_i32(v_2, (v_2 == 0));
+  }
+  int old_value = v_1.old_value;
+  vec4 v_3 = vec4(float(old_value));
+  if (!(continue_execution)) {
+    discard;
+  }
+  return v_3;
+}
+void main() {
+  tint_symbol_loc0_Output = tint_symbol_inner();
+}
diff --git a/test/tint/builtins/gen/var/abs/1ce782.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/abs/1ce782.wgsl.expected.ir.glsl
index 4b12f5d..c13466b 100644
--- a/test/tint/builtins/gen/var/abs/1ce782.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/abs/1ce782.wgsl.expected.ir.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 #version 310 es
 precision highp float;
 precision highp int;
@@ -10,20 +8,12 @@
 } v;
 uvec4 abs_1ce782() {
   uvec4 arg_0 = uvec4(1u);
-  uvec4 res = abs(arg_0);
+  uvec4 res = arg_0;
   return res;
 }
 void main() {
   v.tint_symbol = abs_1ce782();
 }
-error: Error parsing GLSL shader:
-ERROR: 0:11: 'abs' : no matching overloaded function found 
-ERROR: 0:11: '=' :  cannot convert from ' const float' to ' temp highp 4-component vector of uint'
-ERROR: 0:11: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
 #version 310 es
 
 layout(binding = 0, std430)
@@ -32,21 +22,13 @@
 } v;
 uvec4 abs_1ce782() {
   uvec4 arg_0 = uvec4(1u);
-  uvec4 res = abs(arg_0);
+  uvec4 res = arg_0;
   return res;
 }
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 void main() {
   v.tint_symbol = abs_1ce782();
 }
-error: Error parsing GLSL shader:
-ERROR: 0:9: 'abs' : no matching overloaded function found 
-ERROR: 0:9: '=' :  cannot convert from ' const float' to ' temp highp 4-component vector of uint'
-ERROR: 0:9: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
 #version 310 es
 
 
@@ -58,7 +40,7 @@
 layout(location = 0) flat out uvec4 vertex_main_loc0_Output;
 uvec4 abs_1ce782() {
   uvec4 arg_0 = uvec4(1u);
-  uvec4 res = abs(arg_0);
+  uvec4 res = arg_0;
   return res;
 }
 VertexOutput vertex_main_inner() {
@@ -75,13 +57,3 @@
   vertex_main_loc0_Output = v.prevent_dce;
   gl_PointSize = 1.0f;
 }
-error: Error parsing GLSL shader:
-ERROR: 0:12: 'abs' : no matching overloaded function found 
-ERROR: 0:12: '=' :  cannot convert from ' const float' to ' temp highp 4-component vector of uint'
-ERROR: 0:12: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
-
-tint executable returned error: exit status 1
diff --git a/test/tint/builtins/gen/var/abs/467cd1.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/abs/467cd1.wgsl.expected.ir.glsl
index b547e39..bb28c94 100644
--- a/test/tint/builtins/gen/var/abs/467cd1.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/abs/467cd1.wgsl.expected.ir.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 #version 310 es
 precision highp float;
 precision highp int;
@@ -10,20 +8,12 @@
 } v;
 uint abs_467cd1() {
   uint arg_0 = 1u;
-  uint res = abs(arg_0);
+  uint res = arg_0;
   return res;
 }
 void main() {
   v.tint_symbol = abs_467cd1();
 }
-error: Error parsing GLSL shader:
-ERROR: 0:11: 'abs' : no matching overloaded function found 
-ERROR: 0:11: '=' :  cannot convert from ' const float' to ' temp highp uint'
-ERROR: 0:11: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
 #version 310 es
 
 layout(binding = 0, std430)
@@ -32,21 +22,13 @@
 } v;
 uint abs_467cd1() {
   uint arg_0 = 1u;
-  uint res = abs(arg_0);
+  uint res = arg_0;
   return res;
 }
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 void main() {
   v.tint_symbol = abs_467cd1();
 }
-error: Error parsing GLSL shader:
-ERROR: 0:9: 'abs' : no matching overloaded function found 
-ERROR: 0:9: '=' :  cannot convert from ' const float' to ' temp highp uint'
-ERROR: 0:9: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
 #version 310 es
 
 
@@ -58,7 +40,7 @@
 layout(location = 0) flat out uint vertex_main_loc0_Output;
 uint abs_467cd1() {
   uint arg_0 = 1u;
-  uint res = abs(arg_0);
+  uint res = arg_0;
   return res;
 }
 VertexOutput vertex_main_inner() {
@@ -75,13 +57,3 @@
   vertex_main_loc0_Output = v.prevent_dce;
   gl_PointSize = 1.0f;
 }
-error: Error parsing GLSL shader:
-ERROR: 0:12: 'abs' : no matching overloaded function found 
-ERROR: 0:12: '=' :  cannot convert from ' const float' to ' temp highp uint'
-ERROR: 0:12: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
-
-tint executable returned error: exit status 1
diff --git a/test/tint/builtins/gen/var/abs/7326de.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/abs/7326de.wgsl.expected.ir.glsl
index 210019f..d001d95 100644
--- a/test/tint/builtins/gen/var/abs/7326de.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/abs/7326de.wgsl.expected.ir.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 #version 310 es
 precision highp float;
 precision highp int;
@@ -10,20 +8,12 @@
 } v;
 uvec3 abs_7326de() {
   uvec3 arg_0 = uvec3(1u);
-  uvec3 res = abs(arg_0);
+  uvec3 res = arg_0;
   return res;
 }
 void main() {
   v.tint_symbol = abs_7326de();
 }
-error: Error parsing GLSL shader:
-ERROR: 0:11: 'abs' : no matching overloaded function found 
-ERROR: 0:11: '=' :  cannot convert from ' const float' to ' temp highp 3-component vector of uint'
-ERROR: 0:11: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
 #version 310 es
 
 layout(binding = 0, std430)
@@ -32,21 +22,13 @@
 } v;
 uvec3 abs_7326de() {
   uvec3 arg_0 = uvec3(1u);
-  uvec3 res = abs(arg_0);
+  uvec3 res = arg_0;
   return res;
 }
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 void main() {
   v.tint_symbol = abs_7326de();
 }
-error: Error parsing GLSL shader:
-ERROR: 0:9: 'abs' : no matching overloaded function found 
-ERROR: 0:9: '=' :  cannot convert from ' const float' to ' temp highp 3-component vector of uint'
-ERROR: 0:9: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
 #version 310 es
 
 
@@ -58,7 +40,7 @@
 layout(location = 0) flat out uvec3 vertex_main_loc0_Output;
 uvec3 abs_7326de() {
   uvec3 arg_0 = uvec3(1u);
-  uvec3 res = abs(arg_0);
+  uvec3 res = arg_0;
   return res;
 }
 VertexOutput vertex_main_inner() {
@@ -75,13 +57,3 @@
   vertex_main_loc0_Output = v.prevent_dce;
   gl_PointSize = 1.0f;
 }
-error: Error parsing GLSL shader:
-ERROR: 0:12: 'abs' : no matching overloaded function found 
-ERROR: 0:12: '=' :  cannot convert from ' const float' to ' temp highp 3-component vector of uint'
-ERROR: 0:12: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
-
-tint executable returned error: exit status 1
diff --git a/test/tint/builtins/gen/var/abs/7f28e6.wgsl.expected.ir.glsl b/test/tint/builtins/gen/var/abs/7f28e6.wgsl.expected.ir.glsl
index 11fade6..1ee020b 100644
--- a/test/tint/builtins/gen/var/abs/7f28e6.wgsl.expected.ir.glsl
+++ b/test/tint/builtins/gen/var/abs/7f28e6.wgsl.expected.ir.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 #version 310 es
 precision highp float;
 precision highp int;
@@ -10,20 +8,12 @@
 } v;
 uvec2 abs_7f28e6() {
   uvec2 arg_0 = uvec2(1u);
-  uvec2 res = abs(arg_0);
+  uvec2 res = arg_0;
   return res;
 }
 void main() {
   v.tint_symbol = abs_7f28e6();
 }
-error: Error parsing GLSL shader:
-ERROR: 0:11: 'abs' : no matching overloaded function found 
-ERROR: 0:11: '=' :  cannot convert from ' const float' to ' temp highp 2-component vector of uint'
-ERROR: 0:11: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
 #version 310 es
 
 layout(binding = 0, std430)
@@ -32,21 +22,13 @@
 } v;
 uvec2 abs_7f28e6() {
   uvec2 arg_0 = uvec2(1u);
-  uvec2 res = abs(arg_0);
+  uvec2 res = arg_0;
   return res;
 }
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 void main() {
   v.tint_symbol = abs_7f28e6();
 }
-error: Error parsing GLSL shader:
-ERROR: 0:9: 'abs' : no matching overloaded function found 
-ERROR: 0:9: '=' :  cannot convert from ' const float' to ' temp highp 2-component vector of uint'
-ERROR: 0:9: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
 #version 310 es
 
 
@@ -58,7 +40,7 @@
 layout(location = 0) flat out uvec2 vertex_main_loc0_Output;
 uvec2 abs_7f28e6() {
   uvec2 arg_0 = uvec2(1u);
-  uvec2 res = abs(arg_0);
+  uvec2 res = arg_0;
   return res;
 }
 VertexOutput vertex_main_inner() {
@@ -75,13 +57,3 @@
   vertex_main_loc0_Output = v.prevent_dce;
   gl_PointSize = 1.0f;
 }
-error: Error parsing GLSL shader:
-ERROR: 0:12: 'abs' : no matching overloaded function found 
-ERROR: 0:12: '=' :  cannot convert from ' const float' to ' temp highp 2-component vector of uint'
-ERROR: 0:12: '' : compilation terminated 
-ERROR: 3 compilation errors.  No code generated.
-
-
-
-
-tint executable returned error: exit status 1
diff --git a/test/tint/statements/discard/atomic_cmpxchg.wgsl.expected.ir.glsl b/test/tint/statements/discard/atomic_cmpxchg.wgsl.expected.ir.glsl
index 4fd7f3d..5b37541 100644
--- a/test/tint/statements/discard/atomic_cmpxchg.wgsl.expected.ir.glsl
+++ b/test/tint/statements/discard/atomic_cmpxchg.wgsl.expected.ir.glsl
@@ -1,11 +1,36 @@
-SKIP: FAILED
+#version 310 es
+precision highp float;
+precision highp int;
 
-<dawn>/src/tint/lang/core/ir/transform/demote_to_helper.cc:208 internal compiler error: TINT_UNREACHABLE unexpected non-core instruction
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
 
-tint executable returned error: signal: trace/BPT trap
+struct atomic_compare_exchange_result_i32 {
+  int old_value;
+  bool exchanged;
+};
+
+layout(binding = 0, std430)
+buffer tint_symbol_1_1_ssbo {
+  int tint_symbol;
+} v;
+bool continue_execution = true;
+layout(location = 0) out int foo_loc0_Output;
+int foo_inner() {
+  continue_execution = false;
+  int x = 0;
+  atomic_compare_exchange_result_i32 v_1 = atomic_compare_exchange_result_i32(0, false);
+  if (continue_execution) {
+    int v_2 = atomicCompSwap(v.tint_symbol, 0, 1);
+    v_1 = atomic_compare_exchange_result_i32(v_2, (v_2 == 0));
+  }
+  atomic_compare_exchange_result_i32 result = v_1;
+  if (result.exchanged) {
+    x = result.old_value;
+  }
+  if (!(continue_execution)) {
+    discard;
+  }
+  return x;
+}
+void main() {
+  foo_loc0_Output = foo_inner();
+}