tint/intrinsics.def: Add @test_value() annotation

Specifies the value to use for argument values when generating end-to-end tests.

Use this to provide a legal value for atanh().

Change-Id: I008050c856f9d687ab918c68e90678c4e74f3a1d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/106887
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index 54f2a85..9718405 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -423,8 +423,8 @@
 @const fn atan<N: num, T: fa_f32_f16>(vec<N, T>) -> vec<N, T>
 @const fn atan2<T: fa_f32_f16>(T, T) -> T
 @const fn atan2<T: fa_f32_f16, N: num>(vec<N, T>, vec<N, T>) -> vec<N, T>
-fn atanh<T: f32_f16>(T) -> T
-fn atanh<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
+fn atanh<T: f32_f16>(@test_value(0.5) T) -> T
+fn atanh<N: num, T: f32_f16>(@test_value(0.5) vec<N, T>) -> vec<N, T>
 fn ceil<T: f32_f16>(T) -> T
 fn ceil<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
 @const fn clamp<T: fia_fiu32_f16>(T, T, T) -> T
diff --git a/src/tint/resolver/intrinsic_table.inl b/src/tint/resolver/intrinsic_table.inl
index 361a669..e7b2178f 100644
--- a/src/tint/resolver/intrinsic_table.inl
+++ b/src/tint/resolver/intrinsic_table.inl
@@ -13997,8 +13997,8 @@
   },
   {
     /* [10] */
-    /* fn atanh<T : f32_f16>(T) -> T */
-    /* fn atanh<N : num, T : f32_f16>(vec<N, T>) -> vec<N, T> */
+    /* fn atanh<T : f32_f16>(@test_value(0.5) T) -> T */
+    /* fn atanh<N : num, T : f32_f16>(@test_value(0.5) vec<N, T>) -> vec<N, T> */
     /* num overloads */ 2,
     /* overloads */ &kOverloads[404],
   },
diff --git a/test/tint/builtins/gen/gen.wgsl.tmpl b/test/tint/builtins/gen/gen.wgsl.tmpl
index da23064..3c30474 100644
--- a/test/tint/builtins/gen/gen.wgsl.tmpl
+++ b/test/tint/builtins/gen/gen.wgsl.tmpl
@@ -265,17 +265,22 @@
 {{- /* Returns a value that can be used for the parameter argument        */ -}}
 {{- /* ------------------------------------------------------------------ */ -}}
 {{-   $ty := .Type -}}
-{{-   if      eq $ty.Target.Name "i32"  -}}1i
-{{-   else if eq $ty.Target.Name "u32"  -}}1u
-{{-   else if eq $ty.Target.Name "f32"  -}}1.f
-{{-   else if eq $ty.Target.Name "fa"   -}}1
-{{-   else if eq $ty.Target.Name "ia"   -}}1.0
+{{-   $value := printf "%v" .TestValue }}
+{{- /* $float_value is $value with a '.' suffix (if it wasn't a float already) */ -}}
+{{-   $float_value := $value }}
+{{-   if not (Contains $value ".") }}{{$float_value = printf "%v." $value}}{{end}}
+{{- /* emit the value with any necessary suffixes */ -}}
+{{-   if      eq $ty.Target.Name "i32"  -}}{{$value}}i
+{{-   else if eq $ty.Target.Name "u32"  -}}{{$value}}u
+{{-   else if eq $ty.Target.Name "f32"  -}}{{$float_value}}f
+{{-   else if eq $ty.Target.Name "fa"   -}}{{$value}}
+{{-   else if eq $ty.Target.Name "ia"   -}}{{$float_value}}0
 {{-   else if eq $ty.Target.Name "bool" -}}true
 {{-   else if eq $ty.Target.Name "vec"  -}}
