[ir] Use helpers to generate constants.

This CL uses the `Composite` helper in the builder and adds a `Splat`
helper. Then uses them in the places where they were created manually.

Bug: tint:1718
Change-Id: Id239609cb5fc19571430107b0156541e3753a5f5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/144320
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/lang/core/ir/builder.h b/src/tint/lang/core/ir/builder.h
index a71257c..f9157f9 100644
--- a/src/tint/lang/core/ir/builder.h
+++ b/src/tint/lang/core/ir/builder.h
@@ -280,6 +280,17 @@
     }
 
     /// Creates a new ir::Constant
+    /// @param ty the splat type
+    /// @param value the splat value
+    /// @param size the number of items
+    /// @returns the new constant
+    template <typename ARG>
+    ir::Constant* Splat(const type::Type* ty, ARG&& value, size_t size) {
+        return Constant(
+            ir.constant_values.Splat(ty, ConstantValue(std::forward<ARG>(value)), size));
+    }
+
+    /// Creates a new ir::Constant
     /// @param ty the constant type
     /// @param values the composite values
     /// @returns the new constant
@@ -567,9 +578,7 @@
     template <typename VAL>
     ir::Binary* Not(const type::Type* type, VAL&& val) {
         if (auto* vec = type->As<type::Vector>()) {
-            return Equal(type, std::forward<VAL>(val),
-                         Constant(ir.constant_values.Splat(vec, ir.constant_values.Get(false),
-                                                           vec->Width())));
+            return Equal(type, std::forward<VAL>(val), Splat(vec, false, vec->Width()));
         } else {
             return Equal(type, std::forward<VAL>(val), Constant(false));
         }
diff --git a/src/tint/lang/msl/writer/printer/constant_test.cc b/src/tint/lang/msl/writer/printer/constant_test.cc
index b068308..0fc6927 100644
--- a/src/tint/lang/msl/writer/printer/constant_test.cc
+++ b/src/tint/lang/msl/writer/printer/constant_test.cc
@@ -65,56 +65,45 @@
 }
 
 TEST_F(MslPrinterTest, Constant_Vector_Splat) {
-    auto* c = b.Constant(mod.constant_values.Splat(ty.vec3<f32>(), b.Constant(1.5_f)->Value(), 3));
+    auto* c = b.Splat(ty.vec3<f32>(), 1.5_f, 3);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()), std::string("float3(1.5f)"));
 }
 
 TEST_F(MslPrinterTest, Constant_Vector_Composite) {
-    auto* c = b.Constant(mod.constant_values.Composite(
-        ty.vec3<f32>(), Vector{b.Constant(1.5_f)->Value(), b.Constant(1.0_f)->Value(),
-                               b.Constant(1.5_f)->Value()}));
+    auto* c = b.Composite(ty.vec3<f32>(), 1.5_f, 1.0_f, 1.5_f);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()), std::string("float3(1.5f, 1.0f, 1.5f)"));
 }
 
 TEST_F(MslPrinterTest, Constant_Vector_Composite_AnyZero) {
-    auto* c = b.Constant(mod.constant_values.Composite(
-        ty.vec3<f32>(), Vector{b.Constant(1.0_f)->Value(), b.Constant(0.0_f)->Value(),
-                               b.Constant(1.5_f)->Value()}));
+    auto* c = b.Composite(ty.vec3<f32>(), 1.0_f, 0.0_f, 1.5_f);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()), std::string("float3(1.0f, 0.0f, 1.5f)"));
 }
 
 TEST_F(MslPrinterTest, Constant_Vector_Composite_AllZero) {
-    auto* c = b.Constant(mod.constant_values.Composite(
-        ty.vec3<f32>(), Vector{b.Constant(0.0_f)->Value(), b.Constant(0.0_f)->Value(),
-                               b.Constant(0.0_f)->Value()}));
+    auto* c = b.Composite(ty.vec3<f32>(), 0.0_f, 0.0_f, 0.0_f);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()), std::string("float3(0.0f)"));
 }
 
 TEST_F(MslPrinterTest, Constant_Matrix_Splat) {
-    auto* c =
-        b.Constant(mod.constant_values.Splat(ty.mat3x2<f32>(), b.Constant(1.5_f)->Value(), 3));
+    auto* c = b.Splat(ty.mat3x2<f32>(), 1.5_f, 3);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()), std::string("float3x2(1.5f, 1.5f, 1.5f)"));
 }
 
 TEST_F(MslPrinterTest, Constant_Matrix_Composite) {
-    auto* c = b.Constant(mod.constant_values.Composite(
-        ty.mat3x2<f32>(),
-        Vector{mod.constant_values.Composite(
-                   ty.vec2<f32>(), Vector{b.Constant(1.5_f)->Value(), b.Constant(1.0_f)->Value()}),
-               mod.constant_values.Composite(
-                   ty.vec2<f32>(), Vector{b.Constant(1.5_f)->Value(), b.Constant(2.0_f)->Value()}),
-               mod.constant_values.Composite(ty.vec2<f32>(), Vector{b.Constant(2.5_f)->Value(),
-                                                                    b.Constant(3.5_f)->Value()})}));
+    auto* c = b.Composite(ty.mat3x2<f32>(),                           //
+                          b.Composite(ty.vec2<f32>(), 1.5_f, 1.0_f),  //
+                          b.Composite(ty.vec2<f32>(), 1.5_f, 2.0_f),  //
+                          b.Composite(ty.vec2<f32>(), 2.5_f, 3.5_f));
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()),
@@ -122,12 +111,9 @@
 }
 
 TEST_F(MslPrinterTest, Constant_Matrix_Composite_AnyZero) {
-    auto* c = b.Constant(mod.constant_values.Composite(
-        ty.mat2x2<f32>(),
-        Vector{mod.constant_values.Composite(
-                   ty.vec2<f32>(), Vector{b.Constant(1.0_f)->Value(), b.Constant(0.0_f)->Value()}),
-               mod.constant_values.Composite(ty.vec2<f32>(), Vector{b.Constant(1.5_f)->Value(),
-                                                                    b.Constant(2.5_f)->Value()})}));
+    auto* c = b.Composite(ty.mat2x2<f32>(),                           //
+                          b.Composite(ty.vec2<f32>(), 1.0_f, 0.0_f),  //
+                          b.Composite(ty.vec2<f32>(), 1.5_f, 2.5_f));
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()),
@@ -135,14 +121,10 @@
 }
 
 TEST_F(MslPrinterTest, Constant_Matrix_Composite_AllZero) {
-    auto* c = b.Constant(mod.constant_values.Composite(
-        ty.mat3x2<f32>(),
-        Vector{mod.constant_values.Composite(
-                   ty.vec2<f32>(), Vector{b.Constant(0.0_f)->Value(), b.Constant(0.0_f)->Value()}),
-               mod.constant_values.Composite(
-                   ty.vec2<f32>(), Vector{b.Constant(0.0_f)->Value(), b.Constant(0.0_f)->Value()}),
-               mod.constant_values.Composite(ty.vec2<f32>(), Vector{b.Constant(0.0_f)->Value(),
-                                                                    b.Constant(0.0_f)->Value()})}));
+    auto* c = b.Composite(ty.mat3x2<f32>(),                           //
+                          b.Composite(ty.vec2<f32>(), 0.0_f, 0.0_f),  //
+                          b.Composite(ty.vec2<f32>(), 0.0_f, 0.0_f),  //
+                          b.Composite(ty.vec2<f32>(), 0.0_f, 0.0_f));
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()),
@@ -150,88 +132,34 @@
 }
 
 TEST_F(MslPrinterTest, Constant_Array_Splat) {
-    auto* c =
-        b.Constant(mod.constant_values.Splat(ty.array<f32, 3>(), b.Constant(1.5_f)->Value(), 3));
+    auto* c = b.Splat(ty.array<f32, 3>(), 1.5_f, 3);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
-    EXPECT_EQ(tint::TrimSpace(generator_.Result()), R"(template<typename T, size_t N>
-struct tint_array {
-  const constant T& operator[](size_t i) const constant { return elements[i]; }
-  device T& operator[](size_t i) device { return elements[i]; }
-  const device T& operator[](size_t i) const device { return elements[i]; }
-  thread T& operator[](size_t i) thread { return elements[i]; }
-  const thread T& operator[](size_t i) const thread { return elements[i]; }
-  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
-  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
-  T elements[N];
-};
-
-
+    EXPECT_EQ(tint::TrimSpace(generator_.Result()), MetalArray() + R"(
 tint_array<float, 3>{1.5f, 1.5f, 1.5f})");
 }
 
 TEST_F(MslPrinterTest, Constant_Array_Composite) {
-    auto* c = b.Constant(mod.constant_values.Composite(
-        ty.array<f32, 3>(), Vector{b.Constant(1.5_f)->Value(), b.Constant(1.0_f)->Value(),
-                                   b.Constant(2.0_f)->Value()}));
+    auto* c = b.Composite(ty.array<f32, 3>(), 1.5_f, 1.0_f, 2.0_f);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
-    EXPECT_EQ(tint::TrimSpace(generator_.Result()), std::string(R"(template<typename T, size_t N>
-struct tint_array {
-  const constant T& operator[](size_t i) const constant { return elements[i]; }
-  device T& operator[](size_t i) device { return elements[i]; }
-  const device T& operator[](size_t i) const device { return elements[i]; }
-  thread T& operator[](size_t i) thread { return elements[i]; }
-  const thread T& operator[](size_t i) const thread { return elements[i]; }
-  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
-  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
-  T elements[N];
-};
-
-
-tint_array<float, 3>{1.5f, 1.0f, 2.0f})"));
+    EXPECT_EQ(tint::TrimSpace(generator_.Result()), MetalArray() + R"(
+tint_array<float, 3>{1.5f, 1.0f, 2.0f})");
 }
 
 TEST_F(MslPrinterTest, Constant_Array_Composite_AnyZero) {
-    auto* c = b.Constant(mod.constant_values.Composite(
-        ty.array<f32, 2>(), Vector{b.Constant(1.0_f)->Value(), b.Constant(0.0_f)->Value()}));
+    auto* c = b.Composite(ty.array<f32, 2>(), 1.0_f, 0.0_f);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
-    EXPECT_EQ(tint::TrimSpace(generator_.Result()), R"(template<typename T, size_t N>
-struct tint_array {
-  const constant T& operator[](size_t i) const constant { return elements[i]; }
-  device T& operator[](size_t i) device { return elements[i]; }
-  const device T& operator[](size_t i) const device { return elements[i]; }
-  thread T& operator[](size_t i) thread { return elements[i]; }
-  const thread T& operator[](size_t i) const thread { return elements[i]; }
-  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
-  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
-  T elements[N];
-};
-
-
+    EXPECT_EQ(tint::TrimSpace(generator_.Result()), MetalArray() + R"(
 tint_array<float, 2>{1.0f, 0.0f})");
 }
 
 TEST_F(MslPrinterTest, Constant_Array_Composite_AllZero) {
-    auto* c = b.Constant(mod.constant_values.Composite(
-        ty.array<f32, 3>(), Vector{b.Constant(0.0_f)->Value(), b.Constant(0.0_f)->Value(),
-                                   b.Constant(0.0_f)->Value()}));
+    auto* c = b.Composite(ty.array<f32, 3>(), 0.0_f, 0.0_f, 0.0_f);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
-    EXPECT_EQ(tint::TrimSpace(generator_.Result()), R"(template<typename T, size_t N>
-struct tint_array {
-  const constant T& operator[](size_t i) const constant { return elements[i]; }
-  device T& operator[](size_t i) device { return elements[i]; }
-  const device T& operator[](size_t i) const device { return elements[i]; }
-  thread T& operator[](size_t i) thread { return elements[i]; }
-  const thread T& operator[](size_t i) const thread { return elements[i]; }
-  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
-  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
-  T elements[N];
-};
-
-
+    EXPECT_EQ(tint::TrimSpace(generator_.Result()), MetalArray() + R"(
 tint_array<float, 3>{})");
 }
 
@@ -240,7 +168,7 @@
                                                   {mod.symbols.Register("a"), ty.f32()},
                                                   {mod.symbols.Register("b"), ty.f32()},
                                               });
-    auto* c = b.Constant(mod.constant_values.Splat(s, b.Constant(1.5_f)->Value(), 2));
+    auto* c = b.Splat(s, 1.5_f, 2);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()), std::string(R"(struct S {
@@ -256,8 +184,7 @@
                                                   {mod.symbols.Register("a"), ty.f32()},
                                                   {mod.symbols.Register("b"), ty.f32()},
                                               });