-{{-     $el := Eval "ArgumentValue" "Type" (ElementType .Type) "Name" ""}}
+{{-     $el := Eval "ArgumentValue" "Type" (ElementType .Type) "Name" "" "TestValue" .TestValue }}
 {{-     template "Type" $ty}}({{$el}})
 {{-   else if eq $ty.Target.Name "mat"   -}}{{template "Type" $ty}}(
-{{-     $el := Eval "ArgumentValue" "Type" (ElementType .Type) "Name" ""}}
+{{-     $el := Eval "ArgumentValue" "Type" (ElementType .Type) "Name" "" "TestValue" .TestValue }}
 {{-     range $col := Iterate (index $ty.TemplateArguments 0)     }}
 {{-       range $row := Iterate (index $ty.TemplateArguments 1)   }}
 {{-         if or $col $row -}}, {{end}}{{$el}}
diff --git a/test/tint/builtins/gen/literal/atanh/440cca.wgsl b/test/tint/builtins/gen/literal/atanh/440cca.wgsl
index 508c4d8..2ed2e89 100644
--- a/test/tint/builtins/gen/literal/atanh/440cca.wgsl
+++ b/test/tint/builtins/gen/literal/atanh/440cca.wgsl
@@ -23,7 +23,7 @@
 
 // fn atanh(vec<3, f32>) -> vec<3, f32>
 fn atanh_440cca() {
-  var res: vec3<f32> = atanh(vec3<f32>(1.f));
+  var res: vec3<f32> = atanh(vec3<f32>(0.5f));
 }
 
 @vertex
diff --git a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.dxc.hlsl
index 62b4e58..9359293 100644
--- a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.dxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_440cca() {
-  float3 res = tint_atanh((1.0f).xxx);
+  float3 res = tint_atanh((0.5f).xxx);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.fxc.hlsl
index 62b4e58..9359293 100644
--- a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.fxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_440cca() {
-  float3 res = tint_atanh((1.0f).xxx);
+  float3 res = tint_atanh((0.5f).xxx);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.glsl b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.glsl
index b94d529..ec207ee 100644
--- a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.glsl
@@ -5,7 +5,7 @@
 }
 
 void atanh_440cca() {
-  vec3 res = tint_atanh(vec3(1.0f));
+  vec3 res = tint_atanh(vec3(0.5f));
 }
 
 vec4 vertex_main() {
@@ -29,7 +29,7 @@
 }
 
 void atanh_440cca() {
-  vec3 res = tint_atanh(vec3(1.0f));
+  vec3 res = tint_atanh(vec3(0.5f));
 }
 
 void fragment_main() {
@@ -47,7 +47,7 @@
 }
 
 void atanh_440cca() {
-  vec3 res = tint_atanh(vec3(1.0f));
+  vec3 res = tint_atanh(vec3(0.5f));
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.msl b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.msl
index 3d36649..929e177 100644
--- a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.msl
@@ -6,7 +6,7 @@
 }
 
 void atanh_440cca() {
-  float3 res = tint_atanh(float3(1.0f));
+  float3 res = tint_atanh(float3(0.5f));
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.spvasm
index c2c163d..a0b1acc 100644
--- a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 43
+; Bound: 45
 ; Schema: 0
                OpCapability Shader
          %22 = OpExtInstImport "GLSL.std.450"
@@ -40,8 +40,10 @@
          %20 = OpConstantNull %v3float
        %void = OpTypeVoid
          %23 = OpTypeFunction %void
+  %float_0_5 = OpConstant %float 0.5
+         %29 = OpConstantComposite %v3float %float_0_5 %float_0_5 %float_0_5
 %_ptr_Function_v3float = OpTypePointer Function %v3float
-         %30 = OpTypeFunction %v4float
+         %32 = OpTypeFunction %v4float
  %tint_atanh = OpFunction %v3float None %9
           %x = OpFunctionParameter %v3float
          %13 = OpLabel
@@ -53,29 +55,29 @@
 %atanh_440cca = OpFunction %void None %23
          %26 = OpLabel
         %res = OpVariable %_ptr_Function_v3float Function %20
-         %27 = OpFunctionCall %v3float %tint_atanh %16
+         %27 = OpFunctionCall %v3float %tint_atanh %29
                OpStore %res %27
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %30
-         %32 = OpLabel
-         %33 = OpFunctionCall %void %atanh_440cca
+%vertex_main_inner = OpFunction %v4float None %32
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %atanh_440cca
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %23
-         %35 = OpLabel
-         %36 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %36
+         %37 = OpLabel
+         %38 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %38
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %23
-         %38 = OpLabel
-         %39 = OpFunctionCall %void %atanh_440cca
+         %40 = OpLabel
+         %41 = OpFunctionCall %void %atanh_440cca
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %23
-         %41 = OpLabel
-         %42 = OpFunctionCall %void %atanh_440cca
+         %43 = OpLabel
+         %44 = OpFunctionCall %void %atanh_440cca
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.wgsl
index 4426080..f340950 100644
--- a/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.wgsl
+++ b/test/tint/builtins/gen/literal/atanh/440cca.wgsl.expected.wgsl
@@ -1,5 +1,5 @@
 fn atanh_440cca() {
-  var res : vec3<f32> = atanh(vec3<f32>(1.0f));
+  var res : vec3<f32> = atanh(vec3<f32>(0.5f));
 }
 
 @vertex
diff --git a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl
index 1fc4412..a2c969a 100644
--- a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl
+++ b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl
@@ -23,7 +23,7 @@
 
 // fn atanh(f32) -> f32
 fn atanh_7997d8() {
-  var res: f32 = atanh(1.f);
+  var res: f32 = atanh(0.5f);
 }
 
 @vertex
diff --git a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.dxc.hlsl
index 76a5352..eb5bf96 100644
--- a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.dxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_7997d8() {
-  float res = tint_atanh(1.0f);
+  float res = tint_atanh(0.5f);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.fxc.hlsl
index 76a5352..eb5bf96 100644
--- a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.fxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_7997d8() {
-  float res = tint_atanh(1.0f);
+  float res = tint_atanh(0.5f);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.glsl b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.glsl
index f73d0d7..6a74200 100644
--- a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.glsl
@@ -5,7 +5,7 @@
 }
 
 void atanh_7997d8() {
-  float res = tint_atanh(1.0f);
+  float res = tint_atanh(0.5f);
 }
 
 vec4 vertex_main() {
@@ -29,7 +29,7 @@
 }
 
 void atanh_7997d8() {
-  float res = tint_atanh(1.0f);
+  float res = tint_atanh(0.5f);
 }
 
 void fragment_main() {
@@ -47,7 +47,7 @@
 }
 
 void atanh_7997d8() {
-  float res = tint_atanh(1.0f);
+  float res = tint_atanh(0.5f);
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.msl b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.msl
index ec298cf..147d54a 100644
--- a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.msl
@@ -6,7 +6,7 @@
 }
 
 void atanh_7997d8() {
-  float res = tint_atanh(1.0f);
+  float res = tint_atanh(0.5f);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.spvasm
index 9910eed..8274b37 100644
--- a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 39
+; Bound: 40
 ; Schema: 0
                OpCapability Shader
          %18 = OpExtInstImport "GLSL.std.450"
@@ -36,8 +36,9 @@
        %bool = OpTypeBool
        %void = OpTypeVoid
          %19 = OpTypeFunction %void
+  %float_0_5 = OpConstant %float 0.5
 %_ptr_Function_float = OpTypePointer Function %float
-         %26 = OpTypeFunction %v4float
+         %27 = OpTypeFunction %v4float
  %tint_atanh = OpFunction %float None %9
           %x = OpFunctionParameter %float
          %12 = OpLabel
@@ -49,29 +50,29 @@
 %atanh_7997d8 = OpFunction %void None %19
          %22 = OpLabel
         %res = OpVariable %_ptr_Function_float Function %8
-         %23 = OpFunctionCall %float %tint_atanh %float_1
+         %23 = OpFunctionCall %float %tint_atanh %float_0_5
                OpStore %res %23
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %26
-         %28 = OpLabel
-         %29 = OpFunctionCall %void %atanh_7997d8
+%vertex_main_inner = OpFunction %v4float None %27
+         %29 = OpLabel
+         %30 = OpFunctionCall %void %atanh_7997d8
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %19
-         %31 = OpLabel
-         %32 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %32
+         %32 = OpLabel
+         %33 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %33
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %19
-         %34 = OpLabel
-         %35 = OpFunctionCall %void %atanh_7997d8
+         %35 = OpLabel
+         %36 = OpFunctionCall %void %atanh_7997d8
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %19
-         %37 = OpLabel
-         %38 = OpFunctionCall %void %atanh_7997d8
+         %38 = OpLabel
+         %39 = OpFunctionCall %void %atanh_7997d8
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.wgsl
index dcf31c2..c395d17 100644
--- a/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.wgsl
+++ b/test/tint/builtins/gen/literal/atanh/7997d8.wgsl.expected.wgsl
@@ -1,5 +1,5 @@
 fn atanh_7997d8() {
-  var res : f32 = atanh(1.0f);
+  var res : f32 = atanh(0.5f);
 }
 
 @vertex
diff --git a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl
index 9a9eb9d..26654e7 100644
--- a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl
+++ b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl
@@ -23,7 +23,7 @@
 
 // fn atanh(vec<2, f32>) -> vec<2, f32>
 fn atanh_c0e634() {
-  var res: vec2<f32> = atanh(vec2<f32>(1.f));
+  var res: vec2<f32> = atanh(vec2<f32>(0.5f));
 }
 
 @vertex
diff --git a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.dxc.hlsl
index 961f86a..4342cb0 100644
--- a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.dxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_c0e634() {
-  float2 res = tint_atanh((1.0f).xx);
+  float2 res = tint_atanh((0.5f).xx);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.fxc.hlsl
index 961f86a..4342cb0 100644
--- a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.fxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_c0e634() {
-  float2 res = tint_atanh((1.0f).xx);
+  float2 res = tint_atanh((0.5f).xx);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.glsl b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.glsl
index af242ca..1e9ca1a 100644
--- a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.glsl
@@ -5,7 +5,7 @@
 }
 
 void atanh_c0e634() {
-  vec2 res = tint_atanh(vec2(1.0f));
+  vec2 res = tint_atanh(vec2(0.5f));
 }
 
 vec4 vertex_main() {
@@ -29,7 +29,7 @@
 }
 
 void atanh_c0e634() {
-  vec2 res = tint_atanh(vec2(1.0f));
+  vec2 res = tint_atanh(vec2(0.5f));
 }
 
 void fragment_main() {
@@ -47,7 +47,7 @@
 }
 
 void atanh_c0e634() {
-  vec2 res = tint_atanh(vec2(1.0f));
+  vec2 res = tint_atanh(vec2(0.5f));
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.msl b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.msl
index d5c6b49..bc96c02 100644
--- a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.msl
@@ -6,7 +6,7 @@
 }
 
 void atanh_c0e634() {
-  float2 res = tint_atanh(float2(1.0f));
+  float2 res = tint_atanh(float2(0.5f));
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.spvasm
index 4cc3fa4..5fea132 100644
--- a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 43
+; Bound: 45
 ; Schema: 0
                OpCapability Shader
          %22 = OpExtInstImport "GLSL.std.450"
@@ -40,8 +40,10 @@
          %20 = OpConstantNull %v2float
        %void = OpTypeVoid
          %23 = OpTypeFunction %void
+  %float_0_5 = OpConstant %float 0.5
+         %29 = OpConstantComposite %v2float %float_0_5 %float_0_5
 %_ptr_Function_v2float = OpTypePointer Function %v2float
-         %30 = OpTypeFunction %v4float
+         %32 = OpTypeFunction %v4float
  %tint_atanh = OpFunction %v2float None %9
           %x = OpFunctionParameter %v2float
          %13 = OpLabel
@@ -53,29 +55,29 @@
 %atanh_c0e634 = OpFunction %void None %23
          %26 = OpLabel
         %res = OpVariable %_ptr_Function_v2float Function %20
-         %27 = OpFunctionCall %v2float %tint_atanh %16
+         %27 = OpFunctionCall %v2float %tint_atanh %29
                OpStore %res %27
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %30
-         %32 = OpLabel
-         %33 = OpFunctionCall %void %atanh_c0e634
+%vertex_main_inner = OpFunction %v4float None %32
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %atanh_c0e634
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %23
-         %35 = OpLabel
-         %36 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %36
+         %37 = OpLabel
+         %38 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %38
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %23
-         %38 = OpLabel
-         %39 = OpFunctionCall %void %atanh_c0e634
+         %40 = OpLabel
+         %41 = OpFunctionCall %void %atanh_c0e634
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %23
-         %41 = OpLabel
-         %42 = OpFunctionCall %void %atanh_c0e634
+         %43 = OpLabel
+         %44 = OpFunctionCall %void %atanh_c0e634
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.wgsl
index c363536..d8285dc 100644
--- a/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.wgsl
+++ b/test/tint/builtins/gen/literal/atanh/c0e634.wgsl.expected.wgsl
@@ -1,5 +1,5 @@
 fn atanh_c0e634() {
-  var res : vec2<f32> = atanh(vec2<f32>(1.0f));
+  var res : vec2<f32> = atanh(vec2<f32>(0.5f));
 }
 
 @vertex
diff --git a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl
index 038b947..f9b0d0c 100644
--- a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl
+++ b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl
@@ -23,7 +23,7 @@
 
 // fn atanh(vec<4, f32>) -> vec<4, f32>
 fn atanh_f3e01b() {
-  var res: vec4<f32> = atanh(vec4<f32>(1.f));
+  var res: vec4<f32> = atanh(vec4<f32>(0.5f));
 }
 
 @vertex
diff --git a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.dxc.hlsl
index fcae34a..8fa4615 100644
--- a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.dxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_f3e01b() {
-  float4 res = tint_atanh((1.0f).xxxx);
+  float4 res = tint_atanh((0.5f).xxxx);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.fxc.hlsl
index fcae34a..8fa4615 100644
--- a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.fxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_f3e01b() {
-  float4 res = tint_atanh((1.0f).xxxx);
+  float4 res = tint_atanh((0.5f).xxxx);
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.glsl b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.glsl
index a2cda73..e86a88f 100644
--- a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.glsl
@@ -5,7 +5,7 @@
 }
 
 void atanh_f3e01b() {
-  vec4 res = tint_atanh(vec4(1.0f));
+  vec4 res = tint_atanh(vec4(0.5f));
 }
 
 vec4 vertex_main() {
@@ -29,7 +29,7 @@
 }
 
 void atanh_f3e01b() {
-  vec4 res = tint_atanh(vec4(1.0f));
+  vec4 res = tint_atanh(vec4(0.5f));
 }
 
 void fragment_main() {
@@ -47,7 +47,7 @@
 }
 
 void atanh_f3e01b() {
-  vec4 res = tint_atanh(vec4(1.0f));
+  vec4 res = tint_atanh(vec4(0.5f));
 }
 
 void compute_main() {
diff --git a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.msl b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.msl
index 9bf9bd8..ea83ed2 100644
--- a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.msl
+++ b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.msl
@@ -6,7 +6,7 @@
 }
 
 void atanh_f3e01b() {
-  float4 res = tint_atanh(float4(1.0f));
+  float4 res = tint_atanh(float4(0.5f));
 }
 
 struct tint_symbol {
diff --git a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.spvasm b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.spvasm
index 6086ee2..c0daec0 100644
--- a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 41
+; Bound: 43
 ; Schema: 0
                OpCapability Shader
          %20 = OpExtInstImport "GLSL.std.450"
@@ -38,8 +38,10 @@
      %v4bool = OpTypeVector %bool 4
        %void = OpTypeVoid
          %21 = OpTypeFunction %void
+  %float_0_5 = OpConstant %float 0.5
+         %27 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
 %_ptr_Function_v4float = OpTypePointer Function %v4float
-         %28 = OpTypeFunction %v4float
+         %30 = OpTypeFunction %v4float
  %tint_atanh = OpFunction %v4float None %9
           %x = OpFunctionParameter %v4float
          %12 = OpLabel
@@ -51,29 +53,29 @@
 %atanh_f3e01b = OpFunction %void None %21
          %24 = OpLabel
         %res = OpVariable %_ptr_Function_v4float Function %5
-         %25 = OpFunctionCall %v4float %tint_atanh %15
+         %25 = OpFunctionCall %v4float %tint_atanh %27
                OpStore %res %25
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %28
-         %30 = OpLabel
-         %31 = OpFunctionCall %void %atanh_f3e01b
+%vertex_main_inner = OpFunction %v4float None %30
+         %32 = OpLabel
+         %33 = OpFunctionCall %void %atanh_f3e01b
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %21
-         %33 = OpLabel
-         %34 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %34
+         %35 = OpLabel
+         %36 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %36
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %21
-         %36 = OpLabel
-         %37 = OpFunctionCall %void %atanh_f3e01b
+         %38 = OpLabel
+         %39 = OpFunctionCall %void %atanh_f3e01b
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %21
-         %39 = OpLabel
-         %40 = OpFunctionCall %void %atanh_f3e01b
+         %41 = OpLabel
+         %42 = OpFunctionCall %void %atanh_f3e01b
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.wgsl b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.wgsl
index f3ad468..23096b4 100644
--- a/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.wgsl
+++ b/test/tint/builtins/gen/literal/atanh/f3e01b.wgsl.expected.wgsl
@@ -1,5 +1,5 @@
 fn atanh_f3e01b() {
-  var res : vec4<f32> = atanh(vec4<f32>(1.0f));
+  var res : vec4<f32> = atanh(vec4<f32>(0.5f));
 }
 
 @vertex
diff --git a/test/tint/builtins/gen/var/atanh/440cca.wgsl b/test/tint/builtins/gen/var/atanh/440cca.wgsl
index 753c7a9..a0b4fb4 100644
--- a/test/tint/builtins/gen/var/atanh/440cca.wgsl
+++ b/test/tint/builtins/gen/var/atanh/440cca.wgsl
@@ -23,7 +23,7 @@
 
 // fn atanh(vec<3, f32>) -> vec<3, f32>
 fn atanh_440cca() {
-  var arg_0 = vec3<f32>(1.f);
+  var arg_0 = vec3<f32>(0.5f);
   var res: vec3<f32> = atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.dxc.hlsl
index 703758d..6cfcd4c 100644
--- a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.dxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_440cca() {
-  float3 arg_0 = (1.0f).xxx;
+  float3 arg_0 = (0.5f).xxx;
   float3 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.fxc.hlsl
index 703758d..6cfcd4c 100644
--- a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.fxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_440cca() {
-  float3 arg_0 = (1.0f).xxx;
+  float3 arg_0 = (0.5f).xxx;
   float3 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.glsl b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.glsl
index 4e5fb6b..96f88b8 100644
--- a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.glsl
@@ -5,7 +5,7 @@
 }
 
 void atanh_440cca() {
-  vec3 arg_0 = vec3(1.0f);
+  vec3 arg_0 = vec3(0.5f);
   vec3 res = tint_atanh(arg_0);
 }
 
@@ -30,7 +30,7 @@
 }
 
 void atanh_440cca() {
-  vec3 arg_0 = vec3(1.0f);
+  vec3 arg_0 = vec3(0.5f);
   vec3 res = tint_atanh(arg_0);
 }
 
@@ -49,7 +49,7 @@
 }
 
 void atanh_440cca() {
-  vec3 arg_0 = vec3(1.0f);
+  vec3 arg_0 = vec3(0.5f);
   vec3 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.msl b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.msl
index 00cc45c..24e275c 100644
--- a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.msl
+++ b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.msl
@@ -6,7 +6,7 @@
 }
 
 void atanh_440cca() {
-  float3 arg_0 = float3(1.0f);
+  float3 arg_0 = float3(0.5f);
   float3 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.spvasm b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.spvasm
index 4b60b51..7e4e861 100644
--- a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 45
+; Bound: 47
 ; Schema: 0
                OpCapability Shader
          %22 = OpExtInstImport "GLSL.std.450"
@@ -41,8 +41,10 @@
          %20 = OpConstantNull %v3float
        %void = OpTypeVoid
          %23 = OpTypeFunction %void
+  %float_0_5 = OpConstant %float 0.5
+         %28 = OpConstantComposite %v3float %float_0_5 %float_0_5 %float_0_5
 %_ptr_Function_v3float = OpTypePointer Function %v3float
-         %32 = OpTypeFunction %v4float
+         %34 = OpTypeFunction %v4float
  %tint_atanh = OpFunction %v3float None %9
           %x = OpFunctionParameter %v3float
          %13 = OpLabel
@@ -55,31 +57,31 @@
          %26 = OpLabel
       %arg_0 = OpVariable %_ptr_Function_v3float Function %20
         %res = OpVariable %_ptr_Function_v3float Function %20
-               OpStore %arg_0 %16
-         %30 = OpLoad %v3float %arg_0
-         %29 = OpFunctionCall %v3float %tint_atanh %30
-               OpStore %res %29
+               OpStore %arg_0 %28
+         %32 = OpLoad %v3float %arg_0
+         %31 = OpFunctionCall %v3float %tint_atanh %32
+               OpStore %res %31
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %32
-         %34 = OpLabel
-         %35 = OpFunctionCall %void %atanh_440cca
+%vertex_main_inner = OpFunction %v4float None %34
+         %36 = OpLabel
+         %37 = OpFunctionCall %void %atanh_440cca
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %23
-         %37 = OpLabel
-         %38 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %38
+         %39 = OpLabel
+         %40 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %40
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %23
-         %40 = OpLabel
-         %41 = OpFunctionCall %void %atanh_440cca
+         %42 = OpLabel
+         %43 = OpFunctionCall %void %atanh_440cca
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %23
-         %43 = OpLabel
-         %44 = OpFunctionCall %void %atanh_440cca
+         %45 = OpLabel
+         %46 = OpFunctionCall %void %atanh_440cca
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.wgsl b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.wgsl
index b2d4a5a..1c99e3b 100644
--- a/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.wgsl
+++ b/test/tint/builtins/gen/var/atanh/440cca.wgsl.expected.wgsl
@@ -1,5 +1,5 @@
 fn atanh_440cca() {
-  var arg_0 = vec3<f32>(1.0f);
+  var arg_0 = vec3<f32>(0.5f);
   var res : vec3<f32> = atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/7997d8.wgsl b/test/tint/builtins/gen/var/atanh/7997d8.wgsl
index c08b231..45fcd80 100644
--- a/test/tint/builtins/gen/var/atanh/7997d8.wgsl
+++ b/test/tint/builtins/gen/var/atanh/7997d8.wgsl
@@ -23,7 +23,7 @@
 
 // fn atanh(f32) -> f32
 fn atanh_7997d8() {
-  var arg_0 = 1.f;
+  var arg_0 = 0.5f;
   var res: f32 = atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.dxc.hlsl
index 20a886c..24fe178 100644
--- a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.dxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_7997d8() {
-  float arg_0 = 1.0f;
+  float arg_0 = 0.5f;
   float res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.fxc.hlsl
index 20a886c..24fe178 100644
--- a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.fxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_7997d8() {
-  float arg_0 = 1.0f;
+  float arg_0 = 0.5f;
   float res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.glsl b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.glsl
index cedc900..44e3d5f 100644
--- a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.glsl
@@ -5,7 +5,7 @@
 }
 
 void atanh_7997d8() {
-  float arg_0 = 1.0f;
+  float arg_0 = 0.5f;
   float res = tint_atanh(arg_0);
 }
 
@@ -30,7 +30,7 @@
 }
 
 void atanh_7997d8() {
-  float arg_0 = 1.0f;
+  float arg_0 = 0.5f;
   float res = tint_atanh(arg_0);
 }
 
@@ -49,7 +49,7 @@
 }
 
 void atanh_7997d8() {
-  float arg_0 = 1.0f;
+  float arg_0 = 0.5f;
   float res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.msl b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.msl
index 3944dd0..ef13bec 100644
--- a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.msl
+++ b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.msl
@@ -6,7 +6,7 @@
 }
 
 void atanh_7997d8() {
-  float arg_0 = 1.0f;
+  float arg_0 = 0.5f;
   float res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.spvasm b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.spvasm
index 1b473e9..95322a9 100644
--- a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 41
+; Bound: 42
 ; Schema: 0
                OpCapability Shader
          %18 = OpExtInstImport "GLSL.std.450"
@@ -37,8 +37,9 @@
        %bool = OpTypeBool
        %void = OpTypeVoid
          %19 = OpTypeFunction %void
+  %float_0_5 = OpConstant %float 0.5
 %_ptr_Function_float = OpTypePointer Function %float
-         %28 = OpTypeFunction %v4float
+         %29 = OpTypeFunction %v4float
  %tint_atanh = OpFunction %float None %9
           %x = OpFunctionParameter %float
          %12 = OpLabel
@@ -51,31 +52,31 @@
          %22 = OpLabel
       %arg_0 = OpVariable %_ptr_Function_float Function %8
         %res = OpVariable %_ptr_Function_float Function %8
-               OpStore %arg_0 %float_1
-         %26 = OpLoad %float %arg_0
-         %25 = OpFunctionCall %float %tint_atanh %26
-               OpStore %res %25
+               OpStore %arg_0 %float_0_5
+         %27 = OpLoad %float %arg_0
+         %26 = OpFunctionCall %float %tint_atanh %27
+               OpStore %res %26
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %28
-         %30 = OpLabel
-         %31 = OpFunctionCall %void %atanh_7997d8
+%vertex_main_inner = OpFunction %v4float None %29
+         %31 = OpLabel
+         %32 = OpFunctionCall %void %atanh_7997d8
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %19
-         %33 = OpLabel
-         %34 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %34
+         %34 = OpLabel
+         %35 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %35
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %19
-         %36 = OpLabel
-         %37 = OpFunctionCall %void %atanh_7997d8
+         %37 = OpLabel
+         %38 = OpFunctionCall %void %atanh_7997d8
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %19
-         %39 = OpLabel
-         %40 = OpFunctionCall %void %atanh_7997d8
+         %40 = OpLabel
+         %41 = OpFunctionCall %void %atanh_7997d8
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.wgsl b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.wgsl
index 43556590..a375e93 100644
--- a/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.wgsl
+++ b/test/tint/builtins/gen/var/atanh/7997d8.wgsl.expected.wgsl
@@ -1,5 +1,5 @@
 fn atanh_7997d8() {
-  var arg_0 = 1.0f;
+  var arg_0 = 0.5f;
   var res : f32 = atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/c0e634.wgsl b/test/tint/builtins/gen/var/atanh/c0e634.wgsl
index 1538619..11abbc8 100644
--- a/test/tint/builtins/gen/var/atanh/c0e634.wgsl
+++ b/test/tint/builtins/gen/var/atanh/c0e634.wgsl
@@ -23,7 +23,7 @@
 
 // fn atanh(vec<2, f32>) -> vec<2, f32>
 fn atanh_c0e634() {
-  var arg_0 = vec2<f32>(1.f);
+  var arg_0 = vec2<f32>(0.5f);
   var res: vec2<f32> = atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.dxc.hlsl
index 2573bee..4c38c2d 100644
--- a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.dxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_c0e634() {
-  float2 arg_0 = (1.0f).xx;
+  float2 arg_0 = (0.5f).xx;
   float2 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.fxc.hlsl
index 2573bee..4c38c2d 100644
--- a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.fxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_c0e634() {
-  float2 arg_0 = (1.0f).xx;
+  float2 arg_0 = (0.5f).xx;
   float2 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.glsl b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.glsl
index a6857cd..8693caa 100644
--- a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.glsl
@@ -5,7 +5,7 @@
 }
 
 void atanh_c0e634() {
-  vec2 arg_0 = vec2(1.0f);
+  vec2 arg_0 = vec2(0.5f);
   vec2 res = tint_atanh(arg_0);
 }
 
@@ -30,7 +30,7 @@
 }
 
 void atanh_c0e634() {
-  vec2 arg_0 = vec2(1.0f);
+  vec2 arg_0 = vec2(0.5f);
   vec2 res = tint_atanh(arg_0);
 }
 
@@ -49,7 +49,7 @@
 }
 
 void atanh_c0e634() {
-  vec2 arg_0 = vec2(1.0f);
+  vec2 arg_0 = vec2(0.5f);
   vec2 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.msl b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.msl
index a407911..51cfc7a 100644
--- a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.msl
+++ b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.msl
@@ -6,7 +6,7 @@
 }
 
 void atanh_c0e634() {
-  float2 arg_0 = float2(1.0f);
+  float2 arg_0 = float2(0.5f);
   float2 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.spvasm b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.spvasm
index 3bfbe16..8c6366e 100644
--- a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 45
+; Bound: 47
 ; Schema: 0
                OpCapability Shader
          %22 = OpExtInstImport "GLSL.std.450"
@@ -41,8 +41,10 @@
          %20 = OpConstantNull %v2float
        %void = OpTypeVoid
          %23 = OpTypeFunction %void
+  %float_0_5 = OpConstant %float 0.5
+         %28 = OpConstantComposite %v2float %float_0_5 %float_0_5
 %_ptr_Function_v2float = OpTypePointer Function %v2float
-         %32 = OpTypeFunction %v4float
+         %34 = OpTypeFunction %v4float
  %tint_atanh = OpFunction %v2float None %9
           %x = OpFunctionParameter %v2float
          %13 = OpLabel
@@ -55,31 +57,31 @@
          %26 = OpLabel
       %arg_0 = OpVariable %_ptr_Function_v2float Function %20
         %res = OpVariable %_ptr_Function_v2float Function %20
-               OpStore %arg_0 %16
-         %30 = OpLoad %v2float %arg_0
-         %29 = OpFunctionCall %v2float %tint_atanh %30
-               OpStore %res %29
+               OpStore %arg_0 %28
+         %32 = OpLoad %v2float %arg_0
+         %31 = OpFunctionCall %v2float %tint_atanh %32
+               OpStore %res %31
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %32
-         %34 = OpLabel
-         %35 = OpFunctionCall %void %atanh_c0e634
+%vertex_main_inner = OpFunction %v4float None %34
+         %36 = OpLabel
+         %37 = OpFunctionCall %void %atanh_c0e634
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %23
-         %37 = OpLabel
-         %38 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %38
+         %39 = OpLabel
+         %40 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %40
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %23
-         %40 = OpLabel
-         %41 = OpFunctionCall %void %atanh_c0e634
+         %42 = OpLabel
+         %43 = OpFunctionCall %void %atanh_c0e634
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %23
-         %43 = OpLabel
-         %44 = OpFunctionCall %void %atanh_c0e634
+         %45 = OpLabel
+         %46 = OpFunctionCall %void %atanh_c0e634
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.wgsl b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.wgsl
index e9d9908..fd266f3 100644
--- a/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.wgsl
+++ b/test/tint/builtins/gen/var/atanh/c0e634.wgsl.expected.wgsl
@@ -1,5 +1,5 @@
 fn atanh_c0e634() {
-  var arg_0 = vec2<f32>(1.0f);
+  var arg_0 = vec2<f32>(0.5f);
   var res : vec2<f32> = atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl
index c971440..0f72799 100644
--- a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl
+++ b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl
@@ -23,7 +23,7 @@
 
 // fn atanh(vec<4, f32>) -> vec<4, f32>
 fn atanh_f3e01b() {
-  var arg_0 = vec4<f32>(1.f);
+  var arg_0 = vec4<f32>(0.5f);
   var res: vec4<f32> = atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.dxc.hlsl b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.dxc.hlsl
index f85a7e6..88b9078 100644
--- a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.dxc.hlsl
+++ b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.dxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_f3e01b() {
-  float4 arg_0 = (1.0f).xxxx;
+  float4 arg_0 = (0.5f).xxxx;
   float4 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.fxc.hlsl b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.fxc.hlsl
index f85a7e6..88b9078 100644
--- a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.fxc.hlsl
+++ b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.fxc.hlsl
@@ -3,7 +3,7 @@
 }
 
 void atanh_f3e01b() {
-  float4 arg_0 = (1.0f).xxxx;
+  float4 arg_0 = (0.5f).xxxx;
   float4 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.glsl b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.glsl
index 75486c5..cf63d64 100644
--- a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.glsl
@@ -5,7 +5,7 @@
 }
 
 void atanh_f3e01b() {
-  vec4 arg_0 = vec4(1.0f);
+  vec4 arg_0 = vec4(0.5f);
   vec4 res = tint_atanh(arg_0);
 }
 
@@ -30,7 +30,7 @@
 }
 
 void atanh_f3e01b() {
-  vec4 arg_0 = vec4(1.0f);
+  vec4 arg_0 = vec4(0.5f);
   vec4 res = tint_atanh(arg_0);
 }
 
@@ -49,7 +49,7 @@
 }
 
 void atanh_f3e01b() {
-  vec4 arg_0 = vec4(1.0f);
+  vec4 arg_0 = vec4(0.5f);
   vec4 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.msl b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.msl
index 41b2f08..ed733d4 100644
--- a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.msl
+++ b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.msl
@@ -6,7 +6,7 @@
 }
 
 void atanh_f3e01b() {
-  float4 arg_0 = float4(1.0f);
+  float4 arg_0 = float4(0.5f);
   float4 res = tint_atanh(arg_0);
 }
 
diff --git a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.spvasm b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.spvasm
index e78165e..fb1f009 100644
--- a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.spvasm
+++ b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.spvasm
@@ -1,7 +1,7 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
-; Bound: 43
+; Bound: 45
 ; Schema: 0
                OpCapability Shader
          %20 = OpExtInstImport "GLSL.std.450"
@@ -39,8 +39,10 @@
      %v4bool = OpTypeVector %bool 4
        %void = OpTypeVoid
          %21 = OpTypeFunction %void
+  %float_0_5 = OpConstant %float 0.5
+         %26 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
 %_ptr_Function_v4float = OpTypePointer Function %v4float
-         %30 = OpTypeFunction %v4float
+         %32 = OpTypeFunction %v4float
  %tint_atanh = OpFunction %v4float None %9
           %x = OpFunctionParameter %v4float
          %12 = OpLabel
@@ -53,31 +55,31 @@
          %24 = OpLabel
       %arg_0 = OpVariable %_ptr_Function_v4float Function %5
         %res = OpVariable %_ptr_Function_v4float Function %5
-               OpStore %arg_0 %15
-         %28 = OpLoad %v4float %arg_0
-         %27 = OpFunctionCall %v4float %tint_atanh %28
-               OpStore %res %27
+               OpStore %arg_0 %26
+         %30 = OpLoad %v4float %arg_0
+         %29 = OpFunctionCall %v4float %tint_atanh %30
+               OpStore %res %29
                OpReturn
                OpFunctionEnd
-%vertex_main_inner = OpFunction %v4float None %30
-         %32 = OpLabel
-         %33 = OpFunctionCall %void %atanh_f3e01b
+%vertex_main_inner = OpFunction %v4float None %32
+         %34 = OpLabel
+         %35 = OpFunctionCall %void %atanh_f3e01b
                OpReturnValue %5
                OpFunctionEnd
 %vertex_main = OpFunction %void None %21
-         %35 = OpLabel
-         %36 = OpFunctionCall %v4float %vertex_main_inner
-               OpStore %value %36
+         %37 = OpLabel
+         %38 = OpFunctionCall %v4float %vertex_main_inner
+               OpStore %value %38
                OpStore %vertex_point_size %float_1
                OpReturn
                OpFunctionEnd
 %fragment_main = OpFunction %void None %21
-         %38 = OpLabel
-         %39 = OpFunctionCall %void %atanh_f3e01b
+         %40 = OpLabel
+         %41 = OpFunctionCall %void %atanh_f3e01b
                OpReturn
                OpFunctionEnd
 %compute_main = OpFunction %void None %21
-         %41 = OpLabel
-         %42 = OpFunctionCall %void %atanh_f3e01b
+         %43 = OpLabel
+         %44 = OpFunctionCall %void %atanh_f3e01b
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.wgsl b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.wgsl
index ead0ca8..214386d 100644
--- a/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.wgsl
+++ b/test/tint/builtins/gen/var/atanh/f3e01b.wgsl.expected.wgsl
@@ -1,5 +1,5 @@
 fn atanh_f3e01b() {
-  var arg_0 = vec4<f32>(1.0f);
+  var arg_0 = vec4<f32>(0.5f);
   var res : vec4<f32> = atanh(arg_0);
 }
 
diff --git a/tools/src/cmd/gen/main.go b/tools/src/cmd/gen/main.go
index 595f77c..f45c624 100644
--- a/tools/src/cmd/gen/main.go
+++ b/tools/src/cmd/gen/main.go
@@ -303,6 +303,7 @@
 		"Title":                 strings.Title,
 		"PascalCase":            pascalCase,
 		"SplitDisplayName":      gen.SplitDisplayName,
+		"Contains":              strings.Contains,
 		"HasPrefix":             strings.HasPrefix,
 		"HasSuffix":             strings.HasSuffix,
 		"TrimPrefix":            strings.TrimPrefix,
diff --git a/tools/src/tint/intrinsic/ast/ast.go b/tools/src/tint/intrinsic/ast/ast.go
index 6944da2..ffb036e 100644
--- a/tools/src/tint/intrinsic/ast/ast.go
+++ b/tools/src/tint/intrinsic/ast/ast.go
@@ -367,7 +367,7 @@
 type Attribute struct {
 	Source tok.Source
 	Name   string
-	Values []string
+	Values []any
 }
 
 // Format implements the fmt.Formatter interface
diff --git a/tools/src/tint/intrinsic/gen/permutate.go b/tools/src/tint/intrinsic/gen/permutate.go
index df5f1d2..59b3fa5 100644
--- a/tools/src/tint/intrinsic/gen/permutate.go
+++ b/tools/src/tint/intrinsic/gen/permutate.go
@@ -83,9 +83,10 @@
 				return nil
 			}
 			o.Parameters = append(o.Parameters, sem.Parameter{
-				Name:    p.Name,
-				Type:    ty,
-				IsConst: p.IsConst,
+				Name:      p.Name,
+				Type:      ty,
+				IsConst:   p.IsConst,
+				TestValue: p.TestValue,
 			})
 		}
 		if overload.ReturnType != nil {
diff --git a/tools/src/tint/intrinsic/lexer/lexer.go b/tools/src/tint/intrinsic/lexer/lexer.go
index a98a988..91042d6 100644
--- a/tools/src/tint/intrinsic/lexer/lexer.go
+++ b/tools/src/tint/intrinsic/lexer/lexer.go
@@ -104,7 +104,23 @@
 			case unicode.IsLetter(l.peek(0)) || l.peek(0) == '_':
 				l.tok(l.count(alphaNumericOrUnderscore), tok.Identifier)
 			case unicode.IsNumber(l.peek(0)):
-				l.tok(l.count(unicode.IsNumber), tok.Integer)
+				isFloat := false
+				pred := func(r rune) bool {
+					if unicode.IsNumber(r) {
+						return true
+					}
+					if !isFloat && r == '.' {
+						isFloat = true
+						return true
+					}
+					return false
+				}
+				n := l.count(pred)
+				if isFloat {
+					l.tok(n, tok.Float)
+				} else {
+					l.tok(n, tok.Integer)
+				}
 			case l.match("&&", tok.AndAnd):
 			case l.match("&", tok.And):
 			case l.match("||", tok.OrOr):
diff --git a/tools/src/tint/intrinsic/lexer/lexer_test.go b/tools/src/tint/intrinsic/lexer/lexer_test.go
index ce1d618..aec38ec 100644
--- a/tools/src/tint/intrinsic/lexer/lexer_test.go
+++ b/tools/src/tint/intrinsic/lexer/lexer_test.go
@@ -20,12 +20,13 @@
 
 	"dawn.googlesource.com/dawn/tools/src/tint/intrinsic/lexer"
 	"dawn.googlesource.com/dawn/tools/src/tint/intrinsic/tok"
+	"github.com/google/go-cmp/cmp"
 )
 
 func TestLexTokens(t *testing.T) {
 	type test struct {
 		src    string
-		expect tok.Token
+		expect []tok.Token
 	}
 
 	filepath := "test.txt"
@@ -34,144 +35,153 @@
 	}
 
 	for _, test := range []test{
-		{"ident", tok.Token{Kind: tok.Identifier, Runes: []rune("ident"), Source: tok.Source{
+		{"ident", []tok.Token{{Kind: tok.Identifier, Runes: []rune("ident"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 6, 5),
-		}}},
-		{"ident_123", tok.Token{Kind: tok.Identifier, Runes: []rune("ident_123"), Source: tok.Source{
+		}}}},
+		{"ident_123", []tok.Token{{Kind: tok.Identifier, Runes: []rune("ident_123"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 10, 9),
-		}}},
-		{"_ident_", tok.Token{Kind: tok.Identifier, Runes: []rune("_ident_"), Source: tok.Source{
+		}}}},
+		{"_ident_", []tok.Token{{Kind: tok.Identifier, Runes: []rune("_ident_"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 8, 7),
-		}}},
-		{"123456789", tok.Token{Kind: tok.Integer, Runes: []rune("123456789"), Source: tok.Source{
+		}}}},
+		{"123456789", []tok.Token{{Kind: tok.Integer, Runes: []rune("123456789"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 10, 9),
-		}}},
-		{"match", tok.Token{Kind: tok.Match, Runes: []rune("match"), Source: tok.Source{
+		}}}},
+		{"1234.56789", []tok.Token{{Kind: tok.Float, Runes: []rune("1234.56789"), Source: tok.Source{
+			S: loc(1, 1, 0), E: loc(1, 11, 10),
+		}}}},
+		{"123.456.789", []tok.Token{
+			{Kind: tok.Float, Runes: []rune("123.456"), Source: tok.Source{
+				S: loc(1, 1, 0), E: loc(1, 8, 7),
+			}},
+			{Kind: tok.Dot, Runes: []rune("."), Source: tok.Source{
+				S: loc(1, 8, 7), E: loc(1, 9, 8),
+			}},
+			{Kind: tok.Integer, Runes: []rune("789"), Source: tok.Source{
+				S: loc(1, 9, 8), E: loc(1, 12, 11),
+			}},
+		}},
+		{"match", []tok.Token{{Kind: tok.Match, Runes: []rune("match"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 6, 5),
-		}}},
-		{"fn", tok.Token{Kind: tok.Function, Runes: []rune("fn"), Source: tok.Source{
+		}}}},
+		{"fn", []tok.Token{{Kind: tok.Function, Runes: []rune("fn"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{"op", tok.Token{Kind: tok.Operator, Runes: []rune("op"), Source: tok.Source{
+		}}}},
+		{"op", []tok.Token{{Kind: tok.Operator, Runes: []rune("op"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{"type", tok.Token{Kind: tok.Type, Runes: []rune("type"), Source: tok.Source{
+		}}}},
+		{"type", []tok.Token{{Kind: tok.Type, Runes: []rune("type"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 5, 4),
-		}}},
-		{"init", tok.Token{Kind: tok.Initializer, Runes: []rune("init"), Source: tok.Source{
+		}}}},
+		{"init", []tok.Token{{Kind: tok.Initializer, Runes: []rune("init"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 5, 4),
-		}}},
-		{"conv", tok.Token{Kind: tok.Converter, Runes: []rune("conv"), Source: tok.Source{
+		}}}},
+		{"conv", []tok.Token{{Kind: tok.Converter, Runes: []rune("conv"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 5, 4),
-		}}},
-		{"enum", tok.Token{Kind: tok.Enum, Runes: []rune("enum"), Source: tok.Source{
+		}}}},
+		{"enum", []tok.Token{{Kind: tok.Enum, Runes: []rune("enum"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 5, 4),
-		}}},
-		{":", tok.Token{Kind: tok.Colon, Runes: []rune(":"), Source: tok.Source{
+		}}}},
+		{":", []tok.Token{{Kind: tok.Colon, Runes: []rune(":"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{",", tok.Token{Kind: tok.Comma, Runes: []rune(","), Source: tok.Source{
+		}}}},
+		{",", []tok.Token{{Kind: tok.Comma, Runes: []rune(","), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"<", tok.Token{Kind: tok.Lt, Runes: []rune("<"), Source: tok.Source{
+		}}}},
+		{"<", []tok.Token{{Kind: tok.Lt, Runes: []rune("<"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{">", tok.Token{Kind: tok.Gt, Runes: []rune(">"), Source: tok.Source{
+		}}}},
+		{">", []tok.Token{{Kind: tok.Gt, Runes: []rune(">"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"{", tok.Token{Kind: tok.Lbrace, Runes: []rune("{"), Source: tok.Source{
+		}}}},
+		{"{", []tok.Token{{Kind: tok.Lbrace, Runes: []rune("{"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"}", tok.Token{Kind: tok.Rbrace, Runes: []rune("}"), Source: tok.Source{
+		}}}},
+		{"}", []tok.Token{{Kind: tok.Rbrace, Runes: []rune("}"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"&&", tok.Token{Kind: tok.AndAnd, Runes: []rune("&&"), Source: tok.Source{
+		}}}},
+		{"&&", []tok.Token{{Kind: tok.AndAnd, Runes: []rune("&&"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{"&", tok.Token{Kind: tok.And, Runes: []rune("&"), Source: tok.Source{
+		}}}},
+		{"&", []tok.Token{{Kind: tok.And, Runes: []rune("&"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"||", tok.Token{Kind: tok.OrOr, Runes: []rune("||"), Source: tok.Source{
+		}}}},
+		{"||", []tok.Token{{Kind: tok.OrOr, Runes: []rune("||"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{"|", tok.Token{Kind: tok.Or, Runes: []rune("|"), Source: tok.Source{
+		}}}},
+		{"|", []tok.Token{{Kind: tok.Or, Runes: []rune("|"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"!", tok.Token{Kind: tok.Not, Runes: []rune("!"), Source: tok.Source{
+		}}}},
+		{"!", []tok.Token{{Kind: tok.Not, Runes: []rune("!"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"!=", tok.Token{Kind: tok.NotEqual, Runes: []rune("!="), Source: tok.Source{
+		}}}},
+		{"!=", []tok.Token{{Kind: tok.NotEqual, Runes: []rune("!="), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{"==", tok.Token{Kind: tok.Equal, Runes: []rune("=="), Source: tok.Source{
+		}}}},
+		{"==", []tok.Token{{Kind: tok.Equal, Runes: []rune("=="), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{"=", tok.Token{Kind: tok.Assign, Runes: []rune("="), Source: tok.Source{
+		}}}},
+		{"=", []tok.Token{{Kind: tok.Assign, Runes: []rune("="), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"<<", tok.Token{Kind: tok.Shl, Runes: []rune("<<"), Source: tok.Source{
+		}}}},
+		{"<<", []tok.Token{{Kind: tok.Shl, Runes: []rune("<<"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{"<=", tok.Token{Kind: tok.Le, Runes: []rune("<="), Source: tok.Source{
+		}}}},
+		{"<=", []tok.Token{{Kind: tok.Le, Runes: []rune("<="), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{"<", tok.Token{Kind: tok.Lt, Runes: []rune("<"), Source: tok.Source{
+		}}}},
+		{"<", []tok.Token{{Kind: tok.Lt, Runes: []rune("<"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{">=", tok.Token{Kind: tok.Ge, Runes: []rune(">="), Source: tok.Source{
+		}}}},
+		{">=", []tok.Token{{Kind: tok.Ge, Runes: []rune(">="), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{">>", tok.Token{Kind: tok.Shr, Runes: []rune(">>"), Source: tok.Source{
+		}}}},
+		{">>", []tok.Token{{Kind: tok.Shr, Runes: []rune(">>"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{">", tok.Token{Kind: tok.Gt, Runes: []rune(">"), Source: tok.Source{
+		}}}},
+		{">", []tok.Token{{Kind: tok.Gt, Runes: []rune(">"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"@", tok.Token{Kind: tok.Attr, Runes: []rune("@"), Source: tok.Source{
+		}}}},
+		{"@", []tok.Token{{Kind: tok.Attr, Runes: []rune("@"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"(", tok.Token{Kind: tok.Lparen, Runes: []rune("("), Source: tok.Source{
+		}}}},
+		{"(", []tok.Token{{Kind: tok.Lparen, Runes: []rune("("), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{")", tok.Token{Kind: tok.Rparen, Runes: []rune(")"), Source: tok.Source{
+		}}}},
+		{")", []tok.Token{{Kind: tok.Rparen, Runes: []rune(")"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"|", tok.Token{Kind: tok.Or, Runes: []rune("|"), Source: tok.Source{
+		}}}},
+		{"|", []tok.Token{{Kind: tok.Or, Runes: []rune("|"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"*", tok.Token{Kind: tok.Star, Runes: []rune("*"), Source: tok.Source{
+		}}}},
+		{"*", []tok.Token{{Kind: tok.Star, Runes: []rune("*"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{"->", tok.Token{Kind: tok.Arrow, Runes: []rune("->"), Source: tok.Source{
+		}}}},
+		{"->", []tok.Token{{Kind: tok.Arrow, Runes: []rune("->"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 3, 2),
-		}}},
-		{"x // y ", tok.Token{Kind: tok.Identifier, Runes: []rune("x"), Source: tok.Source{
+		}}}},
+		{"x // y ", []tok.Token{{Kind: tok.Identifier, Runes: []rune("x"), Source: tok.Source{
 			S: loc(1, 1, 0), E: loc(1, 2, 1),
-		}}},
-		{`"abc"`, tok.Token{Kind: tok.String, Runes: []rune("abc"), Source: tok.Source{
+		}}}},
+		{`"abc"`, []tok.Token{{Kind: tok.String, Runes: []rune("abc"), Source: tok.Source{
 			S: loc(1, 2, 1), E: loc(1, 5, 4),
-		}}},
+		}}}},
 		{`
    //
    ident
 
-   `, tok.Token{Kind: tok.Identifier, Runes: []rune("ident"), Source: tok.Source{
+   `, []tok.Token{{Kind: tok.Identifier, Runes: []rune("ident"), Source: tok.Source{
 			S: loc(3, 4, 10), E: loc(3, 9, 15),
-		}}},
+		}}}},
 	} {
 		got, err := lexer.Lex([]rune(test.src), filepath)
 		name := fmt.Sprintf(`Lex("%v")`, test.src)
-		switch {
-		case err != nil:
+		if err != nil {
 			t.Errorf("%v returned error: %v", name, err)
-		case len(got) != 1:
-			t.Errorf("%v returned %d tokens: %v", name, len(got), got)
-		case got[0].Kind != test.expect.Kind:
-			t.Errorf(`%v returned unexpected token kind: got "%+v", expected "%+v"`, name, got[0], test.expect)
-		case string(got[0].Runes) != string(test.expect.Runes):
-			t.Errorf(`%v returned unexpected token runes: got "%+v", expected "%+v"`, name, string(got[0].Runes), string(test.expect.Runes))
-		case got[0].Source != test.expect.Source:
-			t.Errorf(`%v returned unexpected token source: got %+v, expected %+v`, name, got[0].Source, test.expect.Source)
+			continue
+		}
+		if diff := cmp.Diff(got, test.expect); diff != "" {
+			t.Errorf(`%v: %v`, name, diff)
 		}
 	}
 }
diff --git a/tools/src/tint/intrinsic/parser/parser.go b/tools/src/tint/intrinsic/parser/parser.go
index cec8d2d..418d543 100644
--- a/tools/src/tint/intrinsic/parser/parser.go
+++ b/tools/src/tint/intrinsic/parser/parser.go
@@ -18,6 +18,7 @@
 
 import (
 	"fmt"
+	"strconv"
 
 	"dawn.googlesource.com/dawn/tools/src/tint/intrinsic/ast"
 	"dawn.googlesource.com/dawn/tools/src/tint/intrinsic/lexer"
@@ -145,10 +146,26 @@
 	var out ast.Attributes
 	for p.match(tok.Attr) != nil && p.err == nil {
 		name := p.expect(tok.Identifier, "attribute name")
-		values := []string{}
+		var values []any
 		if p.match(tok.Lparen) != nil {
+		loop:
 			for p.err == nil {
-				values = append(values, string(p.next().Runes))
+				t := p.next()
+				switch t.Kind {
+				case tok.Rparen:
+					break loop
+				case tok.String:
+					values = append(values, string(t.Runes))
+				case tok.Integer:
+					i, _ := strconv.ParseInt(string(t.Runes), 10, 64)
+					values = append(values, int(i))
+				case tok.Float:
+					f, _ := strconv.ParseFloat(string(t.Runes), 64)
+					values = append(values, f)
+				default:
+					p.err = fmt.Errorf("%v invalid attribute value kind: %v", t.Source, t.Kind)
+					return nil
+				}
 				if p.match(tok.Comma) == nil {
 					break
 				}
diff --git a/tools/src/tint/intrinsic/parser/parser_test.go b/tools/src/tint/intrinsic/parser/parser_test.go
index 24dec43..ce8b377 100644
--- a/tools/src/tint/intrinsic/parser/parser_test.go
+++ b/tools/src/tint/intrinsic/parser/parser_test.go
@@ -52,7 +52,7 @@
 						{
 							Attributes: ast.Attributes{{
 								Name:   "attr",
-								Values: []string{},
+								Values: nil,
 							}},
 							Name: "B",
 						},
@@ -85,7 +85,7 @@
 			ast.AST{
 				Types: []ast.TypeDecl{{
 					Attributes: ast.Attributes{
-						{Name: "attr", Values: []string{}},
+						{Name: "attr", Values: nil},
 					},
 					Name: "T",
 				}},
@@ -96,8 +96,8 @@
 			ast.AST{
 				Types: []ast.TypeDecl{{
 					Attributes: ast.Attributes{
-						{Name: "attr_a", Values: []string{}},
-						{Name: "attr_b", Values: []string{}},
+						{Name: "attr_a", Values: nil},
+						{Name: "attr_b", Values: nil},
 					},
 					Name: "T",
 				}},
@@ -107,17 +107,17 @@
 			`@attr("a", "b") type T`, ast.AST{
 				Types: []ast.TypeDecl{{
 					Attributes: ast.Attributes{
-						{Name: "attr", Values: []string{"a", "b"}},
+						{Name: "attr", Values: []any{"a", "b"}},
 					},
 					Name: "T",
 				}},
 			},
 		}, { ///////////////////////////////////////////////////////////////////
 			utils.ThisLine(),
-			`@attr(1, "x") type T`, ast.AST{
+			`@attr(1, "x", 2.0) type T`, ast.AST{
 				Types: []ast.TypeDecl{{
 					Attributes: ast.Attributes{
-						{Name: "attr", Values: []string{"1", "x"}},
+						{Name: "attr", Values: []any{1, "x", 2.0}},
 					},
 					Name: "T",
 				}},
@@ -194,7 +194,7 @@
 					Kind: ast.Builtin,
 					Name: "F",
 					Attributes: ast.Attributes{
-						{Name: "attr", Values: []string{}},
+						{Name: "attr", Values: nil},
 					},
 					Parameters: ast.Parameters{},
 				}},
@@ -318,7 +318,7 @@
 					Kind: ast.Operator,
 					Name: "F",
 					Attributes: ast.Attributes{
-						{Name: "attr", Values: []string{}},
+						{Name: "attr", Values: nil},
 					},
 					Parameters: ast.Parameters{},
 				}},
@@ -344,7 +344,7 @@
 					Name: "F",
 					Parameters: ast.Parameters{
 						{
-							Attributes: ast.Attributes{{Name: "blah", Values: []string{}}},
+							Attributes: ast.Attributes{{Name: "blah", Values: nil}},
 							Type:       ast.TemplatedName{Name: "a"}},
 					},
 				}},
@@ -456,7 +456,7 @@
 					Kind: ast.Initializer,
 					Name: "F",
 					Attributes: ast.Attributes{
-						{Name: "attr", Values: []string{}},
+						{Name: "attr", Values: nil},
 					},
 					Parameters: ast.Parameters{},
 				}},
@@ -580,7 +580,7 @@
 					Kind: ast.Converter,
 					Name: "F",
 					Attributes: ast.Attributes{
-						{Name: "attr", Values: []string{}},
+						{Name: "attr", Values: nil},
 					},
 					Parameters: ast.Parameters{},
 				}},
diff --git a/tools/src/tint/intrinsic/resolver/resolve.go b/tools/src/tint/intrinsic/resolver/resolve.go
index ab83c09..59e4bfd 100644
--- a/tools/src/tint/intrinsic/resolver/resolve.go
+++ b/tools/src/tint/intrinsic/resolver/resolve.go
@@ -17,7 +17,6 @@
 import (
 	"fmt"
 	"sort"
-	"strconv"
 
 	"dawn.googlesource.com/dawn/tools/src/container"
 	"dawn.googlesource.com/dawn/tools/src/tint/intrinsic/ast"
@@ -184,15 +183,15 @@
 		if len(d.Values) != 1 {
 			return fmt.Errorf("%v expected a single value for 'display' attribute", d.Source)
 		}
-		t.DisplayName = d.Values[0]
+		t.DisplayName = fmt.Sprint(d.Values[0])
 	}
 	if d := a.Attributes.Take("precedence"); d != nil {
 		if len(d.Values) != 1 {
 			return fmt.Errorf("%v expected a single integer value for 'precedence' attribute", d.Source)
 		}
-		n, err := strconv.Atoi(d.Values[0])
-		if err != nil {
-			return fmt.Errorf("%v %v", d.Source, err)
+		n, ok := d.Values[0].(int)
+		if !ok {
+			return fmt.Errorf("%v @precedence value must be an integer", d.Source)
 		}
 		t.Precedence = n
 	}
@@ -358,7 +357,11 @@
 				overload.ConstEvalFunction = "Conv"
 			}
 		case 1:
-			overload.ConstEvalFunction = constEvalFn.Values[0]
+			fn, ok := constEvalFn.Values[0].(string)
+			if !ok {
+				return fmt.Errorf("%v optional @const value must be a string", constEvalFn.Source)
+			}
+			overload.ConstEvalFunction = fn
 		default:
 			return fmt.Errorf("%v too many values for @const attribute", constEvalFn.Source)
 		}
@@ -405,13 +408,25 @@
 		if attribute := p.Attributes.Take("const"); attribute != nil {
 			isConst = true
 		}
+		testValue := 1.0
+		if attribute := p.Attributes.Take("test_value"); attribute != nil {
+			switch v := attribute.Values[0].(type) {
+			case int:
+				testValue = float64(v)
+			case float64:
+				testValue = v
+			default:
+				return fmt.Errorf("%v @test_value must be an integer or float", p.Attributes[0].Source)
+			}
+		}
 		if len(p.Attributes) != 0 {
 			return fmt.Errorf("%v unknown attribute", p.Attributes[0].Source)
 		}
 		overload.Parameters[i] = sem.Parameter{
-			Name:    p.Name,
-			Type:    usage,
-			IsConst: isConst,
+			Name:      p.Name,
+			Type:      usage,
+			IsConst:   isConst,
+			TestValue: testValue,
 		}
 	}
 
diff --git a/tools/src/tint/intrinsic/sem/sem.go b/tools/src/tint/intrinsic/sem/sem.go
index b7d70d8..2c0c1ee 100644
--- a/tools/src/tint/intrinsic/sem/sem.go
+++ b/tools/src/tint/intrinsic/sem/sem.go
@@ -242,9 +242,10 @@
 
 // Parameter describes a single parameter of a function overload
 type Parameter struct {
-	Name    string
-	Type    FullyQualifiedName
-	IsConst bool // Did this parameter have a @const attribute?
+	Name      string
+	Type      FullyQualifiedName
+	IsConst   bool    // Did this parameter have a @const attribute?
+	TestValue float64 // Value to use for end-to-end tests
 }
 
 // Format implements the fmt.Formatter interface
diff --git a/tools/src/tint/intrinsic/tok/tok.go b/tools/src/tint/intrinsic/tok/tok.go
index 8899ffb..0516ce9 100644
--- a/tools/src/tint/intrinsic/tok/tok.go
+++ b/tools/src/tint/intrinsic/tok/tok.go
@@ -26,6 +26,7 @@
 	InvalidToken Kind = "<invalid>"
 	Identifier   Kind = "ident"
 	Integer      Kind = "integer"
+	Float        Kind = "float"
 	String       Kind = "string"
 	Match        Kind = "match"
 	Function     Kind = "fn"