-    auto* c = b.Constant(mod.constant_values.Composite(
-        s, Vector{b.Constant(1.5_f)->Value(), b.Constant(1.0_f)->Value()}));
+    auto* c = b.Composite(s, 1.5_f, 1.0_f);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()), std::string(R"(struct S {
@@ -273,8 +200,7 @@
                                                   {mod.symbols.Register("a"), ty.f32()},
                                                   {mod.symbols.Register("b"), ty.f32()},
                                               });
-    auto* c = b.Constant(mod.constant_values.Composite(
-        s, Vector{b.Constant(1.0_f)->Value(), b.Constant(0.0_f)->Value()}));
+    auto* c = b.Composite(s, 1.0_f, 0.0_f);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()), std::string(R"(struct S {
@@ -290,8 +216,7 @@
                                                   {mod.symbols.Register("a"), ty.f32()},
                                                   {mod.symbols.Register("b"), ty.f32()},
                                               });
-    auto* c = b.Constant(mod.constant_values.Composite(
-        s, Vector{b.Constant(0.0_f)->Value(), b.Constant(0.0_f)->Value()}));
+    auto* c = b.Composite(s, 0.0_f, 0.0_f);
     generator_.EmitConstant(generator_.Line(), c);
     ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
     EXPECT_EQ(tint::TrimSpace(generator_.Result()), std::string(R"(struct S {
diff --git a/src/tint/lang/spirv/writer/common/helper_test.h b/src/tint/lang/spirv/writer/common/helper_test.h
index d8afa0f..24d8ca1 100644
--- a/src/tint/lang/spirv/writer/common/helper_test.h
+++ b/src/tint/lang/spirv/writer/common/helper_test.h
@@ -36,6 +36,8 @@
 
 namespace tint::spirv::writer {
 
+using namespace tint::number_suffixes;  // NOLINT
+
 // Helper macro to check whether the SPIR-V output contains an instruction, dumping the full output
 // if the instruction was not present.
 #define EXPECT_INST(inst) ASSERT_THAT(output_, testing::HasSubstr(inst)) << output_
@@ -215,30 +217,15 @@
     ir::Constant* MakeVectorValue(TestElementType type) {
         switch (type) {
             case kBool:
-                return b.Constant(mod.constant_values.Composite(
-                    MakeVectorType(type),
-                    Vector<const constant::Value*, 2>{mod.constant_values.Get(true),
-                                                      mod.constant_values.Get(false)}));
+                return b.Composite(MakeVectorType(type), true, false);
             case kI32:
-                return b.Constant(mod.constant_values.Composite(
-                    MakeVectorType(type),
-                    Vector<const constant::Value*, 2>{mod.constant_values.Get(i32(42)),
-                                                      mod.constant_values.Get(i32(-10))}));
+                return b.Composite(MakeVectorType(type), 42_i, -10_i);
             case kU32:
-                return b.Constant(mod.constant_values.Composite(
-                    MakeVectorType(type),
-                    Vector<const constant::Value*, 2>{mod.constant_values.Get(u32(42)),
-                                                      mod.constant_values.Get(u32(10))}));
+                return b.Composite(MakeVectorType(type), 42_u, 10_u);
             case kF32:
-                return b.Constant(mod.constant_values.Composite(
-                    MakeVectorType(type),
-                    Vector<const constant::Value*, 2>{mod.constant_values.Get(f32(42)),
-                                                      mod.constant_values.Get(f32(-0.5))}));
+                return b.Composite(MakeVectorType(type), 42_f, -0.5_f);
             case kF16:
-                return b.Constant(mod.constant_values.Composite(
-                    MakeVectorType(type),
-                    Vector<const constant::Value*, 2>{mod.constant_values.Get(f16(42)),
-                                                      mod.constant_values.Get(f16(-0.5))}));
+                return b.Composite(MakeVectorType(type), 42_h, -0.5_h);
         }
         return nullptr;
     }
diff --git a/src/tint/lang/spirv/writer/constant_test.cc b/src/tint/lang/spirv/writer/constant_test.cc
index 0a37c0a..e5968b5 100644
--- a/src/tint/lang/spirv/writer/constant_test.cc
+++ b/src/tint/lang/spirv/writer/constant_test.cc
@@ -60,64 +60,39 @@
 }
 
 TEST_F(SpirvWriterTest, Constant_Vec4Bool) {
-    auto const_bool = [&](bool val) { return mod.constant_values.Get(val); };
-    auto* v = mod.constant_values.Composite(
-        ty.vec4(ty.bool_()),
-        Vector{const_bool(true), const_bool(false), const_bool(false), const_bool(true)});
-
-    writer_.Constant(b.Constant(v));
+    writer_.Constant(b.Composite(ty.vec4<bool>(), true, false, false, true));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST("%1 = OpConstantComposite %v4bool %true %false %false %true");
 }
 
 TEST_F(SpirvWriterTest, Constant_Vec2i) {
-    auto const_i32 = [&](float val) { return mod.constant_values.Get(i32(val)); };
-    auto* v =
-        mod.constant_values.Composite(ty.vec2(ty.i32()), Vector{const_i32(42), const_i32(-1)});
-    writer_.Constant(b.Constant(v));
+    writer_.Constant(b.Composite(ty.vec2<i32>(), 42_i, -1_i));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST("%1 = OpConstantComposite %v2int %int_42 %int_n1");
 }
 
 TEST_F(SpirvWriterTest, Constant_Vec3u) {
-    auto const_u32 = [&](float val) { return mod.constant_values.Get(u32(val)); };
-    auto* v = mod.constant_values.Composite(
-        ty.vec3(ty.u32()), Vector{const_u32(42), const_u32(0), const_u32(4000000000)});
-    writer_.Constant(b.Constant(v));
+    writer_.Constant(b.Composite(ty.vec3<u32>(), 42_u, 0_u, 4000000000_u));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST("%1 = OpConstantComposite %v3uint %uint_42 %uint_0 %uint_4000000000");
 }
 
 TEST_F(SpirvWriterTest, Constant_Vec4f) {
-    auto const_f32 = [&](float val) { return mod.constant_values.Get(f32(val)); };
-    auto* v = mod.constant_values.Composite(
-        ty.vec4(ty.f32()), Vector{const_f32(42), const_f32(0), const_f32(0.25), const_f32(-1)});
-    writer_.Constant(b.Constant(v));
+    writer_.Constant(b.Composite(ty.vec4<f32>(), 42_f, 0_f, 0.25_f, -1_f));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST("%1 = OpConstantComposite %v4float %float_42 %float_0 %float_0_25 %float_n1");
 }
 
 TEST_F(SpirvWriterTest, Constant_Vec2h) {
-    auto const_f16 = [&](float val) { return mod.constant_values.Get(f16(val)); };
-    auto* v =
-        mod.constant_values.Composite(ty.vec2(ty.f16()), Vector{const_f16(42), const_f16(0.25)});
-    writer_.Constant(b.Constant(v));
+    writer_.Constant(b.Composite(ty.vec2<f16>(), 42_h, 0.25_h));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST("%1 = OpConstantComposite %v2half %half_0x1_5p_5 %half_0x1pn2");
 }
 
 TEST_F(SpirvWriterTest, Constant_Mat2x3f) {
-    auto const_f32 = [&](float val) { return mod.constant_values.Get(f32(val)); };
-    auto* f32 = ty.f32();
-    auto* v = mod.constant_values.Composite(
-        ty.mat2x3(f32),
-        Vector{
-            mod.constant_values.Composite(ty.vec3(f32),
-                                          Vector{const_f32(42), const_f32(-1), const_f32(0.25)}),
-            mod.constant_values.Composite(ty.vec3(f32),
-                                          Vector{const_f32(-42), const_f32(0), const_f32(-0.25)}),
-        });
-    writer_.Constant(b.Constant(v));
+    writer_.Constant(b.Composite(ty.mat2x3<f32>(),  //
+                                 b.Composite(ty.vec3<f32>(), 42_f, -1_f, 0.25_f),
+                                 b.Composite(ty.vec3<f32>(), -42_f, 0_f, -0.25_f)));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST(R"(
    %float_42 = OpConstant %float 42
@@ -133,17 +108,11 @@
 }
 
 TEST_F(SpirvWriterTest, Constant_Mat4x2h) {
-    auto const_f16 = [&](float val) { return mod.constant_values.Get(f16(val)); };
-    auto* f16 = ty.f16();
-    auto* v = mod.constant_values.Composite(
-        ty.mat4x2(f16),
-        Vector{
-            mod.constant_values.Composite(ty.vec2(f16), Vector{const_f16(42), const_f16(-1)}),
-            mod.constant_values.Composite(ty.vec2(f16), Vector{const_f16(0), const_f16(0.25)}),
-            mod.constant_values.Composite(ty.vec2(f16), Vector{const_f16(-42), const_f16(1)}),
-            mod.constant_values.Composite(ty.vec2(f16), Vector{const_f16(0.5), const_f16(-0)}),
-        });
-    writer_.Constant(b.Constant(v));
+    writer_.Constant(b.Composite(ty.mat4x2<f16>(),                          //
+                                 b.Composite(ty.vec2<f16>(), 42_h, -1_h),   //
+                                 b.Composite(ty.vec2<f16>(), 0_h, 0.25_h),  //
+                                 b.Composite(ty.vec2<f16>(), -42_h, 1_h),   //
+                                 b.Composite(ty.vec2<f16>(), 0.5_h, f16(-0))));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST(R"(
 %half_0x1_5p_5 = OpConstant %half 0x1.5p+5
@@ -162,33 +131,14 @@
 }
 
 TEST_F(SpirvWriterTest, Constant_Array_I32) {
-    auto* arr =
-        mod.constant_values.Composite(ty.array(ty.i32(), 4), Vector{
-                                                                 mod.constant_values.Get(1_i),
-                                                                 mod.constant_values.Get(2_i),
-                                                                 mod.constant_values.Get(3_i),
-                                                                 mod.constant_values.Get(4_i),
-                                                             });
-    writer_.Constant(b.Constant(arr));
+    writer_.Constant(b.Composite(ty.array<i32, 4>(), 1_i, 2_i, 3_i, 4_i));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST("%1 = OpConstantComposite %_arr_int_uint_4 %int_1 %int_2 %int_3 %int_4");
 }
 
 TEST_F(SpirvWriterTest, Constant_Array_Array_I32) {
-    auto* inner =
-        mod.constant_values.Composite(ty.array(ty.i32(), 4), Vector{
-                                                                 mod.constant_values.Get(1_i),
-                                                                 mod.constant_values.Get(2_i),
-                                                                 mod.constant_values.Get(3_i),
-                                                                 mod.constant_values.Get(4_i),
-                                                             });
-    auto* arr = mod.constant_values.Composite(ty.array(ty.array(ty.i32(), 4), 4), Vector{
-                                                                                      inner,
-                                                                                      inner,
-                                                                                      inner,
-                                                                                      inner,
-                                                                                  });
-    writer_.Constant(b.Constant(arr));
+    auto* inner = b.Composite(ty.array<i32, 4>(), 1_i, 2_i, 3_i, 4_i);
+    writer_.Constant(b.Composite(ty.array(ty.array<i32, 4>(), 4), inner, inner, inner, inner));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST(R"(
           %7 = OpConstantComposite %_arr_int_uint_4 %int_1 %int_2 %int_3 %int_4
@@ -202,21 +152,16 @@
                                                               {mod.symbols.New("b"), ty.u32()},
                                                               {mod.symbols.New("c"), ty.f32()},
                                                           });
-    auto* str = mod.constant_values.Composite(str_ty, Vector{
-                                                          mod.constant_values.Get(1_i),
-                                                          mod.constant_values.Get(2_u),
-                                                          mod.constant_values.Get(3_f),
-                                                      });
-    writer_.Constant(b.Constant(str));
+    writer_.Constant(b.Composite(str_ty, 1_i, 2_u, 3_f));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST("%1 = OpConstantComposite %MyStruct %int_1 %uint_2 %float_3");
 }
 
 // Test that we do not emit the same constant more than once.
 TEST_F(SpirvWriterTest, Constant_Deduplicate) {
-    writer_.Constant(b.Constant(i32(42)));
-    writer_.Constant(b.Constant(i32(42)));
-    writer_.Constant(b.Constant(i32(42)));
+    writer_.Constant(b.Constant(42_i));
+    writer_.Constant(b.Constant(42_i));
+    writer_.Constant(b.Constant(42_i));
     ASSERT_TRUE(Generate()) << Error() << output_;
     EXPECT_INST("%int_42 = OpConstant %int 42");
 }
diff --git a/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc b/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
index 17c3c4f..193e637 100644
--- a/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
@@ -161,7 +161,7 @@
     /// @param value the literal value
     /// @returns the literal operand
     LiteralOperand* Literal(u32 value) {
-        return ir->values.Create<LiteralOperand>(ir->constant_values.Get(value));
+        return ir->values.Create<LiteralOperand>(b.ConstantValue(value));
     }
 
     /// Handle an `arrayLength()` builtin.
diff --git a/src/tint/lang/spirv/writer/raise/builtin_polyfill_test.cc b/src/tint/lang/spirv/writer/raise/builtin_polyfill_test.cc
index 767a585..0f4463f 100644
--- a/src/tint/lang/spirv/writer/raise/builtin_polyfill_test.cc
+++ b/src/tint/lang/spirv/writer/raise/builtin_polyfill_test.cc
@@ -1382,9 +1382,8 @@
     func->SetParams({t, s, coords});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureSample, t, s, coords,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureSample, t, s, coords,
+                              b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -1423,9 +1422,8 @@
     func->SetParams({t, s, coords, array_idx});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureSample, t, s, coords, array_idx,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureSample, t, s, coords,
+                              array_idx, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -1506,9 +1504,8 @@
     func->SetParams({t, s, coords, bias});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureSampleBias, t, s, coords, bias,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureSampleBias, t, s, coords,
+                              bias, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -1548,9 +1545,8 @@
     func->SetParams({t, s, coords, array_idx, bias});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureSampleBias, t, s, coords, array_idx, bias,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureSampleBias, t, s, coords,
+                              array_idx, bias, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -1629,9 +1625,8 @@
     func->SetParams({t, s, coords, dref});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.f32(), builtin::Function::kTextureSampleCompare, t, s, coords, dref,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.f32(), builtin::Function::kTextureSampleCompare, t, s, coords,
+                              dref, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -1670,9 +1665,8 @@
     func->SetParams({t, s, coords, array_idx, bias});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.f32(), builtin::Function::kTextureSampleCompare, t, s, coords, array_idx, bias,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.f32(), builtin::Function::kTextureSampleCompare, t, s, coords,
+                              array_idx, bias, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -1751,9 +1745,8 @@
     func->SetParams({t, s, coords, dref});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.f32(), builtin::Function::kTextureSampleCompareLevel, t, s, coords, dref,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.f32(), builtin::Function::kTextureSampleCompareLevel, t, s, coords,
+                              dref, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -1792,9 +1785,8 @@
     func->SetParams({t, s, coords, array_idx, bias});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.f32(), builtin::Function::kTextureSampleCompareLevel, t, s, coords, array_idx, bias,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.f32(), builtin::Function::kTextureSampleCompareLevel, t, s, coords,
+                              array_idx, bias, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -1877,9 +1869,8 @@
     func->SetParams({t, s, coords, ddx, ddy});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureSampleBias, t, s, coords, ddx, ddy,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureSampleBias, t, s, coords,
+                              ddx, ddy, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -1920,10 +1911,8 @@
     func->SetParams({t, s, coords, array_idx, ddx, ddy});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureSampleBias, t, s, coords, array_idx, ddx,
-            ddy,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureSampleBias, t, s, coords,
+                              array_idx, ddx, ddy, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -2004,9 +1993,8 @@
     func->SetParams({t, s, coords, lod});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureSampleLevel, t, s, coords, lod,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureSampleLevel, t, s, coords,
+                              lod, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -2046,9 +2034,8 @@
     func->SetParams({t, s, coords, array_idx, lod});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureSampleLevel, t, s, coords, array_idx, lod,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureSampleLevel, t, s, coords,
+                              array_idx, lod, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -2129,9 +2116,8 @@
     func->SetParams({t, s, component, coords});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureGather, component, t, s, coords,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureGather, component, t, s,
+                              coords, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -2171,9 +2157,8 @@
     func->SetParams({t, s, component, coords, array_idx});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureGather, component, t, s, coords, array_idx,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureGather, component, t, s,
+                              coords, array_idx, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
@@ -2289,9 +2274,8 @@
     func->SetParams({t, s, coords, depth});
 
     b.Append(func->Block(), [&] {
-        auto* result = b.Call(
-            ty.vec4<f32>(), builtin::Function::kTextureGatherCompare, t, s, coords, depth,
-            b.Constant(mod.constant_values.Splat(ty.vec2<i32>(), mod.constant_values.Get(1_i), 2)));
+        auto* result = b.Call(ty.vec4<f32>(), builtin::Function::kTextureGatherCompare, t, s,
+                              coords, depth, b.Splat(ty.vec2<i32>(), 1_i, 2));
         b.Return(func, result);
     });
 
diff --git a/src/tint/lang/spirv/writer/texture_builtin_test.cc b/src/tint/lang/spirv/writer/texture_builtin_test.cc
index 7ff1426..b4183b4 100644
--- a/src/tint/lang/spirv/writer/texture_builtin_test.cc
+++ b/src/tint/lang/spirv/writer/texture_builtin_test.cc
@@ -174,8 +174,7 @@
             for (const auto& arg : params.args) {
                 auto* value = MakeScalarValue(arg.type, arg_value++);
                 if (arg.width > 1) {
-                    value = b.Constant(mod.constant_values.Splat(ty.vec(value->Type(), arg.width),
-                                                                 value->Value(), arg.width));
+                    value = b.Splat(ty.vec(value->Type(), arg.width), value, arg.width);
                 }
                 args.Push(value);
                 mod.SetName(value, arg.name);