Преглед изворни кода

Constant evaluation support for initializing expressions. (#3624)

The constant value we associate with an initializing representation is
the object representation that the initializing expression will store to
its destination.

Also include the type in the profile of an instruction. This is now
necessary for array values, which are represented as tuple_value
instructions with array type, to avoid instructions with different types
being merged by constant canonicalization.
Richard Smith пре 2 година
родитељ
комит
87ecb34f6b
54 измењених фајлова са 587 додато и 397 уклоњено
  1. 49 16
      toolchain/check/eval.cpp
  2. 77 0
      toolchain/check/testdata/array/array_vs_tuple.carbon
  3. 15 14
      toolchain/check/testdata/array/assign_var.carbon
  4. 50 46
      toolchain/check/testdata/array/base.carbon
  5. 1 1
      toolchain/check/testdata/array/fail_type_mismatch.carbon
  6. 6 5
      toolchain/check/testdata/array/function_param.carbon
  7. 12 11
      toolchain/check/testdata/array/nine_elements.carbon
  8. 42 40
      toolchain/check/testdata/basics/numeric_literals.carbon
  9. 4 2
      toolchain/check/testdata/basics/raw_and_textual_ir.carbon
  10. 2 0
      toolchain/check/testdata/basics/raw_ir.carbon
  11. 2 2
      toolchain/check/testdata/basics/textual_ir.carbon
  12. 11 9
      toolchain/check/testdata/class/base.carbon
  13. 11 8
      toolchain/check/testdata/class/derived_to_base.carbon
  14. 7 7
      toolchain/check/testdata/class/fail_init.carbon
  15. 5 4
      toolchain/check/testdata/class/fail_init_as_inplace.carbon
  16. 4 3
      toolchain/check/testdata/class/init_as.carbon
  17. 3 2
      toolchain/check/testdata/class/method.carbon
  18. 8 7
      toolchain/check/testdata/function/call/more_param_ir.carbon
  19. 4 3
      toolchain/check/testdata/if_expr/basic.carbon
  20. 6 5
      toolchain/check/testdata/if_expr/struct.carbon
  21. 9 8
      toolchain/check/testdata/index/array_element_access.carbon
  22. 21 20
      toolchain/check/testdata/index/expr_category.carbon
  23. 6 5
      toolchain/check/testdata/index/fail_array_large_index.carbon
  24. 6 5
      toolchain/check/testdata/index/fail_array_non_int_indexing.carbon
  25. 6 5
      toolchain/check/testdata/index/fail_array_out_of_bound_access.carbon
  26. 2 1
      toolchain/check/testdata/index/fail_negative_indexing.carbon
  27. 7 6
      toolchain/check/testdata/index/fail_non_deterministic_type.carbon
  28. 5 4
      toolchain/check/testdata/index/fail_tuple_index_error.carbon
  29. 5 4
      toolchain/check/testdata/index/fail_tuple_large_index.carbon
  30. 7 6
      toolchain/check/testdata/index/fail_tuple_non_int_indexing.carbon
  31. 7 6
      toolchain/check/testdata/index/fail_tuple_out_of_bound_access.carbon
  32. 5 4
      toolchain/check/testdata/index/tuple_element_access.carbon
  33. 6 5
      toolchain/check/testdata/let/convert.carbon
  34. 29 27
      toolchain/check/testdata/operators/assignment.carbon
  35. 31 29
      toolchain/check/testdata/operators/fail_assignment_to_non_assignable.carbon
  36. 21 19
      toolchain/check/testdata/pointer/address_of_lvalue.carbon
  37. 5 4
      toolchain/check/testdata/return/fail_return_with_returned_var.carbon
  38. 7 6
      toolchain/check/testdata/return/returned_var.carbon
  39. 5 4
      toolchain/check/testdata/return/tuple.carbon
  40. 5 4
      toolchain/check/testdata/struct/empty.carbon
  41. 3 2
      toolchain/check/testdata/struct/fail_member_access_type.carbon
  42. 3 2
      toolchain/check/testdata/struct/fail_non_member_access.carbon
  43. 5 4
      toolchain/check/testdata/struct/member_access.carbon
  44. 3 2
      toolchain/check/testdata/struct/one_entry.carbon
  45. 8 6
      toolchain/check/testdata/struct/tuple_as_element.carbon
  46. 4 4
      toolchain/check/testdata/struct/two_entries.carbon
  47. 5 4
      toolchain/check/testdata/tuples/empty.carbon
  48. 1 1
      toolchain/check/testdata/tuples/fail_element_type_mismatch.carbon
  49. 9 7
      toolchain/check/testdata/tuples/nested_tuple.carbon
  50. 2 2
      toolchain/check/testdata/tuples/nested_tuple_in_place.carbon
  51. 3 2
      toolchain/check/testdata/tuples/one_element.carbon
  52. 4 4
      toolchain/check/testdata/tuples/two_elements.carbon
  53. 1 0
      toolchain/sem_ir/inst_profile.cpp
  54. 22 0
      toolchain/sem_ir/typed_insts.h

+ 49 - 16
toolchain/check/eval.cpp

@@ -138,6 +138,22 @@ static auto RebuildIfFieldsAreConstant(Context& context, SemIR::Inst inst,
                                            : SemIR::ConstantId::NotConstant;
 }
 
+// Rebuilds the given aggregate initialization instruction as a corresponding
+// constant aggregate value, if its elements are all constants.
+static auto RebuildInitAsValue(Context& context, SemIR::Inst inst,
+                               SemIR::InstKind value_kind)
+    -> SemIR::ConstantId {
+  auto init_inst = inst.As<SemIR::AnyAggregateInit>();
+  Phase phase = Phase::Template;
+  auto elements_id = GetConstantValue(context, init_inst.elements_id, &phase);
+  return MakeConstantResult(
+      context,
+      SemIR::AnyAggregateValue{.kind = value_kind,
+                               .type_id = init_inst.type_id,
+                               .elements_id = elements_id},
+      phase);
+}
+
 auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
     -> SemIR::ConstantId {
   // TODO: Ensure we have test coverage for each of these cases that can result
@@ -163,13 +179,24 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
     case SemIR::StructValue::Kind:
       return RebuildIfFieldsAreConstant(context, inst,
                                         &SemIR::StructValue::elements_id);
-    case SemIR::Temporary::Kind:
-      return RebuildIfFieldsAreConstant(context, inst,
-                                        &SemIR::Temporary::init_id);
     case SemIR::TupleValue::Kind:
       return RebuildIfFieldsAreConstant(context, inst,
                                         &SemIR::TupleValue::elements_id);
 
+    // Initializers evaluate to a value of the object representation.
+    case SemIR::ArrayInit::Kind:
+      // TODO: Add an `ArrayValue` to represent a constant array object
+      // representation instead of using a `TupleValue`.
+      return RebuildInitAsValue(context, inst, SemIR::TupleValue::Kind);
+    case SemIR::ClassInit::Kind:
+      // TODO: Add a `ClassValue` to represent a constant class object
+      // representation instead of using a `StructValue`.
+      return RebuildInitAsValue(context, inst, SemIR::StructValue::Kind);
+    case SemIR::StructInit::Kind:
+      return RebuildInitAsValue(context, inst, SemIR::StructValue::Kind);
+    case SemIR::TupleInit::Kind:
+      return RebuildInitAsValue(context, inst, SemIR::TupleValue::Kind);
+
     // These cases are always constants.
     case SemIR::Builtin::Kind:
     case SemIR::ClassType::Kind:
@@ -200,25 +227,22 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
       // by `APInt`s with different bit widths.
       return MakeConstantResult(context, inst, Phase::Template);
 
-    // TODO: These need special handling.
+    // TODO: Support subobject access.
     case SemIR::ArrayIndex::Kind:
-    case SemIR::ArrayInit::Kind:
+    case SemIR::ClassElementAccess::Kind:
+    case SemIR::StructAccess::Kind:
+    case SemIR::TupleAccess::Kind:
+    case SemIR::TupleIndex::Kind:
+      break;
+
+    // TODO: These need special handling.
     case SemIR::BindValue::Kind:
     case SemIR::Call::Kind:
-    case SemIR::ClassElementAccess::Kind:
-    case SemIR::ClassInit::Kind:
     case SemIR::CrossRef::Kind:
     case SemIR::Deref::Kind:
-    case SemIR::InitializeFrom::Kind:
-    case SemIR::SpliceBlock::Kind:
-    case SemIR::StructAccess::Kind:
-    case SemIR::StructInit::Kind:
+    case SemIR::Temporary::Kind:
     case SemIR::TemporaryStorage::Kind:
-    case SemIR::TupleAccess::Kind:
-    case SemIR::TupleIndex::Kind:
-    case SemIR::TupleInit::Kind:
     case SemIR::ValueAsRef::Kind:
-    case SemIR::ValueOfInitializer::Kind:
       break;
 
     case SemIR::BindSymbolicName::Kind:
@@ -233,12 +257,21 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
       // creating a `BindName` in that case?
       return context.constant_values().Get(inst.As<SemIR::BindName>().value_id);
 
+    // These semnatic wrappers don't change the constant value.
     case SemIR::NameRef::Kind:
       return context.constant_values().Get(inst.As<SemIR::NameRef>().value_id);
-
     case SemIR::Converted::Kind:
       return context.constant_values().Get(
           inst.As<SemIR::Converted>().result_id);
+    case SemIR::InitializeFrom::Kind:
+      return context.constant_values().Get(
+          inst.As<SemIR::InitializeFrom>().src_id);
+    case SemIR::SpliceBlock::Kind:
+      return context.constant_values().Get(
+          inst.As<SemIR::SpliceBlock>().result_id);
+    case SemIR::ValueOfInitializer::Kind:
+      return context.constant_values().Get(
+          inst.As<SemIR::ValueOfInitializer>().init_id);
 
     // `not true` -> `false`, `not false` -> `true`.
     // All other uses of unary `not` are non-constant.

+ 77 - 0
toolchain/check/testdata/array/array_vs_tuple.carbon

@@ -0,0 +1,77 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+
+fn G() {
+  // These should have two different constant values.
+  var a: [i32; 3] = (1, 2, 3);
+  var b: (i32, i32, i32) = (1, 2, 3);
+}
+
+// CHECK:STDOUT: --- array_vs_tuple.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %.1: i32 = int_literal 3 [template]
+// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
+// CHECK:STDOUT:   %.3: type = ptr_type [i32; 3] [template]
+// CHECK:STDOUT:   %.4: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.6: type = tuple_type (i32, i32, i32) [template]
+// CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.8: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.9: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.10: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %.11: type = tuple_type (type, type, type) [template]
+// CHECK:STDOUT:   %.12: type = ptr_type (i32, i32, i32) [template]
+// CHECK:STDOUT:   %.13: (i32, i32, i32) = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace package, {.G = %G} [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @G() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %.loc9_16: i32 = int_literal 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc9_17: type = array_type %.loc9_16, i32 [template = constants.%.2]
+// CHECK:STDOUT:   %a.var: ref [i32; 3] = var a
+// CHECK:STDOUT:   %a: ref [i32; 3] = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc9_22: i32 = int_literal 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc9_25: i32 = int_literal 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc9_28: i32 = int_literal 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc9_29.1: (i32, i32, i32) = tuple_literal (%.loc9_22, %.loc9_25, %.loc9_28)
+// CHECK:STDOUT:   %.loc9_29.2: i32 = int_literal 0 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc9_29.3: ref i32 = array_index %a.var, %.loc9_29.2
+// CHECK:STDOUT:   %.loc9_29.4: init i32 = initialize_from %.loc9_22 to %.loc9_29.3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc9_29.5: i32 = int_literal 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc9_29.6: ref i32 = array_index %a.var, %.loc9_29.5
+// CHECK:STDOUT:   %.loc9_29.7: init i32 = initialize_from %.loc9_25 to %.loc9_29.6 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc9_29.8: i32 = int_literal 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc9_29.9: ref i32 = array_index %a.var, %.loc9_29.8
+// CHECK:STDOUT:   %.loc9_29.10: init i32 = initialize_from %.loc9_28 to %.loc9_29.9 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc9_29.11: init [i32; 3] = array_init (%.loc9_29.4, %.loc9_29.7, %.loc9_29.10) to %a.var [template = constants.%.10]
+// CHECK:STDOUT:   %.loc9_29.12: init [i32; 3] = converted %.loc9_29.1, %.loc9_29.11 [template = constants.%.10]
+// CHECK:STDOUT:   assign %a.var, %.loc9_29.12
+// CHECK:STDOUT:   %.loc10_24.1: (type, type, type) = tuple_literal (i32, i32, i32)
+// CHECK:STDOUT:   %.loc10_24.2: type = converted %.loc10_24.1, constants.%.6 [template = constants.%.6]
+// CHECK:STDOUT:   %b.var: ref (i32, i32, i32) = var b
+// CHECK:STDOUT:   %b: ref (i32, i32, i32) = bind_name b, %b.var
+// CHECK:STDOUT:   %.loc10_29: i32 = int_literal 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc10_32: i32 = int_literal 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc10_35: i32 = int_literal 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc10_36.1: (i32, i32, i32) = tuple_literal (%.loc10_29, %.loc10_32, %.loc10_35)
+// CHECK:STDOUT:   %.loc10_36.2: ref i32 = tuple_access %b.var, element0
+// CHECK:STDOUT:   %.loc10_36.3: init i32 = initialize_from %.loc10_29 to %.loc10_36.2 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc10_36.4: ref i32 = tuple_access %b.var, element1
+// CHECK:STDOUT:   %.loc10_36.5: init i32 = initialize_from %.loc10_32 to %.loc10_36.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc10_36.6: ref i32 = tuple_access %b.var, element2
+// CHECK:STDOUT:   %.loc10_36.7: init i32 = initialize_from %.loc10_35 to %.loc10_36.6 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc10_36.8: init (i32, i32, i32) = tuple_init (%.loc10_36.3, %.loc10_36.5, %.loc10_36.7) to %b.var [template = constants.%.13]
+// CHECK:STDOUT:   %.loc10_36.9: init (i32, i32, i32) = converted %.loc10_36.1, %.loc10_36.8 [template = constants.%.13]
+// CHECK:STDOUT:   assign %b.var, %.loc10_36.9
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 15 - 14
toolchain/check/testdata/array/assign_var.carbon

@@ -16,11 +16,12 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:   %.4: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 3 [template]
-// CHECK:STDOUT:   %.7: type = array_type %.6, i32 [template]
-// CHECK:STDOUT:   %.8: type = ptr_type [i32; 3] [template]
-// CHECK:STDOUT:   %.9: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.10: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.11: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.7: (i32, i32, i32) = tuple_value (%.4, %.5, %.6) [template]
+// CHECK:STDOUT:   %.8: type = array_type %.6, i32 [template]
+// CHECK:STDOUT:   %.9: type = ptr_type [i32; 3] [template]
+// CHECK:STDOUT:   %.10: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.11: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.12: i32 = int_literal 2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -34,32 +35,32 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:   %.loc7_33: i32 = int_literal 3 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc7_34.1: (i32, i32, i32) = tuple_literal (%.loc7_27, %.loc7_30, %.loc7_33)
 // CHECK:STDOUT:   %.loc7_34.2: ref i32 = tuple_access %a.var, element0
-// CHECK:STDOUT:   %.loc7_34.3: init i32 = initialize_from %.loc7_27 to %.loc7_34.2
+// CHECK:STDOUT:   %.loc7_34.3: init i32 = initialize_from %.loc7_27 to %.loc7_34.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_34.4: ref i32 = tuple_access %a.var, element1
-// CHECK:STDOUT:   %.loc7_34.5: init i32 = initialize_from %.loc7_30 to %.loc7_34.4
+// CHECK:STDOUT:   %.loc7_34.5: init i32 = initialize_from %.loc7_30 to %.loc7_34.4 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_34.6: ref i32 = tuple_access %a.var, element2
-// CHECK:STDOUT:   %.loc7_34.7: init i32 = initialize_from %.loc7_33 to %.loc7_34.6
-// CHECK:STDOUT:   %.loc7_34.8: init (i32, i32, i32) = tuple_init (%.loc7_34.3, %.loc7_34.5, %.loc7_34.7) to %a.var
-// CHECK:STDOUT:   %.loc7_34.9: init (i32, i32, i32) = converted %.loc7_34.1, %.loc7_34.8
+// CHECK:STDOUT:   %.loc7_34.7: init i32 = initialize_from %.loc7_33 to %.loc7_34.6 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc7_34.8: init (i32, i32, i32) = tuple_init (%.loc7_34.3, %.loc7_34.5, %.loc7_34.7) to %a.var [template = constants.%.7]
+// CHECK:STDOUT:   %.loc7_34.9: init (i32, i32, i32) = converted %.loc7_34.1, %.loc7_34.8 [template = constants.%.7]
 // CHECK:STDOUT:   assign %a.var, %.loc7_34.9
 // CHECK:STDOUT:   %.loc8_14: i32 = int_literal 3 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc8_15: type = array_type %.loc8_14, i32 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc8_15: type = array_type %.loc8_14, i32 [template = constants.%.8]
 // CHECK:STDOUT:   %b.var: ref [i32; 3] = var b
 // CHECK:STDOUT:   %b: ref [i32; 3] = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: ref (i32, i32, i32) = name_ref a, %a
 // CHECK:STDOUT:   %.loc8_19.1: ref i32 = tuple_access %a.ref, element0
 // CHECK:STDOUT:   %.loc8_19.2: i32 = bind_value %.loc8_19.1
-// CHECK:STDOUT:   %.loc8_19.3: i32 = int_literal 0 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc8_19.3: i32 = int_literal 0 [template = constants.%.10]
 // CHECK:STDOUT:   %.loc8_19.4: ref i32 = array_index %b.var, %.loc8_19.3
 // CHECK:STDOUT:   %.loc8_19.5: init i32 = initialize_from %.loc8_19.2 to %.loc8_19.4
 // CHECK:STDOUT:   %.loc8_19.6: ref i32 = tuple_access %a.ref, element1
 // CHECK:STDOUT:   %.loc8_19.7: i32 = bind_value %.loc8_19.6
-// CHECK:STDOUT:   %.loc8_19.8: i32 = int_literal 1 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc8_19.8: i32 = int_literal 1 [template = constants.%.11]
 // CHECK:STDOUT:   %.loc8_19.9: ref i32 = array_index %b.var, %.loc8_19.8
 // CHECK:STDOUT:   %.loc8_19.10: init i32 = initialize_from %.loc8_19.7 to %.loc8_19.9
 // CHECK:STDOUT:   %.loc8_19.11: ref i32 = tuple_access %a.ref, element2
 // CHECK:STDOUT:   %.loc8_19.12: i32 = bind_value %.loc8_19.11
-// CHECK:STDOUT:   %.loc8_19.13: i32 = int_literal 2 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc8_19.13: i32 = int_literal 2 [template = constants.%.12]
 // CHECK:STDOUT:   %.loc8_19.14: ref i32 = array_index %b.var, %.loc8_19.13
 // CHECK:STDOUT:   %.loc8_19.15: init i32 = initialize_from %.loc8_19.12 to %.loc8_19.14
 // CHECK:STDOUT:   %.loc8_19.16: init [i32; 3] = array_init (%.loc8_19.5, %.loc8_19.10, %.loc8_19.15) to %b.var

+ 50 - 46
toolchain/check/testdata/array/base.carbon

@@ -16,21 +16,25 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.3: type = ptr_type [i32; 1] [template]
 // CHECK:STDOUT:   %.4: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.6: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.7: type = array_type %.6, f64 [template]
-// CHECK:STDOUT:   %.8: type = ptr_type [f64; 2] [template]
-// CHECK:STDOUT:   %.9: f64 = real_literal 111e-1 [template]
-// CHECK:STDOUT:   %.10: f64 = real_literal 22e-1 [template]
-// CHECK:STDOUT:   %.11: type = tuple_type (f64, f64) [template]
-// CHECK:STDOUT:   %.12: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.13: type = tuple_type () [template]
-// CHECK:STDOUT:   %.14: i32 = int_literal 5 [template]
-// CHECK:STDOUT:   %.15: type = array_type %.14, () [template]
-// CHECK:STDOUT:   %.16: type = ptr_type [(); 5] [template]
-// CHECK:STDOUT:   %.17: type = tuple_type ((), (), (), (), ()) [template]
-// CHECK:STDOUT:   %.18: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.19: i32 = int_literal 3 [template]
-// CHECK:STDOUT:   %.20: i32 = int_literal 4 [template]
+// CHECK:STDOUT:   %.6: [i32; 1] = tuple_value (%.1) [template]
+// CHECK:STDOUT:   %.7: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.8: type = array_type %.7, f64 [template]
+// CHECK:STDOUT:   %.9: type = ptr_type [f64; 2] [template]
+// CHECK:STDOUT:   %.10: f64 = real_literal 111e-1 [template]
+// CHECK:STDOUT:   %.11: f64 = real_literal 22e-1 [template]
+// CHECK:STDOUT:   %.12: type = tuple_type (f64, f64) [template]
+// CHECK:STDOUT:   %.13: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.14: [f64; 2] = tuple_value (%.10, %.11) [template]
+// CHECK:STDOUT:   %.15: type = tuple_type () [template]
+// CHECK:STDOUT:   %.16: i32 = int_literal 5 [template]
+// CHECK:STDOUT:   %.17: type = array_type %.16, () [template]
+// CHECK:STDOUT:   %.18: type = ptr_type [(); 5] [template]
+// CHECK:STDOUT:   %.19: type = tuple_type ((), (), (), (), ()) [template]
+// CHECK:STDOUT:   %.20: () = tuple_value () [template]
+// CHECK:STDOUT:   %.21: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.22: i32 = int_literal 3 [template]
+// CHECK:STDOUT:   %.23: i32 = int_literal 4 [template]
+// CHECK:STDOUT:   %.24: [(); 5] = tuple_value (%.20, %.20, %.20, %.20, %.20) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -43,30 +47,30 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.loc7_22.1: (i32,) = tuple_literal (%.loc7_20)
 // CHECK:STDOUT:   %.loc7_22.2: i32 = int_literal 0 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_22.3: ref i32 = array_index %a.var, %.loc7_22.2
-// CHECK:STDOUT:   %.loc7_22.4: init i32 = initialize_from %.loc7_20 to %.loc7_22.3
-// CHECK:STDOUT:   %.loc7_22.5: init [i32; 1] = array_init (%.loc7_22.4) to %a.var
-// CHECK:STDOUT:   %.loc7_22.6: init [i32; 1] = converted %.loc7_22.1, %.loc7_22.5
+// CHECK:STDOUT:   %.loc7_22.4: init i32 = initialize_from %.loc7_20 to %.loc7_22.3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc7_22.5: init [i32; 1] = array_init (%.loc7_22.4) to %a.var [template = constants.%.6]
+// CHECK:STDOUT:   %.loc7_22.6: init [i32; 1] = converted %.loc7_22.1, %.loc7_22.5 [template = constants.%.6]
 // CHECK:STDOUT:   assign %a.var, %.loc7_22.6
-// CHECK:STDOUT:   %.loc8_14: i32 = int_literal 2 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc8_15: type = array_type %.loc8_14, f64 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc8_14: i32 = int_literal 2 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc8_15: type = array_type %.loc8_14, f64 [template = constants.%.8]
 // CHECK:STDOUT:   %b.var: ref [f64; 2] = var b
 // CHECK:STDOUT:   %b: ref [f64; 2] = bind_name b, %b.var
-// CHECK:STDOUT:   %.loc8_20: f64 = real_literal 111e-1 [template = constants.%.9]
-// CHECK:STDOUT:   %.loc8_26: f64 = real_literal 22e-1 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc8_20: f64 = real_literal 111e-1 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc8_26: f64 = real_literal 22e-1 [template = constants.%.11]
 // CHECK:STDOUT:   %.loc8_30.1: (f64, f64) = tuple_literal (%.loc8_20, %.loc8_26)
 // CHECK:STDOUT:   %.loc8_30.2: i32 = int_literal 0 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc8_30.3: ref f64 = array_index %b.var, %.loc8_30.2
-// CHECK:STDOUT:   %.loc8_30.4: init f64 = initialize_from %.loc8_20 to %.loc8_30.3
-// CHECK:STDOUT:   %.loc8_30.5: i32 = int_literal 1 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc8_30.4: init f64 = initialize_from %.loc8_20 to %.loc8_30.3 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc8_30.5: i32 = int_literal 1 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc8_30.6: ref f64 = array_index %b.var, %.loc8_30.5
-// CHECK:STDOUT:   %.loc8_30.7: init f64 = initialize_from %.loc8_26 to %.loc8_30.6
-// CHECK:STDOUT:   %.loc8_30.8: init [f64; 2] = array_init (%.loc8_30.4, %.loc8_30.7) to %b.var
-// CHECK:STDOUT:   %.loc8_30.9: init [f64; 2] = converted %.loc8_30.1, %.loc8_30.8
+// CHECK:STDOUT:   %.loc8_30.7: init f64 = initialize_from %.loc8_26 to %.loc8_30.6 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc8_30.8: init [f64; 2] = array_init (%.loc8_30.4, %.loc8_30.7) to %b.var [template = constants.%.14]
+// CHECK:STDOUT:   %.loc8_30.9: init [f64; 2] = converted %.loc8_30.1, %.loc8_30.8 [template = constants.%.14]
 // CHECK:STDOUT:   assign %b.var, %.loc8_30.9
 // CHECK:STDOUT:   %.loc9_10.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc9_13: i32 = int_literal 5 [template = constants.%.14]
-// CHECK:STDOUT:   %.loc9_10.2: type = converted %.loc9_10.1, constants.%.13 [template = constants.%.13]
-// CHECK:STDOUT:   %.loc9_14: type = array_type %.loc9_13, () [template = constants.%.15]
+// CHECK:STDOUT:   %.loc9_13: i32 = int_literal 5 [template = constants.%.16]
+// CHECK:STDOUT:   %.loc9_10.2: type = converted %.loc9_10.1, constants.%.15 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc9_14: type = array_type %.loc9_13, () [template = constants.%.17]
 // CHECK:STDOUT:   %c.var: ref [(); 5] = var c
 // CHECK:STDOUT:   %c: ref [(); 5] = bind_name c, %c.var
 // CHECK:STDOUT:   %.loc9_20.1: () = tuple_literal ()
@@ -77,26 +81,26 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.loc9_38.1: ((), (), (), (), ()) = tuple_literal (%.loc9_20.1, %.loc9_24.1, %.loc9_28.1, %.loc9_32.1, %.loc9_36.1)
 // CHECK:STDOUT:   %.loc9_38.2: i32 = int_literal 0 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc9_38.3: ref () = array_index %c.var, %.loc9_38.2
-// CHECK:STDOUT:   %.loc9_20.2: init () = tuple_init () to %.loc9_38.3
-// CHECK:STDOUT:   %.loc9_20.3: init () = converted %.loc9_20.1, %.loc9_20.2
-// CHECK:STDOUT:   %.loc9_38.4: i32 = int_literal 1 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc9_20.2: init () = tuple_init () to %.loc9_38.3 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_20.3: init () = converted %.loc9_20.1, %.loc9_20.2 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_38.4: i32 = int_literal 1 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc9_38.5: ref () = array_index %c.var, %.loc9_38.4
-// CHECK:STDOUT:   %.loc9_24.2: init () = tuple_init () to %.loc9_38.5
-// CHECK:STDOUT:   %.loc9_24.3: init () = converted %.loc9_24.1, %.loc9_24.2
-// CHECK:STDOUT:   %.loc9_38.6: i32 = int_literal 2 [template = constants.%.18]
+// CHECK:STDOUT:   %.loc9_24.2: init () = tuple_init () to %.loc9_38.5 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_24.3: init () = converted %.loc9_24.1, %.loc9_24.2 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_38.6: i32 = int_literal 2 [template = constants.%.21]
 // CHECK:STDOUT:   %.loc9_38.7: ref () = array_index %c.var, %.loc9_38.6
-// CHECK:STDOUT:   %.loc9_28.2: init () = tuple_init () to %.loc9_38.7
-// CHECK:STDOUT:   %.loc9_28.3: init () = converted %.loc9_28.1, %.loc9_28.2
-// CHECK:STDOUT:   %.loc9_38.8: i32 = int_literal 3 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_28.2: init () = tuple_init () to %.loc9_38.7 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_28.3: init () = converted %.loc9_28.1, %.loc9_28.2 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_38.8: i32 = int_literal 3 [template = constants.%.22]
 // CHECK:STDOUT:   %.loc9_38.9: ref () = array_index %c.var, %.loc9_38.8
-// CHECK:STDOUT:   %.loc9_32.2: init () = tuple_init () to %.loc9_38.9
-// CHECK:STDOUT:   %.loc9_32.3: init () = converted %.loc9_32.1, %.loc9_32.2
-// CHECK:STDOUT:   %.loc9_38.10: i32 = int_literal 4 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_32.2: init () = tuple_init () to %.loc9_38.9 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_32.3: init () = converted %.loc9_32.1, %.loc9_32.2 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_38.10: i32 = int_literal 4 [template = constants.%.23]
 // CHECK:STDOUT:   %.loc9_38.11: ref () = array_index %c.var, %.loc9_38.10
-// CHECK:STDOUT:   %.loc9_36.2: init () = tuple_init () to %.loc9_38.11
-// CHECK:STDOUT:   %.loc9_36.3: init () = converted %.loc9_36.1, %.loc9_36.2
-// CHECK:STDOUT:   %.loc9_38.12: init [(); 5] = array_init (%.loc9_20.3, %.loc9_24.3, %.loc9_28.3, %.loc9_32.3, %.loc9_36.3) to %c.var
-// CHECK:STDOUT:   %.loc9_38.13: init [(); 5] = converted %.loc9_38.1, %.loc9_38.12
+// CHECK:STDOUT:   %.loc9_36.2: init () = tuple_init () to %.loc9_38.11 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_36.3: init () = converted %.loc9_36.1, %.loc9_36.2 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc9_38.12: init [(); 5] = array_init (%.loc9_20.3, %.loc9_24.3, %.loc9_28.3, %.loc9_32.3, %.loc9_36.3) to %c.var [template = constants.%.24]
+// CHECK:STDOUT:   %.loc9_38.13: init [(); 5] = converted %.loc9_38.1, %.loc9_38.12 [template = constants.%.24]
 // CHECK:STDOUT:   assign %c.var, %.loc9_38.13
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/array/fail_type_mismatch.carbon

@@ -60,7 +60,7 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %.loc10_39.1: (i32, String, String) = tuple_literal (%.loc10_20, %.loc10_23, %.loc10_32)
 // CHECK:STDOUT:   %.loc10_39.2: i32 = int_literal 0 [template = constants.%.9]
 // CHECK:STDOUT:   %.loc10_39.3: ref i32 = array_index %a.var, %.loc10_39.2
-// CHECK:STDOUT:   %.loc10_39.4: init i32 = initialize_from %.loc10_20 to %.loc10_39.3
+// CHECK:STDOUT:   %.loc10_39.4: init i32 = initialize_from %.loc10_20 to %.loc10_39.3 [template = constants.%.4]
 // CHECK:STDOUT:   assign %a.var, <error>
 // CHECK:STDOUT:   %.loc12_29.1: (type, type, type) = tuple_literal (i32, String, String)
 // CHECK:STDOUT:   %.loc12_29.2: type = converted %.loc12_29.1, constants.%.8 [template = constants.%.8]

+ 6 - 5
toolchain/check/testdata/array/function_param.carbon

@@ -24,6 +24,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
 // CHECK:STDOUT:   %.8: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.9: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.10: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -53,15 +54,15 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %.loc12_20.2: ref [i32; 3] = temporary_storage
 // CHECK:STDOUT:   %.loc12_20.3: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc12_20.4: ref i32 = array_index %.loc12_20.2, %.loc12_20.3
-// CHECK:STDOUT:   %.loc12_20.5: init i32 = initialize_from %.loc12_13 to %.loc12_20.4
+// CHECK:STDOUT:   %.loc12_20.5: init i32 = initialize_from %.loc12_13 to %.loc12_20.4 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc12_20.6: i32 = int_literal 1 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc12_20.7: ref i32 = array_index %.loc12_20.2, %.loc12_20.6
-// CHECK:STDOUT:   %.loc12_20.8: init i32 = initialize_from %.loc12_16 to %.loc12_20.7
+// CHECK:STDOUT:   %.loc12_20.8: init i32 = initialize_from %.loc12_16 to %.loc12_20.7 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc12_20.9: i32 = int_literal 2 [template = constants.%.9]
 // CHECK:STDOUT:   %.loc12_20.10: ref i32 = array_index %.loc12_20.2, %.loc12_20.9
-// CHECK:STDOUT:   %.loc12_20.11: init i32 = initialize_from %.loc12_19 to %.loc12_20.10
-// CHECK:STDOUT:   %.loc12_20.12: init [i32; 3] = array_init (%.loc12_20.5, %.loc12_20.8, %.loc12_20.11) to %.loc12_20.2
-// CHECK:STDOUT:   %.loc12_20.13: init [i32; 3] = converted %.loc12_20.1, %.loc12_20.12
+// CHECK:STDOUT:   %.loc12_20.11: init i32 = initialize_from %.loc12_19 to %.loc12_20.10 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc12_20.12: init [i32; 3] = array_init (%.loc12_20.5, %.loc12_20.8, %.loc12_20.11) to %.loc12_20.2 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc12_20.13: init [i32; 3] = converted %.loc12_20.1, %.loc12_20.12 [template = constants.%.10]
 // CHECK:STDOUT:   %.loc12_20.14: ref [i32; 3] = temporary %.loc12_20.2, %.loc12_20.13
 // CHECK:STDOUT:   %.loc12_20.15: [i32; 3] = bind_value %.loc12_20.14
 // CHECK:STDOUT:   %.loc12_11.1: init i32 = call %F.ref(%.loc12_20.15, %.loc12_23)

+ 12 - 11
toolchain/check/testdata/array/nine_elements.carbon

@@ -30,6 +30,7 @@ var a: [i32; 9] = (1, 2, 3, 4, 5, 6, 7, 8, 9);
 // CHECK:STDOUT:   %.19: i32 = int_literal 6 [template]
 // CHECK:STDOUT:   %.20: i32 = int_literal 7 [template]
 // CHECK:STDOUT:   %.21: i32 = int_literal 8 [template]
+// CHECK:STDOUT:   %.22: [i32; 9] = tuple_value (%.4, %.5, %.6, %.7, %.8, %.9, %.10, %.11, %.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -50,33 +51,33 @@ var a: [i32; 9] = (1, 2, 3, 4, 5, 6, 7, 8, 9);
 // CHECK:STDOUT:   %.loc7_45.1: (i32, i32, i32, i32, i32, i32, i32, i32, i32) = tuple_literal (%.loc7_20, %.loc7_23, %.loc7_26, %.loc7_29, %.loc7_32, %.loc7_35, %.loc7_38, %.loc7_41, %.loc7_44)
 // CHECK:STDOUT:   %.loc7_45.2: i32 = int_literal 0 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc7_45.3: ref i32 = array_index %a.var, %.loc7_45.2
-// CHECK:STDOUT:   %.loc7_45.4: init i32 = initialize_from %.loc7_20 to %.loc7_45.3
+// CHECK:STDOUT:   %.loc7_45.4: init i32 = initialize_from %.loc7_20 to %.loc7_45.3 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_45.5: i32 = int_literal 1 [template = constants.%.14]
 // CHECK:STDOUT:   %.loc7_45.6: ref i32 = array_index %a.var, %.loc7_45.5
-// CHECK:STDOUT:   %.loc7_45.7: init i32 = initialize_from %.loc7_23 to %.loc7_45.6
+// CHECK:STDOUT:   %.loc7_45.7: init i32 = initialize_from %.loc7_23 to %.loc7_45.6 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_45.8: i32 = int_literal 2 [template = constants.%.15]
 // CHECK:STDOUT:   %.loc7_45.9: ref i32 = array_index %a.var, %.loc7_45.8
-// CHECK:STDOUT:   %.loc7_45.10: init i32 = initialize_from %.loc7_26 to %.loc7_45.9
+// CHECK:STDOUT:   %.loc7_45.10: init i32 = initialize_from %.loc7_26 to %.loc7_45.9 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc7_45.11: i32 = int_literal 3 [template = constants.%.16]
 // CHECK:STDOUT:   %.loc7_45.12: ref i32 = array_index %a.var, %.loc7_45.11
-// CHECK:STDOUT:   %.loc7_45.13: init i32 = initialize_from %.loc7_29 to %.loc7_45.12
+// CHECK:STDOUT:   %.loc7_45.13: init i32 = initialize_from %.loc7_29 to %.loc7_45.12 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc7_45.14: i32 = int_literal 4 [template = constants.%.17]
 // CHECK:STDOUT:   %.loc7_45.15: ref i32 = array_index %a.var, %.loc7_45.14
-// CHECK:STDOUT:   %.loc7_45.16: init i32 = initialize_from %.loc7_32 to %.loc7_45.15
+// CHECK:STDOUT:   %.loc7_45.16: init i32 = initialize_from %.loc7_32 to %.loc7_45.15 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc7_45.17: i32 = int_literal 5 [template = constants.%.18]
 // CHECK:STDOUT:   %.loc7_45.18: ref i32 = array_index %a.var, %.loc7_45.17
-// CHECK:STDOUT:   %.loc7_45.19: init i32 = initialize_from %.loc7_35 to %.loc7_45.18
+// CHECK:STDOUT:   %.loc7_45.19: init i32 = initialize_from %.loc7_35 to %.loc7_45.18 [template = constants.%.9]
 // CHECK:STDOUT:   %.loc7_45.20: i32 = int_literal 6 [template = constants.%.19]
 // CHECK:STDOUT:   %.loc7_45.21: ref i32 = array_index %a.var, %.loc7_45.20
-// CHECK:STDOUT:   %.loc7_45.22: init i32 = initialize_from %.loc7_38 to %.loc7_45.21
+// CHECK:STDOUT:   %.loc7_45.22: init i32 = initialize_from %.loc7_38 to %.loc7_45.21 [template = constants.%.10]
 // CHECK:STDOUT:   %.loc7_45.23: i32 = int_literal 7 [template = constants.%.20]
 // CHECK:STDOUT:   %.loc7_45.24: ref i32 = array_index %a.var, %.loc7_45.23
-// CHECK:STDOUT:   %.loc7_45.25: init i32 = initialize_from %.loc7_41 to %.loc7_45.24
+// CHECK:STDOUT:   %.loc7_45.25: init i32 = initialize_from %.loc7_41 to %.loc7_45.24 [template = constants.%.11]
 // CHECK:STDOUT:   %.loc7_45.26: i32 = int_literal 8 [template = constants.%.21]
 // CHECK:STDOUT:   %.loc7_45.27: ref i32 = array_index %a.var, %.loc7_45.26
-// CHECK:STDOUT:   %.loc7_45.28: init i32 = initialize_from %.loc7_44 to %.loc7_45.27
-// CHECK:STDOUT:   %.loc7_45.29: init [i32; 9] = array_init (%.loc7_45.4, %.loc7_45.7, %.loc7_45.10, %.loc7_45.13, %.loc7_45.16, %.loc7_45.19, %.loc7_45.22, %.loc7_45.25, %.loc7_45.28) to %a.var
-// CHECK:STDOUT:   %.loc7_45.30: init [i32; 9] = converted %.loc7_45.1, %.loc7_45.29
+// CHECK:STDOUT:   %.loc7_45.28: init i32 = initialize_from %.loc7_44 to %.loc7_45.27 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc7_45.29: init [i32; 9] = array_init (%.loc7_45.4, %.loc7_45.7, %.loc7_45.10, %.loc7_45.13, %.loc7_45.16, %.loc7_45.19, %.loc7_45.22, %.loc7_45.25, %.loc7_45.28) to %a.var [template = constants.%.22]
+// CHECK:STDOUT:   %.loc7_45.30: init [i32; 9] = converted %.loc7_45.1, %.loc7_45.29 [template = constants.%.22]
 // CHECK:STDOUT:   assign %a.var, %.loc7_45.30
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 42 - 40
toolchain/check/testdata/basics/numeric_literals.carbon

@@ -40,19 +40,21 @@ fn F() {
 // CHECK:STDOUT:   %.10: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.11: i32 = int_literal 3 [template]
 // CHECK:STDOUT:   %.12: i32 = int_literal 4 [template]
-// CHECK:STDOUT:   %.13: i32 = int_literal 7 [template]
-// CHECK:STDOUT:   %.14: type = array_type %.13, f64 [template]
-// CHECK:STDOUT:   %.15: type = ptr_type [f64; 7] [template]
-// CHECK:STDOUT:   %.16: f64 = real_literal 9e-1 [template]
-// CHECK:STDOUT:   %.17: f64 = real_literal 80e-1 [template]
-// CHECK:STDOUT:   %.18: f64 = real_literal 800e-1 [template]
-// CHECK:STDOUT:   %.19: f64 = real_literal 10e6 [template]
-// CHECK:STDOUT:   %.20: f64 = real_literal 10e7 [template]
-// CHECK:STDOUT:   %.21: f64 = real_literal 10e-9 [template]
-// CHECK:STDOUT:   %.22: f64 = real_literal 399999999999999999930e39999999999999999992 [template]
-// CHECK:STDOUT:   %.23: type = tuple_type (f64, f64, f64, f64, f64, f64, f64) [template]
-// CHECK:STDOUT:   %.24: i32 = int_literal 5 [template]
-// CHECK:STDOUT:   %.25: i32 = int_literal 6 [template]
+// CHECK:STDOUT:   %.13: [i32; 5] = tuple_value (%.4, %.5, %.4, %.4, %.6) [template]
+// CHECK:STDOUT:   %.14: i32 = int_literal 7 [template]
+// CHECK:STDOUT:   %.15: type = array_type %.14, f64 [template]
+// CHECK:STDOUT:   %.16: type = ptr_type [f64; 7] [template]
+// CHECK:STDOUT:   %.17: f64 = real_literal 9e-1 [template]
+// CHECK:STDOUT:   %.18: f64 = real_literal 80e-1 [template]
+// CHECK:STDOUT:   %.19: f64 = real_literal 800e-1 [template]
+// CHECK:STDOUT:   %.20: f64 = real_literal 10e6 [template]
+// CHECK:STDOUT:   %.21: f64 = real_literal 10e7 [template]
+// CHECK:STDOUT:   %.22: f64 = real_literal 10e-9 [template]
+// CHECK:STDOUT:   %.23: f64 = real_literal 399999999999999999930e39999999999999999992 [template]
+// CHECK:STDOUT:   %.24: type = tuple_type (f64, f64, f64, f64, f64, f64, f64) [template]
+// CHECK:STDOUT:   %.25: i32 = int_literal 5 [template]
+// CHECK:STDOUT:   %.26: i32 = int_literal 6 [template]
+// CHECK:STDOUT:   %.27: [f64; 7] = tuple_value (%.17, %.18, %.19, %.20, %.21, %.22, %.23) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -74,57 +76,57 @@ fn F() {
 // CHECK:STDOUT:   %.loc16_3.1: (i32, i32, i32, i32, i32) = tuple_literal (%.loc11, %.loc12, %.loc13, %.loc14, %.loc15)
 // CHECK:STDOUT:   %.loc16_3.2: i32 = int_literal 0 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc16_3.3: ref i32 = array_index %ints.var, %.loc16_3.2
-// CHECK:STDOUT:   %.loc16_3.4: init i32 = initialize_from %.loc11 to %.loc16_3.3
+// CHECK:STDOUT:   %.loc16_3.4: init i32 = initialize_from %.loc11 to %.loc16_3.3 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc16_3.5: i32 = int_literal 1 [template = constants.%.9]
 // CHECK:STDOUT:   %.loc16_3.6: ref i32 = array_index %ints.var, %.loc16_3.5
-// CHECK:STDOUT:   %.loc16_3.7: init i32 = initialize_from %.loc12 to %.loc16_3.6
+// CHECK:STDOUT:   %.loc16_3.7: init i32 = initialize_from %.loc12 to %.loc16_3.6 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc16_3.8: i32 = int_literal 2 [template = constants.%.10]
 // CHECK:STDOUT:   %.loc16_3.9: ref i32 = array_index %ints.var, %.loc16_3.8
-// CHECK:STDOUT:   %.loc16_3.10: init i32 = initialize_from %.loc13 to %.loc16_3.9
+// CHECK:STDOUT:   %.loc16_3.10: init i32 = initialize_from %.loc13 to %.loc16_3.9 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc16_3.11: i32 = int_literal 3 [template = constants.%.11]
 // CHECK:STDOUT:   %.loc16_3.12: ref i32 = array_index %ints.var, %.loc16_3.11
-// CHECK:STDOUT:   %.loc16_3.13: init i32 = initialize_from %.loc14 to %.loc16_3.12
+// CHECK:STDOUT:   %.loc16_3.13: init i32 = initialize_from %.loc14 to %.loc16_3.12 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc16_3.14: i32 = int_literal 4 [template = constants.%.12]
 // CHECK:STDOUT:   %.loc16_3.15: ref i32 = array_index %ints.var, %.loc16_3.14
-// CHECK:STDOUT:   %.loc16_3.16: init i32 = initialize_from %.loc15 to %.loc16_3.15
-// CHECK:STDOUT:   %.loc16_3.17: init [i32; 5] = array_init (%.loc16_3.4, %.loc16_3.7, %.loc16_3.10, %.loc16_3.13, %.loc16_3.16) to %ints.var
-// CHECK:STDOUT:   %.loc16_3.18: init [i32; 5] = converted %.loc16_3.1, %.loc16_3.17
+// CHECK:STDOUT:   %.loc16_3.16: init i32 = initialize_from %.loc15 to %.loc16_3.15 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc16_3.17: init [i32; 5] = array_init (%.loc16_3.4, %.loc16_3.7, %.loc16_3.10, %.loc16_3.13, %.loc16_3.16) to %ints.var [template = constants.%.13]
+// CHECK:STDOUT:   %.loc16_3.18: init [i32; 5] = converted %.loc16_3.1, %.loc16_3.17 [template = constants.%.13]
 // CHECK:STDOUT:   assign %ints.var, %.loc16_3.18
-// CHECK:STDOUT:   %.loc17_21: i32 = int_literal 7 [template = constants.%.13]
-// CHECK:STDOUT:   %.loc17_22: type = array_type %.loc17_21, f64 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc17_21: i32 = int_literal 7 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc17_22: type = array_type %.loc17_21, f64 [template = constants.%.15]
 // CHECK:STDOUT:   %floats.var: ref [f64; 7] = var floats
 // CHECK:STDOUT:   %floats: ref [f64; 7] = bind_name floats, %floats.var
-// CHECK:STDOUT:   %.loc18: f64 = real_literal 9e-1 [template = constants.%.16]
-// CHECK:STDOUT:   %.loc19: f64 = real_literal 80e-1 [template = constants.%.17]
-// CHECK:STDOUT:   %.loc20: f64 = real_literal 800e-1 [template = constants.%.18]
-// CHECK:STDOUT:   %.loc21: f64 = real_literal 10e6 [template = constants.%.19]
-// CHECK:STDOUT:   %.loc22: f64 = real_literal 10e7 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc23: f64 = real_literal 10e-9 [template = constants.%.21]
-// CHECK:STDOUT:   %.loc24: f64 = real_literal 399999999999999999930e39999999999999999992 [template = constants.%.22]
+// CHECK:STDOUT:   %.loc18: f64 = real_literal 9e-1 [template = constants.%.17]
+// CHECK:STDOUT:   %.loc19: f64 = real_literal 80e-1 [template = constants.%.18]
+// CHECK:STDOUT:   %.loc20: f64 = real_literal 800e-1 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc21: f64 = real_literal 10e6 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc22: f64 = real_literal 10e7 [template = constants.%.21]
+// CHECK:STDOUT:   %.loc23: f64 = real_literal 10e-9 [template = constants.%.22]
+// CHECK:STDOUT:   %.loc24: f64 = real_literal 399999999999999999930e39999999999999999992 [template = constants.%.23]
 // CHECK:STDOUT:   %.loc25_3.1: (f64, f64, f64, f64, f64, f64, f64) = tuple_literal (%.loc18, %.loc19, %.loc20, %.loc21, %.loc22, %.loc23, %.loc24)
 // CHECK:STDOUT:   %.loc25_3.2: i32 = int_literal 0 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc25_3.3: ref f64 = array_index %floats.var, %.loc25_3.2
-// CHECK:STDOUT:   %.loc25_3.4: init f64 = initialize_from %.loc18 to %.loc25_3.3
+// CHECK:STDOUT:   %.loc25_3.4: init f64 = initialize_from %.loc18 to %.loc25_3.3 [template = constants.%.17]
 // CHECK:STDOUT:   %.loc25_3.5: i32 = int_literal 1 [template = constants.%.9]
 // CHECK:STDOUT:   %.loc25_3.6: ref f64 = array_index %floats.var, %.loc25_3.5
-// CHECK:STDOUT:   %.loc25_3.7: init f64 = initialize_from %.loc19 to %.loc25_3.6
+// CHECK:STDOUT:   %.loc25_3.7: init f64 = initialize_from %.loc19 to %.loc25_3.6 [template = constants.%.18]
 // CHECK:STDOUT:   %.loc25_3.8: i32 = int_literal 2 [template = constants.%.10]
 // CHECK:STDOUT:   %.loc25_3.9: ref f64 = array_index %floats.var, %.loc25_3.8
-// CHECK:STDOUT:   %.loc25_3.10: init f64 = initialize_from %.loc20 to %.loc25_3.9
+// CHECK:STDOUT:   %.loc25_3.10: init f64 = initialize_from %.loc20 to %.loc25_3.9 [template = constants.%.19]
 // CHECK:STDOUT:   %.loc25_3.11: i32 = int_literal 3 [template = constants.%.11]
 // CHECK:STDOUT:   %.loc25_3.12: ref f64 = array_index %floats.var, %.loc25_3.11
-// CHECK:STDOUT:   %.loc25_3.13: init f64 = initialize_from %.loc21 to %.loc25_3.12
+// CHECK:STDOUT:   %.loc25_3.13: init f64 = initialize_from %.loc21 to %.loc25_3.12 [template = constants.%.20]
 // CHECK:STDOUT:   %.loc25_3.14: i32 = int_literal 4 [template = constants.%.12]
 // CHECK:STDOUT:   %.loc25_3.15: ref f64 = array_index %floats.var, %.loc25_3.14
-// CHECK:STDOUT:   %.loc25_3.16: init f64 = initialize_from %.loc22 to %.loc25_3.15
-// CHECK:STDOUT:   %.loc25_3.17: i32 = int_literal 5 [template = constants.%.24]
+// CHECK:STDOUT:   %.loc25_3.16: init f64 = initialize_from %.loc22 to %.loc25_3.15 [template = constants.%.21]
+// CHECK:STDOUT:   %.loc25_3.17: i32 = int_literal 5 [template = constants.%.25]
 // CHECK:STDOUT:   %.loc25_3.18: ref f64 = array_index %floats.var, %.loc25_3.17
-// CHECK:STDOUT:   %.loc25_3.19: init f64 = initialize_from %.loc23 to %.loc25_3.18
-// CHECK:STDOUT:   %.loc25_3.20: i32 = int_literal 6 [template = constants.%.25]
+// CHECK:STDOUT:   %.loc25_3.19: init f64 = initialize_from %.loc23 to %.loc25_3.18 [template = constants.%.22]
+// CHECK:STDOUT:   %.loc25_3.20: i32 = int_literal 6 [template = constants.%.26]
 // CHECK:STDOUT:   %.loc25_3.21: ref f64 = array_index %floats.var, %.loc25_3.20
-// CHECK:STDOUT:   %.loc25_3.22: init f64 = initialize_from %.loc24 to %.loc25_3.21
-// CHECK:STDOUT:   %.loc25_3.23: init [f64; 7] = array_init (%.loc25_3.4, %.loc25_3.7, %.loc25_3.10, %.loc25_3.13, %.loc25_3.16, %.loc25_3.19, %.loc25_3.22) to %floats.var
-// CHECK:STDOUT:   %.loc25_3.24: init [f64; 7] = converted %.loc25_3.1, %.loc25_3.23
+// CHECK:STDOUT:   %.loc25_3.22: init f64 = initialize_from %.loc24 to %.loc25_3.21 [template = constants.%.23]
+// CHECK:STDOUT:   %.loc25_3.23: init [f64; 7] = array_init (%.loc25_3.4, %.loc25_3.7, %.loc25_3.10, %.loc25_3.13, %.loc25_3.16, %.loc25_3.19, %.loc25_3.22) to %floats.var [template = constants.%.27]
+// CHECK:STDOUT:   %.loc25_3.24: init [f64; 7] = converted %.loc25_3.1, %.loc25_3.23 [template = constants.%.27]
 // CHECK:STDOUT:   assign %floats.var, %.loc25_3.24
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 4 - 2
toolchain/check/testdata/basics/raw_and_textual_ir.carbon

@@ -81,6 +81,8 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:     inst+12:         template inst+12
 // CHECK:STDOUT:     inst+13:         template inst+14
 // CHECK:STDOUT:     inst+14:         template inst+14
+// CHECK:STDOUT:     inst+19:         template inst+12
+// CHECK:STDOUT:     inst+21:         template inst+14
 // CHECK:STDOUT:   inst_blocks:
 // CHECK:STDOUT:     empty:           {}
 // CHECK:STDOUT:     exports:
@@ -148,9 +150,9 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:   %.loc12_20.2: ref i32 = tuple_access %return, element0
 // CHECK:STDOUT:   %.loc12_20.3: init i32 = initialize_from %n.ref to %.loc12_20.2
 // CHECK:STDOUT:   %.loc12_20.4: ref i32 = tuple_access %return, element1
-// CHECK:STDOUT:   %.loc12_20.5: init i32 = initialize_from %.loc12_14 to %.loc12_20.4
+// CHECK:STDOUT:   %.loc12_20.5: init i32 = initialize_from %.loc12_14 to %.loc12_20.4 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc12_20.6: ref f64 = tuple_access %return, element2
-// CHECK:STDOUT:   %.loc12_20.7: init f64 = initialize_from %.loc12_17 to %.loc12_20.6
+// CHECK:STDOUT:   %.loc12_20.7: init f64 = initialize_from %.loc12_17 to %.loc12_20.6 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc12_20.8: init (i32, i32, f64) = tuple_init (%.loc12_20.3, %.loc12_20.5, %.loc12_20.7) to %return
 // CHECK:STDOUT:   %.loc12_20.9: init (i32, i32, f64) = converted %.loc12_20.1, %.loc12_20.8
 // CHECK:STDOUT:   return %.loc12_20.9

+ 2 - 0
toolchain/check/testdata/basics/raw_ir.carbon

@@ -81,6 +81,8 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:     inst+12:         template inst+12
 // CHECK:STDOUT:     inst+13:         template inst+14
 // CHECK:STDOUT:     inst+14:         template inst+14
+// CHECK:STDOUT:     inst+19:         template inst+12
+// CHECK:STDOUT:     inst+21:         template inst+14
 // CHECK:STDOUT:   inst_blocks:
 // CHECK:STDOUT:     empty:           {}
 // CHECK:STDOUT:     exports:

+ 2 - 2
toolchain/check/testdata/basics/textual_ir.carbon

@@ -36,9 +36,9 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:   %.loc12_20.2: ref i32 = tuple_access %return, element0
 // CHECK:STDOUT:   %.loc12_20.3: init i32 = initialize_from %n.ref to %.loc12_20.2
 // CHECK:STDOUT:   %.loc12_20.4: ref i32 = tuple_access %return, element1
-// CHECK:STDOUT:   %.loc12_20.5: init i32 = initialize_from %.loc12_14 to %.loc12_20.4
+// CHECK:STDOUT:   %.loc12_20.5: init i32 = initialize_from %.loc12_14 to %.loc12_20.4 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc12_20.6: ref f64 = tuple_access %return, element2
-// CHECK:STDOUT:   %.loc12_20.7: init f64 = initialize_from %.loc12_17 to %.loc12_20.6
+// CHECK:STDOUT:   %.loc12_20.7: init f64 = initialize_from %.loc12_17 to %.loc12_20.6 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc12_20.8: init (i32, i32, f64) = tuple_init (%.loc12_20.3, %.loc12_20.5, %.loc12_20.7) to %return
 // CHECK:STDOUT:   %.loc12_20.9: init (i32, i32, f64) = converted %.loc12_20.1, %.loc12_20.8
 // CHECK:STDOUT:   return %.loc12_20.9

+ 11 - 9
toolchain/check/testdata/class/base.carbon

@@ -39,9 +39,11 @@ fn Access(d: Derived) -> (i32, i32) {
 // CHECK:STDOUT:   %.10: i32 = int_literal 4 [template]
 // CHECK:STDOUT:   %.11: i32 = int_literal 7 [template]
 // CHECK:STDOUT:   %.12: type = struct_type {.base: {.b: i32}, .d: i32} [template]
-// CHECK:STDOUT:   %.13: type = tuple_type (type, type) [template]
-// CHECK:STDOUT:   %.14: type = tuple_type (i32, i32) [template]
-// CHECK:STDOUT:   %.15: type = ptr_type (i32, i32) [template]
+// CHECK:STDOUT:   %.13: Base = struct_value (%.10) [template]
+// CHECK:STDOUT:   %.14: Derived = struct_value (%.13, %.11) [template]
+// CHECK:STDOUT:   %.15: type = tuple_type (type, type) [template]
+// CHECK:STDOUT:   %.16: type = tuple_type (i32, i32) [template]
+// CHECK:STDOUT:   %.17: type = ptr_type (i32, i32) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -80,13 +82,13 @@ fn Access(d: Derived) -> (i32, i32) {
 // CHECK:STDOUT:   %.loc18_35.1: {.base: {.b: i32}, .d: i32} = struct_literal (%.loc18_26.1, %.loc18_34)
 // CHECK:STDOUT:   %.loc18_35.2: ref Base = class_element_access %return, element0
 // CHECK:STDOUT:   %.loc18_26.2: ref i32 = class_element_access %.loc18_35.2, element0
-// CHECK:STDOUT:   %.loc18_26.3: init i32 = initialize_from %.loc18_25 to %.loc18_26.2
-// CHECK:STDOUT:   %.loc18_26.4: init Base = class_init (%.loc18_26.3), %.loc18_35.2
-// CHECK:STDOUT:   %.loc18_26.5: init Base = converted %.loc18_26.1, %.loc18_26.4
+// CHECK:STDOUT:   %.loc18_26.3: init i32 = initialize_from %.loc18_25 to %.loc18_26.2 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc18_26.4: init Base = class_init (%.loc18_26.3), %.loc18_35.2 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc18_26.5: init Base = converted %.loc18_26.1, %.loc18_26.4 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc18_35.3: ref i32 = class_element_access %return, element1
-// CHECK:STDOUT:   %.loc18_35.4: init i32 = initialize_from %.loc18_34 to %.loc18_35.3
-// CHECK:STDOUT:   %.loc18_35.5: init Derived = class_init (%.loc18_26.5, %.loc18_35.4), %return
-// CHECK:STDOUT:   %.loc18_35.6: init Derived = converted %.loc18_35.1, %.loc18_35.5
+// CHECK:STDOUT:   %.loc18_35.4: init i32 = initialize_from %.loc18_34 to %.loc18_35.3 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc18_35.5: init Derived = class_init (%.loc18_26.5, %.loc18_35.4), %return [template = constants.%.14]
+// CHECK:STDOUT:   %.loc18_35.6: init Derived = converted %.loc18_35.1, %.loc18_35.5 [template = constants.%.14]
 // CHECK:STDOUT:   return %.loc18_35.6
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 11 - 8
toolchain/check/testdata/class/derived_to_base.carbon

@@ -63,6 +63,9 @@ fn ConvertInit() {
 // CHECK:STDOUT:   %.21: type = struct_type {.base: {.a: i32}, .b: i32} [template]
 // CHECK:STDOUT:   %.22: i32 = int_literal 3 [template]
 // CHECK:STDOUT:   %.23: type = struct_type {.base: {.base: {.a: i32}, .b: i32}, .c: i32} [template]
+// CHECK:STDOUT:   %.24: A = struct_value (%.19) [template]
+// CHECK:STDOUT:   %.25: B = struct_value (%.24, %.20) [template]
+// CHECK:STDOUT:   %.26: C = struct_value (%.25, %.22) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -179,16 +182,16 @@ fn ConvertInit() {
 // CHECK:STDOUT:   %.loc34_57.3: ref B = class_element_access %.loc34_57.2, element0
 // CHECK:STDOUT:   %.loc34_48.2: ref A = class_element_access %.loc34_57.3, element0
 // CHECK:STDOUT:   %.loc34_39.2: ref i32 = class_element_access %.loc34_48.2, element0
-// CHECK:STDOUT:   %.loc34_39.3: init i32 = initialize_from %.loc34_38 to %.loc34_39.2
-// CHECK:STDOUT:   %.loc34_39.4: init A = class_init (%.loc34_39.3), %.loc34_48.2
-// CHECK:STDOUT:   %.loc34_39.5: init A = converted %.loc34_39.1, %.loc34_39.4
+// CHECK:STDOUT:   %.loc34_39.3: init i32 = initialize_from %.loc34_38 to %.loc34_39.2 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc34_39.4: init A = class_init (%.loc34_39.3), %.loc34_48.2 [template = constants.%.24]
+// CHECK:STDOUT:   %.loc34_39.5: init A = converted %.loc34_39.1, %.loc34_39.4 [template = constants.%.24]
 // CHECK:STDOUT:   %.loc34_48.3: ref i32 = class_element_access %.loc34_57.3, element1
-// CHECK:STDOUT:   %.loc34_48.4: init i32 = initialize_from %.loc34_47 to %.loc34_48.3
-// CHECK:STDOUT:   %.loc34_48.5: init B = class_init (%.loc34_39.5, %.loc34_48.4), %.loc34_57.3
-// CHECK:STDOUT:   %.loc34_48.6: init B = converted %.loc34_48.1, %.loc34_48.5
+// CHECK:STDOUT:   %.loc34_48.4: init i32 = initialize_from %.loc34_47 to %.loc34_48.3 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc34_48.5: init B = class_init (%.loc34_39.5, %.loc34_48.4), %.loc34_57.3 [template = constants.%.25]
+// CHECK:STDOUT:   %.loc34_48.6: init B = converted %.loc34_48.1, %.loc34_48.5 [template = constants.%.25]
 // CHECK:STDOUT:   %.loc34_57.4: ref i32 = class_element_access %.loc34_57.2, element1
-// CHECK:STDOUT:   %.loc34_57.5: init i32 = initialize_from %.loc34_56 to %.loc34_57.4
-// CHECK:STDOUT:   %.loc34_57.6: init C = class_init (%.loc34_48.6, %.loc34_57.5), %.loc34_57.2
+// CHECK:STDOUT:   %.loc34_57.5: init i32 = initialize_from %.loc34_56 to %.loc34_57.4 [template = constants.%.22]
+// CHECK:STDOUT:   %.loc34_57.6: init C = class_init (%.loc34_48.6, %.loc34_57.5), %.loc34_57.2 [template = constants.%.26]
 // CHECK:STDOUT:   %.loc34_57.7: ref C = temporary %.loc34_57.2, %.loc34_57.6
 // CHECK:STDOUT:   %.loc34_57.8: ref C = converted %.loc34_57.1, %.loc34_57.7
 // CHECK:STDOUT:   %.loc34_63.1: ref B = class_element_access %.loc34_57.8, element0

+ 7 - 7
toolchain/check/testdata/class/fail_init.carbon

@@ -62,25 +62,25 @@ fn F() {
 // CHECK:STDOUT:   %.loc16_10.1: {.a: i32} = struct_literal (%.loc16_9)
 // CHECK:STDOUT:   %Class.ref.loc16: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc16_10.2: ref Class = temporary_storage
-// CHECK:STDOUT:   %.loc16_10.3: ref Class = temporary %.loc16_10.2, <error> [template = <error>]
-// CHECK:STDOUT:   %.loc16_10.4: ref Class = converted %.loc16_10.1, %.loc16_10.3 [template = <error>]
+// CHECK:STDOUT:   %.loc16_10.3: ref Class = temporary %.loc16_10.2, <error>
+// CHECK:STDOUT:   %.loc16_10.4: ref Class = converted %.loc16_10.1, %.loc16_10.3
 // CHECK:STDOUT:   %.loc20_9: i32 = int_literal 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc20_17: i32 = int_literal 2 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc20_18.1: {.a: i32, .c: i32} = struct_literal (%.loc20_9, %.loc20_17)
 // CHECK:STDOUT:   %Class.ref.loc20: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc20_18.2: ref Class = temporary_storage
 // CHECK:STDOUT:   %.loc20_18.3: ref i32 = class_element_access %.loc20_18.2, element0
-// CHECK:STDOUT:   %.loc20_18.4: init i32 = initialize_from %.loc20_9 to %.loc20_18.3
-// CHECK:STDOUT:   %.loc20_18.5: ref Class = temporary %.loc20_18.2, <error> [template = <error>]
-// CHECK:STDOUT:   %.loc20_18.6: ref Class = converted %.loc20_18.1, %.loc20_18.5 [template = <error>]
+// CHECK:STDOUT:   %.loc20_18.4: init i32 = initialize_from %.loc20_9 to %.loc20_18.3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc20_18.5: ref Class = temporary %.loc20_18.2, <error>
+// CHECK:STDOUT:   %.loc20_18.6: ref Class = converted %.loc20_18.1, %.loc20_18.5
 // CHECK:STDOUT:   %.loc24_9: i32 = int_literal 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc24_17: i32 = int_literal 2 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc24_25: i32 = int_literal 3 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc24_26.1: {.a: i32, .b: i32, .c: i32} = struct_literal (%.loc24_9, %.loc24_17, %.loc24_25)
 // CHECK:STDOUT:   %Class.ref.loc24: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc24_26.2: ref Class = temporary_storage
-// CHECK:STDOUT:   %.loc24_26.3: ref Class = temporary %.loc24_26.2, <error> [template = <error>]
-// CHECK:STDOUT:   %.loc24_26.4: ref Class = converted %.loc24_26.1, %.loc24_26.3 [template = <error>]
+// CHECK:STDOUT:   %.loc24_26.3: ref Class = temporary %.loc24_26.2, <error>
+// CHECK:STDOUT:   %.loc24_26.4: ref Class = converted %.loc24_26.1, %.loc24_26.3
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 5 - 4
toolchain/check/testdata/class/fail_init_as_inplace.carbon

@@ -32,7 +32,8 @@ fn F() {
 // CHECK:STDOUT:   %.4: type = ptr_type {.a: i32, .b: i32} [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.7: type = tuple_type () [template]
+// CHECK:STDOUT:   %.7: Class = struct_value (%.5, %.6) [template]
+// CHECK:STDOUT:   %.8: type = tuple_type () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -66,10 +67,10 @@ fn F() {
 // CHECK:STDOUT:   %Class.ref.loc21_38: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc21_33.2: ref Class = temporary_storage
 // CHECK:STDOUT:   %.loc21_33.3: ref i32 = class_element_access %.loc21_33.2, element0
-// CHECK:STDOUT:   %.loc21_33.4: init i32 = initialize_from %.loc21_24 to %.loc21_33.3
+// CHECK:STDOUT:   %.loc21_33.4: init i32 = initialize_from %.loc21_24 to %.loc21_33.3 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc21_33.5: ref i32 = class_element_access %.loc21_33.2, element1
-// CHECK:STDOUT:   %.loc21_33.6: init i32 = initialize_from %.loc21_32 to %.loc21_33.5
-// CHECK:STDOUT:   %.loc21_33.7: init Class = class_init (%.loc21_33.4, %.loc21_33.6), %.loc21_33.2
+// CHECK:STDOUT:   %.loc21_33.6: init i32 = initialize_from %.loc21_32 to %.loc21_33.5 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc21_33.7: init Class = class_init (%.loc21_33.4, %.loc21_33.6), %.loc21_33.2 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc21_33.8: ref Class = temporary %.loc21_33.2, %.loc21_33.7
 // CHECK:STDOUT:   %.loc21_33.9: ref Class = converted %.loc21_33.1, %.loc21_33.8
 // CHECK:STDOUT:   %.loc21_33.10: Class = bind_value %.loc21_33.9

+ 4 - 3
toolchain/check/testdata/class/init_as.carbon

@@ -22,6 +22,7 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %.3: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.5: type = ptr_type {.a: i32, .b: i32} [template]
+// CHECK:STDOUT:   %.6: Class = struct_value (%.3, %.4) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -49,10 +50,10 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc13_26.2: ref Class = temporary_storage
 // CHECK:STDOUT:   %.loc13_26.3: ref i32 = class_element_access %.loc13_26.2, element0
-// CHECK:STDOUT:   %.loc13_26.4: init i32 = initialize_from %.loc13_17 to %.loc13_26.3
+// CHECK:STDOUT:   %.loc13_26.4: init i32 = initialize_from %.loc13_17 to %.loc13_26.3 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc13_26.5: ref i32 = class_element_access %.loc13_26.2, element1
-// CHECK:STDOUT:   %.loc13_26.6: init i32 = initialize_from %.loc13_25 to %.loc13_26.5
-// CHECK:STDOUT:   %.loc13_26.7: init Class = class_init (%.loc13_26.4, %.loc13_26.6), %.loc13_26.2
+// CHECK:STDOUT:   %.loc13_26.6: init i32 = initialize_from %.loc13_25 to %.loc13_26.5 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc13_26.7: init Class = class_init (%.loc13_26.4, %.loc13_26.6), %.loc13_26.2 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc13_26.8: ref Class = temporary %.loc13_26.2, %.loc13_26.7
 // CHECK:STDOUT:   %.loc13_26.9: ref Class = converted %.loc13_26.1, %.loc13_26.8
 // CHECK:STDOUT:   %.loc13_37.1: ref i32 = class_element_access %.loc13_26.9, element0

+ 3 - 2
toolchain/check/testdata/class/method.carbon

@@ -57,6 +57,7 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %.3: type = struct_type {.k: i32} [template]
 // CHECK:STDOUT:   %.4: type = ptr_type {.k: i32} [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.6: Class = struct_value (%.5) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -112,8 +113,8 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc25_18.2: ref Class = temporary_storage
 // CHECK:STDOUT:   %.loc25_18.3: ref i32 = class_element_access %.loc25_18.2, element0
-// CHECK:STDOUT:   %.loc25_18.4: init i32 = initialize_from %.loc25_17 to %.loc25_18.3
-// CHECK:STDOUT:   %.loc25_18.5: init Class = class_init (%.loc25_18.4), %.loc25_18.2
+// CHECK:STDOUT:   %.loc25_18.4: init i32 = initialize_from %.loc25_17 to %.loc25_18.3 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc25_18.5: init Class = class_init (%.loc25_18.4), %.loc25_18.2 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc25_18.6: ref Class = temporary %.loc25_18.2, %.loc25_18.5
 // CHECK:STDOUT:   %.loc25_18.7: ref Class = converted %.loc25_18.1, %.loc25_18.6
 // CHECK:STDOUT:   %.loc25_29: <bound method> = bound_method %.loc25_18.7, @Class.%F

+ 8 - 7
toolchain/check/testdata/function/call/more_param_ir.carbon

@@ -18,9 +18,10 @@ fn Main() {
 // CHECK:STDOUT:   %.1: type = tuple_type (type) [template]
 // CHECK:STDOUT:   %.2: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.3: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.4: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.5: i32 = int_literal 6 [template]
-// CHECK:STDOUT:   %.6: type = tuple_type () [template]
+// CHECK:STDOUT:   %.4: (i32,) = tuple_value (%.3) [template]
+// CHECK:STDOUT:   %.5: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.6: i32 = int_literal 6 [template]
+// CHECK:STDOUT:   %.7: type = tuple_type () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -42,14 +43,14 @@ fn Main() {
 // CHECK:STDOUT:   %x: ref (i32,) = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc10_20: i32 = int_literal 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc10_22.1: (i32,) = tuple_literal (%.loc10_20)
-// CHECK:STDOUT:   %.loc10_22.2: init (i32,) = tuple_init (%.loc10_20) to %x.var
-// CHECK:STDOUT:   %.loc10_22.3: init (i32,) = converted %.loc10_22.1, %.loc10_22.2
+// CHECK:STDOUT:   %.loc10_22.2: init (i32,) = tuple_init (%.loc10_20) to %x.var [template = constants.%.4]
+// CHECK:STDOUT:   %.loc10_22.3: init (i32,) = converted %.loc10_22.1, %.loc10_22.2 [template = constants.%.4]
 // CHECK:STDOUT:   assign %x.var, %.loc10_22.3
 // CHECK:STDOUT:   %Foo.ref: <function> = name_ref Foo, file.%Foo [template = file.%Foo]
 // CHECK:STDOUT:   %x.ref: ref (i32,) = name_ref x, %x
-// CHECK:STDOUT:   %.loc12_9: i32 = int_literal 0 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc12_9: i32 = int_literal 0 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc12_10.1: ref i32 = tuple_index %x.ref, %.loc12_9
-// CHECK:STDOUT:   %.loc12_13: i32 = int_literal 6 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc12_13: i32 = int_literal 6 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc12_10.2: i32 = bind_value %.loc12_10.1
 // CHECK:STDOUT:   %.loc12_6: init () = call %Foo.ref(%.loc12_10.2, %.loc12_13)
 // CHECK:STDOUT:   return

+ 4 - 3
toolchain/check/testdata/if_expr/basic.carbon

@@ -18,6 +18,7 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:   %.4: i32 = int_literal 0 [template]
 // CHECK:STDOUT:   %.5: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.7: [i32; 1] = tuple_value (%.4) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -35,9 +36,9 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:   %.loc8_24.1: (i32,) = tuple_literal (%.loc8_22)
 // CHECK:STDOUT:   %.loc8_24.2: i32 = int_literal 0 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc8_24.3: ref i32 = array_index %x.var, %.loc8_24.2
-// CHECK:STDOUT:   %.loc8_24.4: init i32 = initialize_from %.loc8_22 to %.loc8_24.3
-// CHECK:STDOUT:   %.loc8_24.5: init [i32; 1] = array_init (%.loc8_24.4) to %x.var
-// CHECK:STDOUT:   %.loc8_24.6: init [i32; 1] = converted %.loc8_24.1, %.loc8_24.5
+// CHECK:STDOUT:   %.loc8_24.4: init i32 = initialize_from %.loc8_22 to %.loc8_24.3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc8_24.5: init [i32; 1] = array_init (%.loc8_24.4) to %x.var [template = constants.%.7]
+// CHECK:STDOUT:   %.loc8_24.6: init [i32; 1] = converted %.loc8_24.1, %.loc8_24.5 [template = constants.%.7]
 // CHECK:STDOUT:   assign %x.var, %.loc8_24.6
 // CHECK:STDOUT:   %b.ref: bool = name_ref b, %b
 // CHECK:STDOUT:   if %b.ref br !if.expr.then else br !if.expr.else

+ 6 - 5
toolchain/check/testdata/if_expr/struct.carbon

@@ -18,7 +18,8 @@ fn F(cond: bool) {
 // CHECK:STDOUT:   %.2: type = ptr_type {.a: i32, .b: i32} [template]
 // CHECK:STDOUT:   %.3: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.5: type = tuple_type () [template]
+// CHECK:STDOUT:   %.5: {.a: i32, .b: i32} = struct_value (%.3, %.4) [template]
+// CHECK:STDOUT:   %.6: type = tuple_type () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -38,11 +39,11 @@ fn F(cond: bool) {
 // CHECK:STDOUT:   %.loc10_45: i32 = int_literal 2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc10_46.1: {.a: i32, .b: i32} = struct_literal (%.loc10_37, %.loc10_45)
 // CHECK:STDOUT:   %.loc10_46.2: ref i32 = struct_access %a.var, element0
-// CHECK:STDOUT:   %.loc10_46.3: init i32 = initialize_from %.loc10_37 to %.loc10_46.2
+// CHECK:STDOUT:   %.loc10_46.3: init i32 = initialize_from %.loc10_37 to %.loc10_46.2 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc10_46.4: ref i32 = struct_access %a.var, element1
-// CHECK:STDOUT:   %.loc10_46.5: init i32 = initialize_from %.loc10_45 to %.loc10_46.4
-// CHECK:STDOUT:   %.loc10_46.6: init {.a: i32, .b: i32} = struct_init (%.loc10_46.3, %.loc10_46.5) to %a.var
-// CHECK:STDOUT:   %.loc10_46.7: init {.a: i32, .b: i32} = converted %.loc10_46.1, %.loc10_46.6
+// CHECK:STDOUT:   %.loc10_46.5: init i32 = initialize_from %.loc10_45 to %.loc10_46.4 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc10_46.6: init {.a: i32, .b: i32} = struct_init (%.loc10_46.3, %.loc10_46.5) to %a.var [template = constants.%.5]
+// CHECK:STDOUT:   %.loc10_46.7: init {.a: i32, .b: i32} = converted %.loc10_46.1, %.loc10_46.6 [template = constants.%.5]
 // CHECK:STDOUT:   assign %a.var, %.loc10_46.7
 // CHECK:STDOUT:   %G.ref: <function> = name_ref G, file.%G [template = file.%G]
 // CHECK:STDOUT:   %cond.ref: bool = name_ref cond, %cond

+ 9 - 8
toolchain/check/testdata/index/array_element_access.carbon

@@ -20,8 +20,9 @@ var d: i32 = a[b];
 // CHECK:STDOUT:   %.6: type = tuple_type (i32, i32) [template]
 // CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
 // CHECK:STDOUT:   %.8: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.9: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.10: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.9: [i32; 2] = tuple_value (%.4, %.5) [template]
+// CHECK:STDOUT:   %.10: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.11: i32 = int_literal 0 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -35,21 +36,21 @@ var d: i32 = a[b];
 // CHECK:STDOUT:   %.loc7_26.1: (i32, i32) = tuple_literal (%.loc7_20, %.loc7_24)
 // CHECK:STDOUT:   %.loc7_26.2: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc7_26.3: ref i32 = array_index %a.var, %.loc7_26.2
-// CHECK:STDOUT:   %.loc7_26.4: init i32 = initialize_from %.loc7_20 to %.loc7_26.3
+// CHECK:STDOUT:   %.loc7_26.4: init i32 = initialize_from %.loc7_20 to %.loc7_26.3 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_26.5: i32 = int_literal 1 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc7_26.6: ref i32 = array_index %a.var, %.loc7_26.5
-// CHECK:STDOUT:   %.loc7_26.7: init i32 = initialize_from %.loc7_24 to %.loc7_26.6
-// CHECK:STDOUT:   %.loc7_26.8: init [i32; 2] = array_init (%.loc7_26.4, %.loc7_26.7) to %a.var
-// CHECK:STDOUT:   %.loc7_26.9: init [i32; 2] = converted %.loc7_26.1, %.loc7_26.8
+// CHECK:STDOUT:   %.loc7_26.7: init i32 = initialize_from %.loc7_24 to %.loc7_26.6 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc7_26.8: init [i32; 2] = array_init (%.loc7_26.4, %.loc7_26.7) to %a.var [template = constants.%.9]
+// CHECK:STDOUT:   %.loc7_26.9: init [i32; 2] = converted %.loc7_26.1, %.loc7_26.8 [template = constants.%.9]
 // CHECK:STDOUT:   assign %a.var, %.loc7_26.9
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
-// CHECK:STDOUT:   %.loc8: i32 = int_literal 1 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc8: i32 = int_literal 1 [template = constants.%.10]
 // CHECK:STDOUT:   assign %b.var, %.loc8
 // CHECK:STDOUT:   %c.var: ref i32 = var c
 // CHECK:STDOUT:   %c: ref i32 = bind_name c, %c.var
 // CHECK:STDOUT:   %a.ref.loc9: ref [i32; 2] = name_ref a, %a
-// CHECK:STDOUT:   %.loc9_16: i32 = int_literal 0 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc9_16: i32 = int_literal 0 [template = constants.%.11]
 // CHECK:STDOUT:   %.loc9_17.1: ref i32 = array_index %a.ref.loc9, %.loc9_16
 // CHECK:STDOUT:   %.loc9_17.2: i32 = bind_value %.loc9_17.1
 // CHECK:STDOUT:   assign %c.var, %.loc9_17.2

+ 21 - 20
toolchain/check/testdata/index/expr_category.carbon

@@ -36,9 +36,10 @@ fn ValueBinding(b: [i32; 3]) {
 // CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
 // CHECK:STDOUT:   %.8: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.9: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.10: type = ptr_type i32 [template]
-// CHECK:STDOUT:   %.11: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.12: i32 = int_literal 4 [template]
+// CHECK:STDOUT:   %.10: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %.11: type = ptr_type i32 [template]
+// CHECK:STDOUT:   %.12: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.13: i32 = int_literal 4 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -62,28 +63,28 @@ fn ValueBinding(b: [i32; 3]) {
 // CHECK:STDOUT:   %.loc10_29.1: (i32, i32, i32) = tuple_literal (%.loc10_22, %.loc10_25, %.loc10_28)
 // CHECK:STDOUT:   %.loc10_29.2: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc10_29.3: ref i32 = array_index %a.var, %.loc10_29.2
-// CHECK:STDOUT:   %.loc10_29.4: init i32 = initialize_from %.loc10_22 to %.loc10_29.3
+// CHECK:STDOUT:   %.loc10_29.4: init i32 = initialize_from %.loc10_22 to %.loc10_29.3 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc10_29.5: i32 = int_literal 1 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc10_29.6: ref i32 = array_index %a.var, %.loc10_29.5
-// CHECK:STDOUT:   %.loc10_29.7: init i32 = initialize_from %.loc10_25 to %.loc10_29.6
+// CHECK:STDOUT:   %.loc10_29.7: init i32 = initialize_from %.loc10_25 to %.loc10_29.6 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc10_29.8: i32 = int_literal 2 [template = constants.%.9]
 // CHECK:STDOUT:   %.loc10_29.9: ref i32 = array_index %a.var, %.loc10_29.8
-// CHECK:STDOUT:   %.loc10_29.10: init i32 = initialize_from %.loc10_28 to %.loc10_29.9
-// CHECK:STDOUT:   %.loc10_29.11: init [i32; 3] = array_init (%.loc10_29.4, %.loc10_29.7, %.loc10_29.10) to %a.var
-// CHECK:STDOUT:   %.loc10_29.12: init [i32; 3] = converted %.loc10_29.1, %.loc10_29.11
+// CHECK:STDOUT:   %.loc10_29.10: init i32 = initialize_from %.loc10_28 to %.loc10_29.9 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc10_29.11: init [i32; 3] = array_init (%.loc10_29.4, %.loc10_29.7, %.loc10_29.10) to %a.var [template = constants.%.10]
+// CHECK:STDOUT:   %.loc10_29.12: init [i32; 3] = converted %.loc10_29.1, %.loc10_29.11 [template = constants.%.10]
 // CHECK:STDOUT:   assign %a.var, %.loc10_29.12
-// CHECK:STDOUT:   %.loc13_14: type = ptr_type i32 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc13_14: type = ptr_type i32 [template = constants.%.11]
 // CHECK:STDOUT:   %pa.var: ref i32* = var pa
 // CHECK:STDOUT:   %pa: ref i32* = bind_name pa, %pa.var
 // CHECK:STDOUT:   %a.ref.loc13: ref [i32; 3] = name_ref a, %a
-// CHECK:STDOUT:   %.loc13_21: i32 = int_literal 0 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc13_21: i32 = int_literal 0 [template = constants.%.12]
 // CHECK:STDOUT:   %.loc13_22: ref i32 = array_index %a.ref.loc13, %.loc13_21
 // CHECK:STDOUT:   %.loc13_18: i32* = addr_of %.loc13_22
 // CHECK:STDOUT:   assign %pa.var, %.loc13_18
 // CHECK:STDOUT:   %a.ref.loc14: ref [i32; 3] = name_ref a, %a
-// CHECK:STDOUT:   %.loc14_5: i32 = int_literal 0 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc14_5: i32 = int_literal 0 [template = constants.%.12]
 // CHECK:STDOUT:   %.loc14_6: ref i32 = array_index %a.ref.loc14, %.loc14_5
-// CHECK:STDOUT:   %.loc14_10: i32 = int_literal 4 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc14_10: i32 = int_literal 4 [template = constants.%.13]
 // CHECK:STDOUT:   assign %.loc14_6, %.loc14_10
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -100,28 +101,28 @@ fn ValueBinding(b: [i32; 3]) {
 // CHECK:STDOUT:   %.loc18_29.1: (i32, i32, i32) = tuple_literal (%.loc18_22, %.loc18_25, %.loc18_28)
 // CHECK:STDOUT:   %.loc18_29.2: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc18_29.3: ref i32 = array_index %a.var, %.loc18_29.2
-// CHECK:STDOUT:   %.loc18_29.4: init i32 = initialize_from %.loc18_22 to %.loc18_29.3
+// CHECK:STDOUT:   %.loc18_29.4: init i32 = initialize_from %.loc18_22 to %.loc18_29.3 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc18_29.5: i32 = int_literal 1 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc18_29.6: ref i32 = array_index %a.var, %.loc18_29.5
-// CHECK:STDOUT:   %.loc18_29.7: init i32 = initialize_from %.loc18_25 to %.loc18_29.6
+// CHECK:STDOUT:   %.loc18_29.7: init i32 = initialize_from %.loc18_25 to %.loc18_29.6 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc18_29.8: i32 = int_literal 2 [template = constants.%.9]
 // CHECK:STDOUT:   %.loc18_29.9: ref i32 = array_index %a.var, %.loc18_29.8
-// CHECK:STDOUT:   %.loc18_29.10: init i32 = initialize_from %.loc18_28 to %.loc18_29.9
-// CHECK:STDOUT:   %.loc18_29.11: init [i32; 3] = array_init (%.loc18_29.4, %.loc18_29.7, %.loc18_29.10) to %a.var
-// CHECK:STDOUT:   %.loc18_29.12: init [i32; 3] = converted %.loc18_29.1, %.loc18_29.11
+// CHECK:STDOUT:   %.loc18_29.10: init i32 = initialize_from %.loc18_28 to %.loc18_29.9 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc18_29.11: init [i32; 3] = array_init (%.loc18_29.4, %.loc18_29.7, %.loc18_29.10) to %a.var [template = constants.%.10]
+// CHECK:STDOUT:   %.loc18_29.12: init [i32; 3] = converted %.loc18_29.1, %.loc18_29.11 [template = constants.%.10]
 // CHECK:STDOUT:   assign %a.var, %.loc18_29.12
 // CHECK:STDOUT:   %a.ref: ref [i32; 3] = name_ref a, %a
-// CHECK:STDOUT:   %.loc22_5: i32 = int_literal 0 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc22_5: i32 = int_literal 0 [template = constants.%.12]
 // CHECK:STDOUT:   %.loc22_6: ref i32 = array_index %a.ref, %.loc22_5
 // CHECK:STDOUT:   %b.ref: [i32; 3] = name_ref b, %b
-// CHECK:STDOUT:   %.loc23_5: i32 = int_literal 0 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc23_5: i32 = int_literal 0 [template = constants.%.12]
 // CHECK:STDOUT:   %.loc23_6.1: ref [i32; 3] = value_as_ref %b.ref
 // CHECK:STDOUT:   %.loc23_6.2: ref i32 = array_index %.loc23_6.1, %.loc23_5
 // CHECK:STDOUT:   %.loc23_6.3: i32 = bind_value %.loc23_6.2
 // CHECK:STDOUT:   %F.ref: <function> = name_ref F, file.%F [template = file.%F]
 // CHECK:STDOUT:   %.loc24_4.1: ref [i32; 3] = temporary_storage
 // CHECK:STDOUT:   %.loc24_4.2: init [i32; 3] = call %F.ref() to %.loc24_4.1
-// CHECK:STDOUT:   %.loc24_7: i32 = int_literal 0 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc24_7: i32 = int_literal 0 [template = constants.%.12]
 // CHECK:STDOUT:   %.loc24_4.3: ref [i32; 3] = temporary %.loc24_4.1, %.loc24_4.2
 // CHECK:STDOUT:   %.loc24_8.1: ref i32 = array_index %.loc24_4.3, %.loc24_7
 // CHECK:STDOUT:   %.loc24_8.2: i32 = bind_value %.loc24_8.1

+ 6 - 5
toolchain/check/testdata/index/fail_array_large_index.carbon

@@ -19,7 +19,8 @@ var b: i32 = a[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %.4: i32 = int_literal 12 [template]
 // CHECK:STDOUT:   %.5: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.7: i32 = int_literal 295147905179352825855 [template]
+// CHECK:STDOUT:   %.7: [i32; 1] = tuple_value (%.4) [template]
+// CHECK:STDOUT:   %.8: i32 = int_literal 295147905179352825855 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -32,14 +33,14 @@ var b: i32 = a[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %.loc7_23.1: (i32,) = tuple_literal (%.loc7_20)
 // CHECK:STDOUT:   %.loc7_23.2: i32 = int_literal 0 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc7_23.3: ref i32 = array_index %a.var, %.loc7_23.2
-// CHECK:STDOUT:   %.loc7_23.4: init i32 = initialize_from %.loc7_20 to %.loc7_23.3
-// CHECK:STDOUT:   %.loc7_23.5: init [i32; 1] = array_init (%.loc7_23.4) to %a.var
-// CHECK:STDOUT:   %.loc7_23.6: init [i32; 1] = converted %.loc7_23.1, %.loc7_23.5
+// CHECK:STDOUT:   %.loc7_23.4: init i32 = initialize_from %.loc7_20 to %.loc7_23.3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc7_23.5: init [i32; 1] = array_init (%.loc7_23.4) to %a.var [template = constants.%.7]
+// CHECK:STDOUT:   %.loc7_23.6: init [i32; 1] = converted %.loc7_23.1, %.loc7_23.5 [template = constants.%.7]
 // CHECK:STDOUT:   assign %a.var, %.loc7_23.6
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: ref [i32; 1] = name_ref a, %a
-// CHECK:STDOUT:   %.loc11_16: i32 = int_literal 295147905179352825855 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc11_16: i32 = int_literal 295147905179352825855 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc11_35.1: ref i32 = array_index %a.ref, <error>
 // CHECK:STDOUT:   %.loc11_35.2: i32 = bind_value %.loc11_35.1
 // CHECK:STDOUT:   assign %b.var, %.loc11_35.2

+ 6 - 5
toolchain/check/testdata/index/fail_array_non_int_indexing.carbon

@@ -19,7 +19,8 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:   %.4: i32 = int_literal 12 [template]
 // CHECK:STDOUT:   %.5: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.7: f64 = real_literal 26e-1 [template]
+// CHECK:STDOUT:   %.7: [i32; 1] = tuple_value (%.4) [template]
+// CHECK:STDOUT:   %.8: f64 = real_literal 26e-1 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -32,14 +33,14 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:   %.loc7_23.1: (i32,) = tuple_literal (%.loc7_20)
 // CHECK:STDOUT:   %.loc7_23.2: i32 = int_literal 0 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc7_23.3: ref i32 = array_index %a.var, %.loc7_23.2
-// CHECK:STDOUT:   %.loc7_23.4: init i32 = initialize_from %.loc7_20 to %.loc7_23.3
-// CHECK:STDOUT:   %.loc7_23.5: init [i32; 1] = array_init (%.loc7_23.4) to %a.var
-// CHECK:STDOUT:   %.loc7_23.6: init [i32; 1] = converted %.loc7_23.1, %.loc7_23.5
+// CHECK:STDOUT:   %.loc7_23.4: init i32 = initialize_from %.loc7_20 to %.loc7_23.3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc7_23.5: init [i32; 1] = array_init (%.loc7_23.4) to %a.var [template = constants.%.7]
+// CHECK:STDOUT:   %.loc7_23.6: init [i32; 1] = converted %.loc7_23.1, %.loc7_23.5 [template = constants.%.7]
 // CHECK:STDOUT:   assign %a.var, %.loc7_23.6
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: ref [i32; 1] = name_ref a, %a
-// CHECK:STDOUT:   %.loc11_16: f64 = real_literal 26e-1 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc11_16: f64 = real_literal 26e-1 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc11_19.1: ref i32 = array_index %a.ref, <error>
 // CHECK:STDOUT:   %.loc11_19.2: i32 = bind_value %.loc11_19.1
 // CHECK:STDOUT:   assign %b.var, %.loc11_19.2

+ 6 - 5
toolchain/check/testdata/index/fail_array_out_of_bound_access.carbon

@@ -19,7 +19,8 @@ var b: i32 = a[2];
 // CHECK:STDOUT:   %.4: i32 = int_literal 12 [template]
 // CHECK:STDOUT:   %.5: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.7: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.7: [i32; 1] = tuple_value (%.4) [template]
+// CHECK:STDOUT:   %.8: i32 = int_literal 2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -32,14 +33,14 @@ var b: i32 = a[2];
 // CHECK:STDOUT:   %.loc7_23.1: (i32,) = tuple_literal (%.loc7_20)
 // CHECK:STDOUT:   %.loc7_23.2: i32 = int_literal 0 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc7_23.3: ref i32 = array_index %a.var, %.loc7_23.2
-// CHECK:STDOUT:   %.loc7_23.4: init i32 = initialize_from %.loc7_20 to %.loc7_23.3
-// CHECK:STDOUT:   %.loc7_23.5: init [i32; 1] = array_init (%.loc7_23.4) to %a.var
-// CHECK:STDOUT:   %.loc7_23.6: init [i32; 1] = converted %.loc7_23.1, %.loc7_23.5
+// CHECK:STDOUT:   %.loc7_23.4: init i32 = initialize_from %.loc7_20 to %.loc7_23.3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc7_23.5: init [i32; 1] = array_init (%.loc7_23.4) to %a.var [template = constants.%.7]
+// CHECK:STDOUT:   %.loc7_23.6: init [i32; 1] = converted %.loc7_23.1, %.loc7_23.5 [template = constants.%.7]
 // CHECK:STDOUT:   assign %a.var, %.loc7_23.6
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: ref [i32; 1] = name_ref a, %a
-// CHECK:STDOUT:   %.loc11_16: i32 = int_literal 2 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc11_16: i32 = int_literal 2 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc11_17.1: ref i32 = array_index %a.ref, <error>
 // CHECK:STDOUT:   %.loc11_17.2: i32 = bind_value %.loc11_17.1
 // CHECK:STDOUT:   assign %b.var, %.loc11_17.2

+ 2 - 1
toolchain/check/testdata/index/fail_negative_indexing.carbon

@@ -18,7 +18,8 @@ var b: i32 = a[-10];
 // CHECK:STDOUT:   %.3: type = ptr_type (i32, i32) [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 12 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 6 [template]
-// CHECK:STDOUT:   %.6: i32 = int_literal 10 [template]
+// CHECK:STDOUT:   %.6: (i32, i32) = tuple_value (%.4, %.5) [template]
+// CHECK:STDOUT:   %.7: i32 = int_literal 10 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {

+ 7 - 6
toolchain/check/testdata/index/fail_non_deterministic_type.carbon

@@ -19,7 +19,8 @@ var c: i32 = a[b];
 // CHECK:STDOUT:   %.3: type = ptr_type (i32, i32) [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 3 [template]
-// CHECK:STDOUT:   %.6: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.6: (i32, i32) = tuple_value (%.4, %.5) [template]
+// CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -32,15 +33,15 @@ var c: i32 = a[b];
 // CHECK:STDOUT:   %.loc7_25: i32 = int_literal 3 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_26.1: (i32, i32) = tuple_literal (%.loc7_22, %.loc7_25)
 // CHECK:STDOUT:   %.loc7_26.2: ref i32 = tuple_access %a.var, element0
-// CHECK:STDOUT:   %.loc7_26.3: init i32 = initialize_from %.loc7_22 to %.loc7_26.2
+// CHECK:STDOUT:   %.loc7_26.3: init i32 = initialize_from %.loc7_22 to %.loc7_26.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_26.4: ref i32 = tuple_access %a.var, element1
-// CHECK:STDOUT:   %.loc7_26.5: init i32 = initialize_from %.loc7_25 to %.loc7_26.4
-// CHECK:STDOUT:   %.loc7_26.6: init (i32, i32) = tuple_init (%.loc7_26.3, %.loc7_26.5) to %a.var
-// CHECK:STDOUT:   %.loc7_26.7: init (i32, i32) = converted %.loc7_26.1, %.loc7_26.6
+// CHECK:STDOUT:   %.loc7_26.5: init i32 = initialize_from %.loc7_25 to %.loc7_26.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc7_26.6: init (i32, i32) = tuple_init (%.loc7_26.3, %.loc7_26.5) to %a.var [template = constants.%.6]
+// CHECK:STDOUT:   %.loc7_26.7: init (i32, i32) = converted %.loc7_26.1, %.loc7_26.6 [template = constants.%.6]
 // CHECK:STDOUT:   assign %a.var, %.loc7_26.7
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
-// CHECK:STDOUT:   %.loc8: i32 = int_literal 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc8: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   assign %b.var, %.loc8
 // CHECK:STDOUT:   %c.var: ref i32 = var c
 // CHECK:STDOUT:   %c: ref i32 = bind_name c, %c.var

+ 5 - 4
toolchain/check/testdata/index/fail_tuple_index_error.carbon

@@ -18,6 +18,7 @@ var b: i32 = a[oops];
 // CHECK:STDOUT:   %.3: type = ptr_type (i32, i32) [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 12 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 6 [template]
+// CHECK:STDOUT:   %.6: (i32, i32) = tuple_value (%.4, %.5) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -30,11 +31,11 @@ var b: i32 = a[oops];
 // CHECK:STDOUT:   %.loc7_26: i32 = int_literal 6 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_27.1: (i32, i32) = tuple_literal (%.loc7_22, %.loc7_26)
 // CHECK:STDOUT:   %.loc7_27.2: ref i32 = tuple_access %a.var, element0
-// CHECK:STDOUT:   %.loc7_27.3: init i32 = initialize_from %.loc7_22 to %.loc7_27.2
+// CHECK:STDOUT:   %.loc7_27.3: init i32 = initialize_from %.loc7_22 to %.loc7_27.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_27.4: ref i32 = tuple_access %a.var, element1
-// CHECK:STDOUT:   %.loc7_27.5: init i32 = initialize_from %.loc7_26 to %.loc7_27.4
-// CHECK:STDOUT:   %.loc7_27.6: init (i32, i32) = tuple_init (%.loc7_27.3, %.loc7_27.5) to %a.var
-// CHECK:STDOUT:   %.loc7_27.7: init (i32, i32) = converted %.loc7_27.1, %.loc7_27.6
+// CHECK:STDOUT:   %.loc7_27.5: init i32 = initialize_from %.loc7_26 to %.loc7_27.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc7_27.6: init (i32, i32) = tuple_init (%.loc7_27.3, %.loc7_27.5) to %a.var [template = constants.%.6]
+// CHECK:STDOUT:   %.loc7_27.7: init (i32, i32) = converted %.loc7_27.1, %.loc7_27.6 [template = constants.%.6]
 // CHECK:STDOUT:   assign %a.var, %.loc7_27.7
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var

+ 5 - 4
toolchain/check/testdata/index/fail_tuple_large_index.carbon

@@ -17,7 +17,8 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %.1: type = tuple_type (type) [template]
 // CHECK:STDOUT:   %.2: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.3: i32 = int_literal 12 [template]
-// CHECK:STDOUT:   %.4: i32 = int_literal 295147905179352825855 [template]
+// CHECK:STDOUT:   %.4: (i32,) = tuple_value (%.3) [template]
+// CHECK:STDOUT:   %.5: i32 = int_literal 295147905179352825855 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -28,8 +29,8 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %a: ref (i32,) = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc7_18: i32 = int_literal 12 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc7_21.1: (i32,) = tuple_literal (%.loc7_18)
-// CHECK:STDOUT:   %.loc7_21.2: init (i32,) = tuple_init (%.loc7_18) to %a.var
-// CHECK:STDOUT:   %.loc7_21.3: init (i32,) = converted %.loc7_21.1, %.loc7_21.2
+// CHECK:STDOUT:   %.loc7_21.2: init (i32,) = tuple_init (%.loc7_18) to %a.var [template = constants.%.4]
+// CHECK:STDOUT:   %.loc7_21.3: init (i32,) = converted %.loc7_21.1, %.loc7_21.2 [template = constants.%.4]
 // CHECK:STDOUT:   assign %a.var, %.loc7_21.3
 // CHECK:STDOUT:   %.loc8_13.1: (type,) = tuple_literal (i32)
 // CHECK:STDOUT:   %.loc8_13.2: type = converted %.loc8_13.1, constants.%.2 [template = constants.%.2]
@@ -44,7 +45,7 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %c.var: ref i32 = var c
 // CHECK:STDOUT:   %c: ref i32 = bind_name c, %c.var
 // CHECK:STDOUT:   %b.ref: ref (i32,) = name_ref b, %b
-// CHECK:STDOUT:   %.loc12_16: i32 = int_literal 295147905179352825855 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc12_16: i32 = int_literal 295147905179352825855 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc12_35: ref <error> = tuple_index %b.ref, <error>
 // CHECK:STDOUT:   assign %c.var, <error>
 // CHECK:STDOUT: }

+ 7 - 6
toolchain/check/testdata/index/fail_tuple_non_int_indexing.carbon

@@ -18,7 +18,8 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:   %.3: type = ptr_type (i32, i32) [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 12 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 6 [template]
-// CHECK:STDOUT:   %.6: f64 = real_literal 26e-1 [template]
+// CHECK:STDOUT:   %.6: (i32, i32) = tuple_value (%.4, %.5) [template]
+// CHECK:STDOUT:   %.7: f64 = real_literal 26e-1 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -31,16 +32,16 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:   %.loc7_26: i32 = int_literal 6 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_27.1: (i32, i32) = tuple_literal (%.loc7_22, %.loc7_26)
 // CHECK:STDOUT:   %.loc7_27.2: ref i32 = tuple_access %a.var, element0
-// CHECK:STDOUT:   %.loc7_27.3: init i32 = initialize_from %.loc7_22 to %.loc7_27.2
+// CHECK:STDOUT:   %.loc7_27.3: init i32 = initialize_from %.loc7_22 to %.loc7_27.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_27.4: ref i32 = tuple_access %a.var, element1
-// CHECK:STDOUT:   %.loc7_27.5: init i32 = initialize_from %.loc7_26 to %.loc7_27.4
-// CHECK:STDOUT:   %.loc7_27.6: init (i32, i32) = tuple_init (%.loc7_27.3, %.loc7_27.5) to %a.var
-// CHECK:STDOUT:   %.loc7_27.7: init (i32, i32) = converted %.loc7_27.1, %.loc7_27.6
+// CHECK:STDOUT:   %.loc7_27.5: init i32 = initialize_from %.loc7_26 to %.loc7_27.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc7_27.6: init (i32, i32) = tuple_init (%.loc7_27.3, %.loc7_27.5) to %a.var [template = constants.%.6]
+// CHECK:STDOUT:   %.loc7_27.7: init (i32, i32) = converted %.loc7_27.1, %.loc7_27.6 [template = constants.%.6]
 // CHECK:STDOUT:   assign %a.var, %.loc7_27.7
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: ref (i32, i32) = name_ref a, %a
-// CHECK:STDOUT:   %.loc11_16: f64 = real_literal 26e-1 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc11_16: f64 = real_literal 26e-1 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc11_19: ref <error> = tuple_index %a.ref, <error>
 // CHECK:STDOUT:   assign %b.var, <error>
 // CHECK:STDOUT: }

+ 7 - 6
toolchain/check/testdata/index/fail_tuple_out_of_bound_access.carbon

@@ -18,7 +18,8 @@ var b: i32 = a[2];
 // CHECK:STDOUT:   %.3: type = ptr_type (i32, i32) [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 12 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 6 [template]
-// CHECK:STDOUT:   %.6: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.6: (i32, i32) = tuple_value (%.4, %.5) [template]
+// CHECK:STDOUT:   %.7: i32 = int_literal 2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -31,16 +32,16 @@ var b: i32 = a[2];
 // CHECK:STDOUT:   %.loc7_26: i32 = int_literal 6 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_27.1: (i32, i32) = tuple_literal (%.loc7_22, %.loc7_26)
 // CHECK:STDOUT:   %.loc7_27.2: ref i32 = tuple_access %a.var, element0
-// CHECK:STDOUT:   %.loc7_27.3: init i32 = initialize_from %.loc7_22 to %.loc7_27.2
+// CHECK:STDOUT:   %.loc7_27.3: init i32 = initialize_from %.loc7_22 to %.loc7_27.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_27.4: ref i32 = tuple_access %a.var, element1
-// CHECK:STDOUT:   %.loc7_27.5: init i32 = initialize_from %.loc7_26 to %.loc7_27.4
-// CHECK:STDOUT:   %.loc7_27.6: init (i32, i32) = tuple_init (%.loc7_27.3, %.loc7_27.5) to %a.var
-// CHECK:STDOUT:   %.loc7_27.7: init (i32, i32) = converted %.loc7_27.1, %.loc7_27.6
+// CHECK:STDOUT:   %.loc7_27.5: init i32 = initialize_from %.loc7_26 to %.loc7_27.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc7_27.6: init (i32, i32) = tuple_init (%.loc7_27.3, %.loc7_27.5) to %a.var [template = constants.%.6]
+// CHECK:STDOUT:   %.loc7_27.7: init (i32, i32) = converted %.loc7_27.1, %.loc7_27.6 [template = constants.%.6]
 // CHECK:STDOUT:   assign %a.var, %.loc7_27.7
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: ref (i32, i32) = name_ref a, %a
-// CHECK:STDOUT:   %.loc11_16: i32 = int_literal 2 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc11_16: i32 = int_literal 2 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc11_17: ref <error> = tuple_index %a.ref, <error>
 // CHECK:STDOUT:   assign %b.var, <error>
 // CHECK:STDOUT: }

+ 5 - 4
toolchain/check/testdata/index/tuple_element_access.carbon

@@ -14,7 +14,8 @@ var c: i32 = b[0];
 // CHECK:STDOUT:   %.1: type = tuple_type (type) [template]
 // CHECK:STDOUT:   %.2: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.3: i32 = int_literal 12 [template]
-// CHECK:STDOUT:   %.4: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.4: (i32,) = tuple_value (%.3) [template]
+// CHECK:STDOUT:   %.5: i32 = int_literal 0 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -25,8 +26,8 @@ var c: i32 = b[0];
 // CHECK:STDOUT:   %a: ref (i32,) = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc7_18: i32 = int_literal 12 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc7_21.1: (i32,) = tuple_literal (%.loc7_18)
-// CHECK:STDOUT:   %.loc7_21.2: init (i32,) = tuple_init (%.loc7_18) to %a.var
-// CHECK:STDOUT:   %.loc7_21.3: init (i32,) = converted %.loc7_21.1, %.loc7_21.2
+// CHECK:STDOUT:   %.loc7_21.2: init (i32,) = tuple_init (%.loc7_18) to %a.var [template = constants.%.4]
+// CHECK:STDOUT:   %.loc7_21.3: init (i32,) = converted %.loc7_21.1, %.loc7_21.2 [template = constants.%.4]
 // CHECK:STDOUT:   assign %a.var, %.loc7_21.3
 // CHECK:STDOUT:   %.loc8_13.1: (type,) = tuple_literal (i32)
 // CHECK:STDOUT:   %.loc8_13.2: type = converted %.loc8_13.1, constants.%.2 [template = constants.%.2]
@@ -41,7 +42,7 @@ var c: i32 = b[0];
 // CHECK:STDOUT:   %c.var: ref i32 = var c
 // CHECK:STDOUT:   %c: ref i32 = bind_name c, %c.var
 // CHECK:STDOUT:   %b.ref: ref (i32,) = name_ref b, %b
-// CHECK:STDOUT:   %.loc9_16: i32 = int_literal 0 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc9_16: i32 = int_literal 0 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc9_17.1: ref i32 = tuple_index %b.ref, %.loc9_16
 // CHECK:STDOUT:   %.loc9_17.2: i32 = bind_value %.loc9_17.1
 // CHECK:STDOUT:   assign %c.var, %.loc9_17.2

+ 6 - 5
toolchain/check/testdata/let/convert.carbon

@@ -20,6 +20,7 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %.4: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 3 [template]
+// CHECK:STDOUT:   %.7: (i32, i32, i32) = tuple_value (%.4, %.5, %.6) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -38,13 +39,13 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %.loc8_35: i32 = int_literal 3 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc8_36.1: (i32, i32, i32) = tuple_literal (%.loc8_29, %.loc8_32, %.loc8_35)
 // CHECK:STDOUT:   %.loc8_36.2: ref i32 = tuple_access %v.var, element0
-// CHECK:STDOUT:   %.loc8_36.3: init i32 = initialize_from %.loc8_29 to %.loc8_36.2
+// CHECK:STDOUT:   %.loc8_36.3: init i32 = initialize_from %.loc8_29 to %.loc8_36.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc8_36.4: ref i32 = tuple_access %v.var, element1
-// CHECK:STDOUT:   %.loc8_36.5: init i32 = initialize_from %.loc8_32 to %.loc8_36.4
+// CHECK:STDOUT:   %.loc8_36.5: init i32 = initialize_from %.loc8_32 to %.loc8_36.4 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc8_36.6: ref i32 = tuple_access %v.var, element2
-// CHECK:STDOUT:   %.loc8_36.7: init i32 = initialize_from %.loc8_35 to %.loc8_36.6
-// CHECK:STDOUT:   %.loc8_36.8: init (i32, i32, i32) = tuple_init (%.loc8_36.3, %.loc8_36.5, %.loc8_36.7) to %v.var
-// CHECK:STDOUT:   %.loc8_36.9: init (i32, i32, i32) = converted %.loc8_36.1, %.loc8_36.8
+// CHECK:STDOUT:   %.loc8_36.7: init i32 = initialize_from %.loc8_35 to %.loc8_36.6 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc8_36.8: init (i32, i32, i32) = tuple_init (%.loc8_36.3, %.loc8_36.5, %.loc8_36.7) to %v.var [template = constants.%.7]
+// CHECK:STDOUT:   %.loc8_36.9: init (i32, i32, i32) = converted %.loc8_36.1, %.loc8_36.8 [template = constants.%.7]
 // CHECK:STDOUT:   assign %v.var, %.loc8_36.9
 // CHECK:STDOUT:   %.loc10_24.1: (type, type, type) = tuple_literal (i32, i32, i32)
 // CHECK:STDOUT:   %.loc10_24.2: type = converted %.loc10_24.1, constants.%.2 [template = constants.%.2]

+ 29 - 27
toolchain/check/testdata/operators/assignment.carbon

@@ -32,15 +32,17 @@ fn Main() {
 // CHECK:STDOUT:   %.5: type = ptr_type (i32, i32) [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.7: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.8: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.9: i32 = int_literal 3 [template]
-// CHECK:STDOUT:   %.10: i32 = int_literal 4 [template]
-// CHECK:STDOUT:   %.11: type = struct_type {.a: i32, .b: i32} [template]
-// CHECK:STDOUT:   %.12: type = ptr_type {.a: i32, .b: i32} [template]
-// CHECK:STDOUT:   %.13: type = ptr_type i32 [template]
-// CHECK:STDOUT:   %.14: i32 = int_literal 5 [template]
-// CHECK:STDOUT:   %.15: bool = bool_literal true [template]
-// CHECK:STDOUT:   %.16: i32 = int_literal 10 [template]
+// CHECK:STDOUT:   %.8: (i32, i32) = tuple_value (%.6, %.7) [template]
+// CHECK:STDOUT:   %.9: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.10: i32 = int_literal 3 [template]
+// CHECK:STDOUT:   %.11: i32 = int_literal 4 [template]
+// CHECK:STDOUT:   %.12: type = struct_type {.a: i32, .b: i32} [template]
+// CHECK:STDOUT:   %.13: type = ptr_type {.a: i32, .b: i32} [template]
+// CHECK:STDOUT:   %.14: {.a: i32, .b: i32} = struct_value (%.6, %.7) [template]
+// CHECK:STDOUT:   %.15: type = ptr_type i32 [template]
+// CHECK:STDOUT:   %.16: i32 = int_literal 5 [template]
+// CHECK:STDOUT:   %.17: bool = bool_literal true [template]
+// CHECK:STDOUT:   %.18: i32 = int_literal 10 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -65,44 +67,44 @@ fn Main() {
 // CHECK:STDOUT:   %.loc11_27: i32 = int_literal 2 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc11_28.1: (i32, i32) = tuple_literal (%.loc11_24, %.loc11_27)
 // CHECK:STDOUT:   %.loc11_28.2: ref i32 = tuple_access %b.var, element0
-// CHECK:STDOUT:   %.loc11_28.3: init i32 = initialize_from %.loc11_24 to %.loc11_28.2
+// CHECK:STDOUT:   %.loc11_28.3: init i32 = initialize_from %.loc11_24 to %.loc11_28.2 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc11_28.4: ref i32 = tuple_access %b.var, element1
-// CHECK:STDOUT:   %.loc11_28.5: init i32 = initialize_from %.loc11_27 to %.loc11_28.4
-// CHECK:STDOUT:   %.loc11_28.6: init (i32, i32) = tuple_init (%.loc11_28.3, %.loc11_28.5) to %b.var
-// CHECK:STDOUT:   %.loc11_28.7: init (i32, i32) = converted %.loc11_28.1, %.loc11_28.6
+// CHECK:STDOUT:   %.loc11_28.5: init i32 = initialize_from %.loc11_27 to %.loc11_28.4 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc11_28.6: init (i32, i32) = tuple_init (%.loc11_28.3, %.loc11_28.5) to %b.var [template = constants.%.8]
+// CHECK:STDOUT:   %.loc11_28.7: init (i32, i32) = converted %.loc11_28.1, %.loc11_28.6 [template = constants.%.8]
 // CHECK:STDOUT:   assign %b.var, %.loc11_28.7
 // CHECK:STDOUT:   %b.ref.loc12: ref (i32, i32) = name_ref b, %b
-// CHECK:STDOUT:   %.loc12_5: i32 = int_literal 0 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc12_5: i32 = int_literal 0 [template = constants.%.9]
 // CHECK:STDOUT:   %.loc12_6: ref i32 = tuple_index %b.ref.loc12, %.loc12_5
-// CHECK:STDOUT:   %.loc12_10: i32 = int_literal 3 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc12_10: i32 = int_literal 3 [template = constants.%.10]
 // CHECK:STDOUT:   assign %.loc12_6, %.loc12_10
 // CHECK:STDOUT:   %b.ref.loc13: ref (i32, i32) = name_ref b, %b
 // CHECK:STDOUT:   %.loc13_5: i32 = int_literal 1 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc13_6: ref i32 = tuple_index %b.ref.loc13, %.loc13_5
-// CHECK:STDOUT:   %.loc13_10: i32 = int_literal 4 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc13_10: i32 = int_literal 4 [template = constants.%.11]
 // CHECK:STDOUT:   assign %.loc13_6, %.loc13_10
-// CHECK:STDOUT:   %.loc15_27: type = struct_type {.a: i32, .b: i32} [template = constants.%.11]
+// CHECK:STDOUT:   %.loc15_27: type = struct_type {.a: i32, .b: i32} [template = constants.%.12]
 // CHECK:STDOUT:   %c.var: ref {.a: i32, .b: i32} = var c
 // CHECK:STDOUT:   %c: ref {.a: i32, .b: i32} = bind_name c, %c.var
 // CHECK:STDOUT:   %.loc15_37: i32 = int_literal 1 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc15_45: i32 = int_literal 2 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc15_46.1: {.a: i32, .b: i32} = struct_literal (%.loc15_37, %.loc15_45)
 // CHECK:STDOUT:   %.loc15_46.2: ref i32 = struct_access %c.var, element0
-// CHECK:STDOUT:   %.loc15_46.3: init i32 = initialize_from %.loc15_37 to %.loc15_46.2
+// CHECK:STDOUT:   %.loc15_46.3: init i32 = initialize_from %.loc15_37 to %.loc15_46.2 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc15_46.4: ref i32 = struct_access %c.var, element1
-// CHECK:STDOUT:   %.loc15_46.5: init i32 = initialize_from %.loc15_45 to %.loc15_46.4
-// CHECK:STDOUT:   %.loc15_46.6: init {.a: i32, .b: i32} = struct_init (%.loc15_46.3, %.loc15_46.5) to %c.var
-// CHECK:STDOUT:   %.loc15_46.7: init {.a: i32, .b: i32} = converted %.loc15_46.1, %.loc15_46.6
+// CHECK:STDOUT:   %.loc15_46.5: init i32 = initialize_from %.loc15_45 to %.loc15_46.4 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc15_46.6: init {.a: i32, .b: i32} = struct_init (%.loc15_46.3, %.loc15_46.5) to %c.var [template = constants.%.14]
+// CHECK:STDOUT:   %.loc15_46.7: init {.a: i32, .b: i32} = converted %.loc15_46.1, %.loc15_46.6 [template = constants.%.14]
 // CHECK:STDOUT:   assign %c.var, %.loc15_46.7
 // CHECK:STDOUT:   %c.ref.loc16: ref {.a: i32, .b: i32} = name_ref c, %c
 // CHECK:STDOUT:   %.loc16_4: ref i32 = struct_access %c.ref.loc16, element0
-// CHECK:STDOUT:   %.loc16_9: i32 = int_literal 3 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc16_9: i32 = int_literal 3 [template = constants.%.10]
 // CHECK:STDOUT:   assign %.loc16_4, %.loc16_9
 // CHECK:STDOUT:   %c.ref.loc17: ref {.a: i32, .b: i32} = name_ref c, %c
 // CHECK:STDOUT:   %.loc17_4: ref i32 = struct_access %c.ref.loc17, element1
-// CHECK:STDOUT:   %.loc17_9: i32 = int_literal 4 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc17_9: i32 = int_literal 4 [template = constants.%.11]
 // CHECK:STDOUT:   assign %.loc17_4, %.loc17_9
-// CHECK:STDOUT:   %.loc19_13: type = ptr_type i32 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc19_13: type = ptr_type i32 [template = constants.%.15]
 // CHECK:STDOUT:   %p.var: ref i32* = var p
 // CHECK:STDOUT:   %p: ref i32* = bind_name p, %p.var
 // CHECK:STDOUT:   %a.ref.loc19: ref i32 = name_ref a, %a
@@ -111,9 +113,9 @@ fn Main() {
 // CHECK:STDOUT:   %p.ref.loc20: ref i32* = name_ref p, %p
 // CHECK:STDOUT:   %.loc20_4: i32* = bind_value %p.ref.loc20
 // CHECK:STDOUT:   %.loc20_3: ref i32 = deref %.loc20_4
-// CHECK:STDOUT:   %.loc20_8: i32 = int_literal 5 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc20_8: i32 = int_literal 5 [template = constants.%.16]
 // CHECK:STDOUT:   assign %.loc20_3, %.loc20_8
-// CHECK:STDOUT:   %.loc22_8: bool = bool_literal true [template = constants.%.15]
+// CHECK:STDOUT:   %.loc22_8: bool = bool_literal true [template = constants.%.17]
 // CHECK:STDOUT:   if %.loc22_8 br !if.expr.then else br !if.expr.else
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.then:
@@ -129,7 +131,7 @@ fn Main() {
 // CHECK:STDOUT: !if.expr.result:
 // CHECK:STDOUT:   %.loc22_5: i32* = block_arg !if.expr.result
 // CHECK:STDOUT:   %.loc22_3: ref i32 = deref %.loc22_5
-// CHECK:STDOUT:   %.loc22_31: i32 = int_literal 10 [template = constants.%.16]
+// CHECK:STDOUT:   %.loc22_31: i32 = int_literal 10 [template = constants.%.18]
 // CHECK:STDOUT:   assign %.loc22_3, %.loc22_31
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 31 - 29
toolchain/check/testdata/operators/fail_assignment_to_non_assignable.carbon

@@ -54,14 +54,16 @@ fn Main() {
 // CHECK:STDOUT:   %.4: i32 = int_literal 3 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 4 [template]
 // CHECK:STDOUT:   %.6: type = ptr_type (i32, i32) [template]
-// CHECK:STDOUT:   %.7: (i32, i32) = tuple_value (%.1, %.2) [template]
-// CHECK:STDOUT:   %.8: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.9: type = ptr_type i32 [template]
-// CHECK:STDOUT:   %.10: type = struct_type {.x: i32, .y: i32} [template]
-// CHECK:STDOUT:   %.11: type = ptr_type {.x: i32, .y: i32} [template]
-// CHECK:STDOUT:   %.12: {.x: i32, .y: i32} = struct_value (%.1, %.2) [template]
-// CHECK:STDOUT:   %.13: bool = bool_literal true [template]
-// CHECK:STDOUT:   %.14: i32 = int_literal 10 [template]
+// CHECK:STDOUT:   %.7: (i32, i32) = tuple_value (%.4, %.5) [template]
+// CHECK:STDOUT:   %.8: (i32, i32) = tuple_value (%.1, %.2) [template]
+// CHECK:STDOUT:   %.9: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.10: type = ptr_type i32 [template]
+// CHECK:STDOUT:   %.11: type = struct_type {.x: i32, .y: i32} [template]
+// CHECK:STDOUT:   %.12: type = ptr_type {.x: i32, .y: i32} [template]
+// CHECK:STDOUT:   %.13: {.x: i32, .y: i32} = struct_value (%.4, %.5) [template]
+// CHECK:STDOUT:   %.14: {.x: i32, .y: i32} = struct_value (%.1, %.2) [template]
+// CHECK:STDOUT:   %.15: bool = bool_literal true [template]
+// CHECK:STDOUT:   %.16: i32 = int_literal 10 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -88,17 +90,17 @@ fn Main() {
 // CHECK:STDOUT:   %.loc21_16: i32 = int_literal 4 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc21_17.1: (i32, i32) = tuple_literal (%.loc21_13, %.loc21_16)
 // CHECK:STDOUT:   %.loc21_17.2: i32 = tuple_access %.loc21_8.1, element0
-// CHECK:STDOUT:   %.loc21_17.3: init i32 = initialize_from %.loc21_13 to %.loc21_17.2
+// CHECK:STDOUT:   %.loc21_17.3: init i32 = initialize_from %.loc21_13 to %.loc21_17.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc21_17.4: i32 = tuple_access %.loc21_8.1, element1
-// CHECK:STDOUT:   %.loc21_17.5: init i32 = initialize_from %.loc21_16 to %.loc21_17.4
-// CHECK:STDOUT:   %.loc21_17.6: init (i32, i32) = tuple_init (%.loc21_17.3, %.loc21_17.5) to %.loc21_8.1
-// CHECK:STDOUT:   %.loc21_17.7: init (i32, i32) = converted %.loc21_17.1, %.loc21_17.6
+// CHECK:STDOUT:   %.loc21_17.5: init i32 = initialize_from %.loc21_16 to %.loc21_17.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc21_17.6: init (i32, i32) = tuple_init (%.loc21_17.3, %.loc21_17.5) to %.loc21_8.1 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc21_17.7: init (i32, i32) = converted %.loc21_17.1, %.loc21_17.6 [template = constants.%.7]
 // CHECK:STDOUT:   assign %.loc21_8.1, %.loc21_17.7
-// CHECK:STDOUT:   %.loc21_8.2: (i32, i32) = tuple_value (%.loc21_4, %.loc21_7) [template = constants.%.7]
-// CHECK:STDOUT:   %.loc21_8.3: (i32, i32) = converted %.loc21_8.1, %.loc21_8.2 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc21_8.2: (i32, i32) = tuple_value (%.loc21_4, %.loc21_7) [template = constants.%.8]
+// CHECK:STDOUT:   %.loc21_8.3: (i32, i32) = converted %.loc21_8.1, %.loc21_8.2 [template = constants.%.8]
 // CHECK:STDOUT:   %n.var: ref i32 = var n
 // CHECK:STDOUT:   %n: ref i32 = bind_name n, %n.var
-// CHECK:STDOUT:   %.loc22: i32 = int_literal 0 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc22: i32 = int_literal 0 [template = constants.%.9]
 // CHECK:STDOUT:   assign %n.var, %.loc22
 // CHECK:STDOUT:   %n.ref.loc26_4: ref i32 = name_ref n, %n
 // CHECK:STDOUT:   %n.ref.loc26_7: ref i32 = name_ref n, %n
@@ -107,17 +109,17 @@ fn Main() {
 // CHECK:STDOUT:   %.loc26_16: i32 = int_literal 2 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc26_17.1: (i32, i32) = tuple_literal (%.loc26_13, %.loc26_16)
 // CHECK:STDOUT:   %.loc26_17.2: i32 = tuple_access %.loc26_8.1, element0
-// CHECK:STDOUT:   %.loc26_17.3: init i32 = initialize_from %.loc26_13 to %.loc26_17.2
+// CHECK:STDOUT:   %.loc26_17.3: init i32 = initialize_from %.loc26_13 to %.loc26_17.2 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc26_17.4: i32 = tuple_access %.loc26_8.1, element1
-// CHECK:STDOUT:   %.loc26_17.5: init i32 = initialize_from %.loc26_16 to %.loc26_17.4
-// CHECK:STDOUT:   %.loc26_17.6: init (i32, i32) = tuple_init (%.loc26_17.3, %.loc26_17.5) to %.loc26_8.1
-// CHECK:STDOUT:   %.loc26_17.7: init (i32, i32) = converted %.loc26_17.1, %.loc26_17.6
+// CHECK:STDOUT:   %.loc26_17.5: init i32 = initialize_from %.loc26_16 to %.loc26_17.4 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc26_17.6: init (i32, i32) = tuple_init (%.loc26_17.3, %.loc26_17.5) to %.loc26_8.1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc26_17.7: init (i32, i32) = converted %.loc26_17.1, %.loc26_17.6 [template = constants.%.8]
 // CHECK:STDOUT:   assign %.loc26_8.1, %.loc26_17.7
 // CHECK:STDOUT:   %.loc26_4: i32 = bind_value %n.ref.loc26_4
 // CHECK:STDOUT:   %.loc26_7: i32 = bind_value %n.ref.loc26_7
 // CHECK:STDOUT:   %.loc26_8.2: (i32, i32) = tuple_value (%.loc26_4, %.loc26_7)
 // CHECK:STDOUT:   %.loc26_8.3: (i32, i32) = converted %.loc26_8.1, %.loc26_8.2
-// CHECK:STDOUT:   %.loc30: type = ptr_type i32 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc30: type = ptr_type i32 [template = constants.%.10]
 // CHECK:STDOUT:   assign i32, %.loc30
 // CHECK:STDOUT:   %.loc34_9: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc34_17: i32 = int_literal 2 [template = constants.%.2]
@@ -126,15 +128,15 @@ fn Main() {
 // CHECK:STDOUT:   %.loc34_36: i32 = int_literal 4 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc34_37.1: {.x: i32, .y: i32} = struct_literal (%.loc34_28, %.loc34_36)
 // CHECK:STDOUT:   %.loc34_37.2: i32 = struct_access %.loc34_18.1, element0
-// CHECK:STDOUT:   %.loc34_37.3: init i32 = initialize_from %.loc34_28 to %.loc34_37.2
+// CHECK:STDOUT:   %.loc34_37.3: init i32 = initialize_from %.loc34_28 to %.loc34_37.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc34_37.4: i32 = struct_access %.loc34_18.1, element1
-// CHECK:STDOUT:   %.loc34_37.5: init i32 = initialize_from %.loc34_36 to %.loc34_37.4
-// CHECK:STDOUT:   %.loc34_37.6: init {.x: i32, .y: i32} = struct_init (%.loc34_37.3, %.loc34_37.5) to %.loc34_18.1
-// CHECK:STDOUT:   %.loc34_37.7: init {.x: i32, .y: i32} = converted %.loc34_37.1, %.loc34_37.6
+// CHECK:STDOUT:   %.loc34_37.5: init i32 = initialize_from %.loc34_36 to %.loc34_37.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc34_37.6: init {.x: i32, .y: i32} = struct_init (%.loc34_37.3, %.loc34_37.5) to %.loc34_18.1 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc34_37.7: init {.x: i32, .y: i32} = converted %.loc34_37.1, %.loc34_37.6 [template = constants.%.13]
 // CHECK:STDOUT:   assign %.loc34_18.1, %.loc34_37.7
-// CHECK:STDOUT:   %.loc34_18.2: {.x: i32, .y: i32} = struct_value (%.loc34_9, %.loc34_17) [template = constants.%.12]
-// CHECK:STDOUT:   %.loc34_18.3: {.x: i32, .y: i32} = converted %.loc34_18.1, %.loc34_18.2 [template = constants.%.12]
-// CHECK:STDOUT:   %.loc38_7: bool = bool_literal true [template = constants.%.13]
+// CHECK:STDOUT:   %.loc34_18.2: {.x: i32, .y: i32} = struct_value (%.loc34_9, %.loc34_17) [template = constants.%.14]
+// CHECK:STDOUT:   %.loc34_18.3: {.x: i32, .y: i32} = converted %.loc34_18.1, %.loc34_18.2 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc38_7: bool = bool_literal true [template = constants.%.15]
 // CHECK:STDOUT:   if %.loc38_7 br !if.expr.then.loc38 else br !if.expr.else.loc38
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.then.loc38:
@@ -151,7 +153,7 @@ fn Main() {
 // CHECK:STDOUT:   assign %.loc38_4, %.loc38_29
 // CHECK:STDOUT:   %a.var: ref i32 = var a
 // CHECK:STDOUT:   %a: ref i32 = bind_name a, %a.var
-// CHECK:STDOUT:   %.loc45_7: bool = bool_literal true [template = constants.%.13]
+// CHECK:STDOUT:   %.loc45_7: bool = bool_literal true [template = constants.%.15]
 // CHECK:STDOUT:   if %.loc45_7 br !if.expr.then.loc45 else br !if.expr.else.loc45
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.then.loc45:
@@ -166,7 +168,7 @@ fn Main() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.result.loc45:
 // CHECK:STDOUT:   %.loc45_4: i32 = block_arg !if.expr.result.loc45
-// CHECK:STDOUT:   %.loc45_29: i32 = int_literal 10 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc45_29: i32 = int_literal 10 [template = constants.%.16]
 // CHECK:STDOUT:   assign %.loc45_4, %.loc45_29
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 21 - 19
toolchain/check/testdata/pointer/address_of_lvalue.carbon

@@ -23,11 +23,13 @@ fn F() {
 // CHECK:STDOUT:   %.2: type = ptr_type {.a: i32, .b: i32} [template]
 // CHECK:STDOUT:   %.3: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type i32 [template]
-// CHECK:STDOUT:   %.6: type = tuple_type (type, type) [template]
-// CHECK:STDOUT:   %.7: type = tuple_type (i32, i32) [template]
-// CHECK:STDOUT:   %.8: type = ptr_type (i32, i32) [template]
-// CHECK:STDOUT:   %.9: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.5: {.a: i32, .b: i32} = struct_value (%.3, %.4) [template]
+// CHECK:STDOUT:   %.6: type = ptr_type i32 [template]
+// CHECK:STDOUT:   %.7: type = tuple_type (type, type) [template]
+// CHECK:STDOUT:   %.8: type = tuple_type (i32, i32) [template]
+// CHECK:STDOUT:   %.9: type = ptr_type (i32, i32) [template]
+// CHECK:STDOUT:   %.10: (i32, i32) = tuple_value (%.3, %.4) [template]
+// CHECK:STDOUT:   %.11: i32 = int_literal 0 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -44,11 +46,11 @@ fn F() {
 // CHECK:STDOUT:   %.loc8_45: i32 = int_literal 2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc8_46.1: {.a: i32, .b: i32} = struct_literal (%.loc8_37, %.loc8_45)
 // CHECK:STDOUT:   %.loc8_46.2: ref i32 = struct_access %s.var, element0
-// CHECK:STDOUT:   %.loc8_46.3: init i32 = initialize_from %.loc8_37 to %.loc8_46.2
+// CHECK:STDOUT:   %.loc8_46.3: init i32 = initialize_from %.loc8_37 to %.loc8_46.2 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc8_46.4: ref i32 = struct_access %s.var, element1
-// CHECK:STDOUT:   %.loc8_46.5: init i32 = initialize_from %.loc8_45 to %.loc8_46.4
-// CHECK:STDOUT:   %.loc8_46.6: init {.a: i32, .b: i32} = struct_init (%.loc8_46.3, %.loc8_46.5) to %s.var
-// CHECK:STDOUT:   %.loc8_46.7: init {.a: i32, .b: i32} = converted %.loc8_46.1, %.loc8_46.6
+// CHECK:STDOUT:   %.loc8_46.5: init i32 = initialize_from %.loc8_45 to %.loc8_46.4 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc8_46.6: init {.a: i32, .b: i32} = struct_init (%.loc8_46.3, %.loc8_46.5) to %s.var [template = constants.%.5]
+// CHECK:STDOUT:   %.loc8_46.7: init {.a: i32, .b: i32} = converted %.loc8_46.1, %.loc8_46.6 [template = constants.%.5]
 // CHECK:STDOUT:   assign %s.var, %.loc8_46.7
 // CHECK:STDOUT:   %.loc10_27: type = struct_type {.a: i32, .b: i32} [template = constants.%.1]
 // CHECK:STDOUT:   %.loc10_28: type = ptr_type {.a: i32, .b: i32} [template = constants.%.2]
@@ -57,14 +59,14 @@ fn F() {
 // CHECK:STDOUT:   %s.ref.loc10: ref {.a: i32, .b: i32} = name_ref s, %s
 // CHECK:STDOUT:   %.loc10_32: {.a: i32, .b: i32}* = addr_of %s.ref.loc10
 // CHECK:STDOUT:   assign %p.var, %.loc10_32
-// CHECK:STDOUT:   %.loc11_13: type = ptr_type i32 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_13: type = ptr_type i32 [template = constants.%.6]
 // CHECK:STDOUT:   %q.var: ref i32* = var q
 // CHECK:STDOUT:   %q: ref i32* = bind_name q, %q.var
 // CHECK:STDOUT:   %s.ref.loc11: ref {.a: i32, .b: i32} = name_ref s, %s
 // CHECK:STDOUT:   %.loc11_19: ref i32 = struct_access %s.ref.loc11, element0
 // CHECK:STDOUT:   %.loc11_17: i32* = addr_of %.loc11_19
 // CHECK:STDOUT:   assign %q.var, %.loc11_17
-// CHECK:STDOUT:   %.loc12_13: type = ptr_type i32 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc12_13: type = ptr_type i32 [template = constants.%.6]
 // CHECK:STDOUT:   %r.var: ref i32* = var r
 // CHECK:STDOUT:   %r: ref i32* = bind_name r, %r.var
 // CHECK:STDOUT:   %s.ref.loc12: ref {.a: i32, .b: i32} = name_ref s, %s
@@ -72,28 +74,28 @@ fn F() {
 // CHECK:STDOUT:   %.loc12_17: i32* = addr_of %.loc12_19
 // CHECK:STDOUT:   assign %r.var, %.loc12_17
 // CHECK:STDOUT:   %.loc14_19.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc14_19.2: type = converted %.loc14_19.1, constants.%.7 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc14_19.2: type = converted %.loc14_19.1, constants.%.8 [template = constants.%.8]
 // CHECK:STDOUT:   %t.var: ref (i32, i32) = var t
 // CHECK:STDOUT:   %t: ref (i32, i32) = bind_name t, %t.var
 // CHECK:STDOUT:   %.loc14_24: i32 = int_literal 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc14_27: i32 = int_literal 2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc14_28.1: (i32, i32) = tuple_literal (%.loc14_24, %.loc14_27)
 // CHECK:STDOUT:   %.loc14_28.2: ref i32 = tuple_access %t.var, element0
-// CHECK:STDOUT:   %.loc14_28.3: init i32 = initialize_from %.loc14_24 to %.loc14_28.2
+// CHECK:STDOUT:   %.loc14_28.3: init i32 = initialize_from %.loc14_24 to %.loc14_28.2 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc14_28.4: ref i32 = tuple_access %t.var, element1
-// CHECK:STDOUT:   %.loc14_28.5: init i32 = initialize_from %.loc14_27 to %.loc14_28.4
-// CHECK:STDOUT:   %.loc14_28.6: init (i32, i32) = tuple_init (%.loc14_28.3, %.loc14_28.5) to %t.var
-// CHECK:STDOUT:   %.loc14_28.7: init (i32, i32) = converted %.loc14_28.1, %.loc14_28.6
+// CHECK:STDOUT:   %.loc14_28.5: init i32 = initialize_from %.loc14_27 to %.loc14_28.4 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc14_28.6: init (i32, i32) = tuple_init (%.loc14_28.3, %.loc14_28.5) to %t.var [template = constants.%.10]
+// CHECK:STDOUT:   %.loc14_28.7: init (i32, i32) = converted %.loc14_28.1, %.loc14_28.6 [template = constants.%.10]
 // CHECK:STDOUT:   assign %t.var, %.loc14_28.7
-// CHECK:STDOUT:   %.loc15_14: type = ptr_type i32 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc15_14: type = ptr_type i32 [template = constants.%.6]
 // CHECK:STDOUT:   %t0.var: ref i32* = var t0
 // CHECK:STDOUT:   %t0: ref i32* = bind_name t0, %t0.var
 // CHECK:STDOUT:   %t.ref.loc15: ref (i32, i32) = name_ref t, %t
-// CHECK:STDOUT:   %.loc15_21: i32 = int_literal 0 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc15_21: i32 = int_literal 0 [template = constants.%.11]
 // CHECK:STDOUT:   %.loc15_22: ref i32 = tuple_index %t.ref.loc15, %.loc15_21
 // CHECK:STDOUT:   %.loc15_18: i32* = addr_of %.loc15_22
 // CHECK:STDOUT:   assign %t0.var, %.loc15_18
-// CHECK:STDOUT:   %.loc16_14: type = ptr_type i32 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc16_14: type = ptr_type i32 [template = constants.%.6]
 // CHECK:STDOUT:   %t1.var: ref i32* = var t1
 // CHECK:STDOUT:   %t1: ref i32* = bind_name t1, %t1.var
 // CHECK:STDOUT:   %t.ref.loc16: ref (i32, i32) = name_ref t, %t

+ 5 - 4
toolchain/check/testdata/return/fail_return_with_returned_var.carbon

@@ -37,6 +37,7 @@ fn G() -> C {
 // CHECK:STDOUT:   %.4: type = struct_type {.a: i32, .b: i32} [template]
 // CHECK:STDOUT:   %.5: type = ptr_type {.a: i32, .b: i32} [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.7: C = struct_value (%.2, %.6) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -75,11 +76,11 @@ fn G() -> C {
 // CHECK:STDOUT:   %.loc20_37: i32 = int_literal 2 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc20_38.1: {.a: i32, .b: i32} = struct_literal (%.loc20_29, %.loc20_37)
 // CHECK:STDOUT:   %.loc20_38.2: ref i32 = class_element_access %return, element0
-// CHECK:STDOUT:   %.loc20_38.3: init i32 = initialize_from %.loc20_29 to %.loc20_38.2
+// CHECK:STDOUT:   %.loc20_38.3: init i32 = initialize_from %.loc20_29 to %.loc20_38.2 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc20_38.4: ref i32 = class_element_access %return, element1
-// CHECK:STDOUT:   %.loc20_38.5: init i32 = initialize_from %.loc20_37 to %.loc20_38.4
-// CHECK:STDOUT:   %.loc20_38.6: init C = class_init (%.loc20_38.3, %.loc20_38.5), %return
-// CHECK:STDOUT:   %.loc20_38.7: init C = converted %.loc20_38.1, %.loc20_38.6
+// CHECK:STDOUT:   %.loc20_38.5: init i32 = initialize_from %.loc20_37 to %.loc20_38.4 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc20_38.6: init C = class_init (%.loc20_38.3, %.loc20_38.5), %return [template = constants.%.7]
+// CHECK:STDOUT:   %.loc20_38.7: init C = converted %.loc20_38.1, %.loc20_38.6 [template = constants.%.7]
 // CHECK:STDOUT:   assign %return, %.loc20_38.7
 // CHECK:STDOUT:   %c.ref: ref C = name_ref c, %c
 // CHECK:STDOUT:   return <error>

+ 7 - 6
toolchain/check/testdata/return/returned_var.carbon

@@ -28,7 +28,8 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %.3: type = ptr_type {.a: i32, .b: i32} [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.6: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.6: C = struct_value (%.4, %.5) [template]
+// CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -57,11 +58,11 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %.loc13_42: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc13_43.1: {.a: i32, .b: i32} = struct_literal (%.loc13_34, %.loc13_42)
 // CHECK:STDOUT:   %.loc13_43.2: ref i32 = class_element_access %return, element0
-// CHECK:STDOUT:   %.loc13_43.3: init i32 = initialize_from %.loc13_34 to %.loc13_43.2
+// CHECK:STDOUT:   %.loc13_43.3: init i32 = initialize_from %.loc13_34 to %.loc13_43.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc13_43.4: ref i32 = class_element_access %return, element1
-// CHECK:STDOUT:   %.loc13_43.5: init i32 = initialize_from %.loc13_42 to %.loc13_43.4
-// CHECK:STDOUT:   %.loc13_43.6: init C = class_init (%.loc13_43.3, %.loc13_43.5), %return
-// CHECK:STDOUT:   %.loc13_43.7: init C = converted %.loc13_43.1, %.loc13_43.6
+// CHECK:STDOUT:   %.loc13_43.5: init i32 = initialize_from %.loc13_42 to %.loc13_43.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc13_43.6: init C = class_init (%.loc13_43.3, %.loc13_43.5), %return [template = constants.%.6]
+// CHECK:STDOUT:   %.loc13_43.7: init C = converted %.loc13_43.1, %.loc13_43.6 [template = constants.%.6]
 // CHECK:STDOUT:   assign %return, %.loc13_43.7
 // CHECK:STDOUT:   return %result
 // CHECK:STDOUT: }
@@ -70,7 +71,7 @@ fn G() -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %result.var: ref i32 = var result
 // CHECK:STDOUT:   %result: ref i32 = bind_name result, %result.var
-// CHECK:STDOUT:   %.loc18_30: i32 = int_literal 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc18_30: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   assign %result.var, %.loc18_30
 // CHECK:STDOUT:   %.loc18_16: i32 = bind_value %result
 // CHECK:STDOUT:   return %.loc18_16

+ 5 - 4
toolchain/check/testdata/return/tuple.carbon

@@ -17,6 +17,7 @@ fn Main() -> (i32, i32) {
 // CHECK:STDOUT:   %.3: type = ptr_type (i32, i32) [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 15 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 35 [template]
+// CHECK:STDOUT:   %.6: (i32, i32) = tuple_value (%.4, %.5) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -30,11 +31,11 @@ fn Main() -> (i32, i32) {
 // CHECK:STDOUT:   %.loc9_15: i32 = int_literal 35 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc9_17.1: (i32, i32) = tuple_literal (%.loc9_11, %.loc9_15)
 // CHECK:STDOUT:   %.loc9_17.2: ref i32 = tuple_access %return, element0
-// CHECK:STDOUT:   %.loc9_17.3: init i32 = initialize_from %.loc9_11 to %.loc9_17.2
+// CHECK:STDOUT:   %.loc9_17.3: init i32 = initialize_from %.loc9_11 to %.loc9_17.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc9_17.4: ref i32 = tuple_access %return, element1
-// CHECK:STDOUT:   %.loc9_17.5: init i32 = initialize_from %.loc9_15 to %.loc9_17.4
-// CHECK:STDOUT:   %.loc9_17.6: init (i32, i32) = tuple_init (%.loc9_17.3, %.loc9_17.5) to %return
-// CHECK:STDOUT:   %.loc9_17.7: init (i32, i32) = converted %.loc9_17.1, %.loc9_17.6
+// CHECK:STDOUT:   %.loc9_17.5: init i32 = initialize_from %.loc9_15 to %.loc9_17.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc9_17.6: init (i32, i32) = tuple_init (%.loc9_17.3, %.loc9_17.5) to %return [template = constants.%.6]
+// CHECK:STDOUT:   %.loc9_17.7: init (i32, i32) = converted %.loc9_17.1, %.loc9_17.6 [template = constants.%.6]
 // CHECK:STDOUT:   return %.loc9_17.7
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 5 - 4
toolchain/check/testdata/struct/empty.carbon

@@ -12,6 +12,7 @@ var y: {} = x;
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %.1: type = struct_type {} [template]
 // CHECK:STDOUT:   %.2: type = tuple_type () [template]
+// CHECK:STDOUT:   %.3: {} = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -21,16 +22,16 @@ var y: {} = x;
 // CHECK:STDOUT:   %x.var: ref {} = var x
 // CHECK:STDOUT:   %x: ref {} = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_14.1: {} = struct_literal ()
-// CHECK:STDOUT:   %.loc7_14.2: init {} = struct_init () to %x.var
-// CHECK:STDOUT:   %.loc7_14.3: init {} = converted %.loc7_14.1, %.loc7_14.2
+// CHECK:STDOUT:   %.loc7_14.2: init {} = struct_init () to %x.var [template = constants.%.3]
+// CHECK:STDOUT:   %.loc7_14.3: init {} = converted %.loc7_14.1, %.loc7_14.2 [template = constants.%.3]
 // CHECK:STDOUT:   assign %x.var, %.loc7_14.3
 // CHECK:STDOUT:   %.loc8_9.1: {} = struct_literal ()
 // CHECK:STDOUT:   %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1]
 // CHECK:STDOUT:   %y.var: ref {} = var y
 // CHECK:STDOUT:   %y: ref {} = bind_name y, %y.var
 // CHECK:STDOUT:   %x.ref: ref {} = name_ref x, %x
-// CHECK:STDOUT:   %.loc8_13.1: init {} = struct_init () to %y.var
-// CHECK:STDOUT:   %.loc8_13.2: init {} = converted %x.ref, %.loc8_13.1
+// CHECK:STDOUT:   %.loc8_13.1: init {} = struct_init () to %y.var [template = constants.%.3]
+// CHECK:STDOUT:   %.loc8_13.2: init {} = converted %x.ref, %.loc8_13.1 [template = constants.%.3]
 // CHECK:STDOUT:   assign %y.var, %.loc8_13.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 3 - 2
toolchain/check/testdata/struct/fail_member_access_type.carbon

@@ -15,6 +15,7 @@ var y: i32 = x.b;
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %.1: type = struct_type {.a: f64} [template]
 // CHECK:STDOUT:   %.2: f64 = real_literal 40e-1 [template]
+// CHECK:STDOUT:   %.3: {.a: f64} = struct_value (%.2) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -24,8 +25,8 @@ var y: i32 = x.b;
 // CHECK:STDOUT:   %x: ref {.a: f64} = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_26: f64 = real_literal 40e-1 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc7_29.1: {.a: f64} = struct_literal (%.loc7_26)
-// CHECK:STDOUT:   %.loc7_29.2: init {.a: f64} = struct_init (%.loc7_26) to %x.var
-// CHECK:STDOUT:   %.loc7_29.3: init {.a: f64} = converted %.loc7_29.1, %.loc7_29.2
+// CHECK:STDOUT:   %.loc7_29.2: init {.a: f64} = struct_init (%.loc7_26) to %x.var [template = constants.%.3]
+// CHECK:STDOUT:   %.loc7_29.3: init {.a: f64} = converted %.loc7_29.1, %.loc7_29.2 [template = constants.%.3]
 // CHECK:STDOUT:   assign %x.var, %.loc7_29.3
 // CHECK:STDOUT:   %y.var: ref i32 = var y
 // CHECK:STDOUT:   %y: ref i32 = bind_name y, %y.var

+ 3 - 2
toolchain/check/testdata/struct/fail_non_member_access.carbon

@@ -15,6 +15,7 @@ var y: i32 = x.b;
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %.1: type = struct_type {.a: i32} [template]
 // CHECK:STDOUT:   %.2: i32 = int_literal 4 [template]
+// CHECK:STDOUT:   %.3: {.a: i32} = struct_value (%.2) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -24,8 +25,8 @@ var y: i32 = x.b;
 // CHECK:STDOUT:   %x: ref {.a: i32} = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_26: i32 = int_literal 4 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc7_27.1: {.a: i32} = struct_literal (%.loc7_26)
-// CHECK:STDOUT:   %.loc7_27.2: init {.a: i32} = struct_init (%.loc7_26) to %x.var
-// CHECK:STDOUT:   %.loc7_27.3: init {.a: i32} = converted %.loc7_27.1, %.loc7_27.2
+// CHECK:STDOUT:   %.loc7_27.2: init {.a: i32} = struct_init (%.loc7_26) to %x.var [template = constants.%.3]
+// CHECK:STDOUT:   %.loc7_27.3: init {.a: i32} = converted %.loc7_27.1, %.loc7_27.2 [template = constants.%.3]
 // CHECK:STDOUT:   assign %x.var, %.loc7_27.3
 // CHECK:STDOUT:   %y.var: ref i32 = var y
 // CHECK:STDOUT:   %y: ref i32 = bind_name y, %y.var

+ 5 - 4
toolchain/check/testdata/struct/member_access.carbon

@@ -15,6 +15,7 @@ var z: i32 = y;
 // CHECK:STDOUT:   %.2: type = ptr_type {.a: f64, .b: i32} [template]
 // CHECK:STDOUT:   %.3: f64 = real_literal 0e-1 [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.5: {.a: f64, .b: i32} = struct_value (%.3, %.4) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -26,11 +27,11 @@ var z: i32 = y;
 // CHECK:STDOUT:   %.loc7_45: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_46.1: {.a: f64, .b: i32} = struct_literal (%.loc7_35, %.loc7_45)
 // CHECK:STDOUT:   %.loc7_46.2: ref f64 = struct_access %x.var, element0
-// CHECK:STDOUT:   %.loc7_46.3: init f64 = initialize_from %.loc7_35 to %.loc7_46.2
+// CHECK:STDOUT:   %.loc7_46.3: init f64 = initialize_from %.loc7_35 to %.loc7_46.2 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc7_46.4: ref i32 = struct_access %x.var, element1
-// CHECK:STDOUT:   %.loc7_46.5: init i32 = initialize_from %.loc7_45 to %.loc7_46.4
-// CHECK:STDOUT:   %.loc7_46.6: init {.a: f64, .b: i32} = struct_init (%.loc7_46.3, %.loc7_46.5) to %x.var
-// CHECK:STDOUT:   %.loc7_46.7: init {.a: f64, .b: i32} = converted %.loc7_46.1, %.loc7_46.6
+// CHECK:STDOUT:   %.loc7_46.5: init i32 = initialize_from %.loc7_45 to %.loc7_46.4 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc7_46.6: init {.a: f64, .b: i32} = struct_init (%.loc7_46.3, %.loc7_46.5) to %x.var [template = constants.%.5]
+// CHECK:STDOUT:   %.loc7_46.7: init {.a: f64, .b: i32} = converted %.loc7_46.1, %.loc7_46.6 [template = constants.%.5]
 // CHECK:STDOUT:   assign %x.var, %.loc7_46.7
 // CHECK:STDOUT:   %y.var: ref i32 = var y
 // CHECK:STDOUT:   %y: ref i32 = bind_name y, %y.var

+ 3 - 2
toolchain/check/testdata/struct/one_entry.carbon

@@ -12,6 +12,7 @@ var y: {.a: i32} = x;
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %.1: type = struct_type {.a: i32} [template]
 // CHECK:STDOUT:   %.2: i32 = int_literal 4 [template]
+// CHECK:STDOUT:   %.3: {.a: i32} = struct_value (%.2) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -21,8 +22,8 @@ var y: {.a: i32} = x;
 // CHECK:STDOUT:   %x: ref {.a: i32} = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_26: i32 = int_literal 4 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc7_27.1: {.a: i32} = struct_literal (%.loc7_26)
-// CHECK:STDOUT:   %.loc7_27.2: init {.a: i32} = struct_init (%.loc7_26) to %x.var
-// CHECK:STDOUT:   %.loc7_27.3: init {.a: i32} = converted %.loc7_27.1, %.loc7_27.2
+// CHECK:STDOUT:   %.loc7_27.2: init {.a: i32} = struct_init (%.loc7_26) to %x.var [template = constants.%.3]
+// CHECK:STDOUT:   %.loc7_27.3: init {.a: i32} = converted %.loc7_27.1, %.loc7_27.2 [template = constants.%.3]
 // CHECK:STDOUT:   assign %x.var, %.loc7_27.3
 // CHECK:STDOUT:   %.loc8_16: type = struct_type {.a: i32} [template = constants.%.1]
 // CHECK:STDOUT:   %y.var: ref {.a: i32} = var y

+ 8 - 6
toolchain/check/testdata/struct/tuple_as_element.carbon

@@ -16,6 +16,8 @@ var y: {.a: i32, .b: (i32,)} = x;
 // CHECK:STDOUT:   %.4: type = ptr_type {.a: i32, .b: (i32,)} [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.7: (i32,) = tuple_value (%.6) [template]
+// CHECK:STDOUT:   %.8: {.a: i32, .b: (i32,)} = struct_value (%.5, %.7) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -30,13 +32,13 @@ var y: {.a: i32, .b: (i32,)} = x;
 // CHECK:STDOUT:   %.loc7_49.1: (i32,) = tuple_literal (%.loc7_47)
 // CHECK:STDOUT:   %.loc7_50.1: {.a: i32, .b: (i32,)} = struct_literal (%.loc7_38, %.loc7_49.1)
 // CHECK:STDOUT:   %.loc7_50.2: ref i32 = struct_access %x.var, element0
-// CHECK:STDOUT:   %.loc7_50.3: init i32 = initialize_from %.loc7_38 to %.loc7_50.2
+// CHECK:STDOUT:   %.loc7_50.3: init i32 = initialize_from %.loc7_38 to %.loc7_50.2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_50.4: ref (i32,) = struct_access %x.var, element1
-// CHECK:STDOUT:   %.loc7_49.2: init (i32,) = tuple_init (%.loc7_47) to %.loc7_50.4
-// CHECK:STDOUT:   %.loc7_49.3: init (i32,) = converted %.loc7_49.1, %.loc7_49.2
-// CHECK:STDOUT:   %.loc7_50.5: init (i32,) = initialize_from %.loc7_49.3 to %.loc7_50.4
-// CHECK:STDOUT:   %.loc7_50.6: init {.a: i32, .b: (i32,)} = struct_init (%.loc7_50.3, %.loc7_50.5) to %x.var
-// CHECK:STDOUT:   %.loc7_50.7: init {.a: i32, .b: (i32,)} = converted %.loc7_50.1, %.loc7_50.6
+// CHECK:STDOUT:   %.loc7_49.2: init (i32,) = tuple_init (%.loc7_47) to %.loc7_50.4 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc7_49.3: init (i32,) = converted %.loc7_49.1, %.loc7_49.2 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc7_50.5: init (i32,) = initialize_from %.loc7_49.3 to %.loc7_50.4 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc7_50.6: init {.a: i32, .b: (i32,)} = struct_init (%.loc7_50.3, %.loc7_50.5) to %x.var [template = constants.%.8]
+// CHECK:STDOUT:   %.loc7_50.7: init {.a: i32, .b: (i32,)} = converted %.loc7_50.1, %.loc7_50.6 [template = constants.%.8]
 // CHECK:STDOUT:   assign %x.var, %.loc7_50.7
 // CHECK:STDOUT:   %.loc8_27.1: (type,) = tuple_literal (i32)
 // CHECK:STDOUT:   %.loc8_27.2: type = converted %.loc8_27.1, constants.%.2 [template = constants.%.2]

+ 4 - 4
toolchain/check/testdata/struct/two_entries.carbon

@@ -39,11 +39,11 @@ var y: {.a: i32, .b: i32} = x;
 // CHECK:STDOUT:   %.loc10_43: i32 = int_literal 2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc10_44.1: {.a: i32, .b: i32} = struct_literal (%.loc10_35, %.loc10_43)
 // CHECK:STDOUT:   %.loc10_44.2: ref i32 = struct_access %x.var, element0
-// CHECK:STDOUT:   %.loc10_44.3: init i32 = initialize_from %.loc10_35 to %.loc10_44.2
+// CHECK:STDOUT:   %.loc10_44.3: init i32 = initialize_from %.loc10_35 to %.loc10_44.2 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc10_44.4: ref i32 = struct_access %x.var, element1
-// CHECK:STDOUT:   %.loc10_44.5: init i32 = initialize_from %.loc10_43 to %.loc10_44.4
-// CHECK:STDOUT:   %.loc10_44.6: init {.a: i32, .b: i32} = struct_init (%.loc10_44.3, %.loc10_44.5) to %x.var
-// CHECK:STDOUT:   %.loc10_44.7: init {.a: i32, .b: i32} = converted %.loc10_44.1, %.loc10_44.6
+// CHECK:STDOUT:   %.loc10_44.5: init i32 = initialize_from %.loc10_43 to %.loc10_44.4 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc10_44.6: init {.a: i32, .b: i32} = struct_init (%.loc10_44.3, %.loc10_44.5) to %x.var [template = constants.%.5]
+// CHECK:STDOUT:   %.loc10_44.7: init {.a: i32, .b: i32} = converted %.loc10_44.1, %.loc10_44.6 [template = constants.%.5]
 // CHECK:STDOUT:   assign %x.var, %.loc10_44.7
 // CHECK:STDOUT:   %.loc11_25: type = struct_type {.a: i32, .b: i32} [template = constants.%.1]
 // CHECK:STDOUT:   %y.var: ref {.a: i32, .b: i32} = var y

+ 5 - 4
toolchain/check/testdata/tuples/empty.carbon

@@ -11,6 +11,7 @@ var y: () = x;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %.1: type = tuple_type () [template]
+// CHECK:STDOUT:   %.2: () = tuple_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -20,16 +21,16 @@ var y: () = x;
 // CHECK:STDOUT:   %x.var: ref () = var x
 // CHECK:STDOUT:   %x: ref () = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_14.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc7_14.2: init () = tuple_init () to %x.var
-// CHECK:STDOUT:   %.loc7_14.3: init () = converted %.loc7_14.1, %.loc7_14.2
+// CHECK:STDOUT:   %.loc7_14.2: init () = tuple_init () to %x.var [template = constants.%.2]
+// CHECK:STDOUT:   %.loc7_14.3: init () = converted %.loc7_14.1, %.loc7_14.2 [template = constants.%.2]
 // CHECK:STDOUT:   assign %x.var, %.loc7_14.3
 // CHECK:STDOUT:   %.loc8_9.1: () = tuple_literal ()
 // CHECK:STDOUT:   %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1]
 // CHECK:STDOUT:   %y.var: ref () = var y
 // CHECK:STDOUT:   %y: ref () = bind_name y, %y.var
 // CHECK:STDOUT:   %x.ref: ref () = name_ref x, %x
-// CHECK:STDOUT:   %.loc8_13.1: init () = tuple_init () to %y.var
-// CHECK:STDOUT:   %.loc8_13.2: init () = converted %x.ref, %.loc8_13.1
+// CHECK:STDOUT:   %.loc8_13.1: init () = tuple_init () to %y.var [template = constants.%.2]
+// CHECK:STDOUT:   %.loc8_13.2: init () = converted %x.ref, %.loc8_13.1 [template = constants.%.2]
 // CHECK:STDOUT:   assign %y.var, %.loc8_13.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/tuples/fail_element_type_mismatch.carbon

@@ -30,7 +30,7 @@ var x: (i32, i32) = (2, 65.89);
 // CHECK:STDOUT:   %.loc10_25: f64 = real_literal 6589e-2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc10_30.1: (i32, f64) = tuple_literal (%.loc10_22, %.loc10_25)
 // CHECK:STDOUT:   %.loc10_30.2: ref i32 = tuple_access %x.var, element0
-// CHECK:STDOUT:   %.loc10_30.3: init i32 = initialize_from %.loc10_22 to %.loc10_30.2
+// CHECK:STDOUT:   %.loc10_30.3: init i32 = initialize_from %.loc10_22 to %.loc10_30.2 [template = constants.%.4]
 // CHECK:STDOUT:   assign %x.var, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 9 - 7
toolchain/check/testdata/tuples/nested_tuple.carbon

@@ -19,6 +19,8 @@ var x: ((i32, i32), i32) = ((12, 76), 6);
 // CHECK:STDOUT:   %.8: i32 = int_literal 12 [template]
 // CHECK:STDOUT:   %.9: i32 = int_literal 76 [template]
 // CHECK:STDOUT:   %.10: i32 = int_literal 6 [template]
+// CHECK:STDOUT:   %.11: (i32, i32) = tuple_value (%.8, %.9) [template]
+// CHECK:STDOUT:   %.12: ((i32, i32), i32) = tuple_value (%.11, %.10) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -36,15 +38,15 @@ var x: ((i32, i32), i32) = ((12, 76), 6);
 // CHECK:STDOUT:   %.loc7_40.1: ((i32, i32), i32) = tuple_literal (%.loc7_36.1, %.loc7_39)
 // CHECK:STDOUT:   %.loc7_40.2: ref (i32, i32) = tuple_access %x.var, element0
 // CHECK:STDOUT:   %.loc7_36.2: ref i32 = tuple_access %.loc7_40.2, element0
-// CHECK:STDOUT:   %.loc7_36.3: init i32 = initialize_from %.loc7_30 to %.loc7_36.2
+// CHECK:STDOUT:   %.loc7_36.3: init i32 = initialize_from %.loc7_30 to %.loc7_36.2 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc7_36.4: ref i32 = tuple_access %.loc7_40.2, element1
-// CHECK:STDOUT:   %.loc7_36.5: init i32 = initialize_from %.loc7_34 to %.loc7_36.4
-// CHECK:STDOUT:   %.loc7_36.6: init (i32, i32) = tuple_init (%.loc7_36.3, %.loc7_36.5) to %.loc7_40.2
-// CHECK:STDOUT:   %.loc7_36.7: init (i32, i32) = converted %.loc7_36.1, %.loc7_36.6
+// CHECK:STDOUT:   %.loc7_36.5: init i32 = initialize_from %.loc7_34 to %.loc7_36.4 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc7_36.6: init (i32, i32) = tuple_init (%.loc7_36.3, %.loc7_36.5) to %.loc7_40.2 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc7_36.7: init (i32, i32) = converted %.loc7_36.1, %.loc7_36.6 [template = constants.%.11]
 // CHECK:STDOUT:   %.loc7_40.3: ref i32 = tuple_access %x.var, element1
-// CHECK:STDOUT:   %.loc7_40.4: init i32 = initialize_from %.loc7_39 to %.loc7_40.3
-// CHECK:STDOUT:   %.loc7_40.5: init ((i32, i32), i32) = tuple_init (%.loc7_36.7, %.loc7_40.4) to %x.var
-// CHECK:STDOUT:   %.loc7_40.6: init ((i32, i32), i32) = converted %.loc7_40.1, %.loc7_40.5
+// CHECK:STDOUT:   %.loc7_40.4: init i32 = initialize_from %.loc7_39 to %.loc7_40.3 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc7_40.5: init ((i32, i32), i32) = tuple_init (%.loc7_36.7, %.loc7_40.4) to %x.var [template = constants.%.12]
+// CHECK:STDOUT:   %.loc7_40.6: init ((i32, i32), i32) = converted %.loc7_40.1, %.loc7_40.5 [template = constants.%.12]
 // CHECK:STDOUT:   assign %x.var, %.loc7_40.6
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/tuples/nested_tuple_in_place.carbon

@@ -79,9 +79,9 @@ fn H() {
 // CHECK:STDOUT:   %.loc14_49: i32 = int_literal 2 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc14_50.2: (i32, (i32, i32, i32), i32) = tuple_literal (%.loc14_41, %.loc14_45, %.loc14_49)
 // CHECK:STDOUT:   %.loc14_50.3: ref i32 = tuple_access %v.var, element0
-// CHECK:STDOUT:   %.loc14_50.4: init i32 = initialize_from %.loc14_41 to %.loc14_50.3
+// CHECK:STDOUT:   %.loc14_50.4: init i32 = initialize_from %.loc14_41 to %.loc14_50.3 [template = constants.%.12]
 // CHECK:STDOUT:   %.loc14_50.5: ref i32 = tuple_access %v.var, element2
-// CHECK:STDOUT:   %.loc14_50.6: init i32 = initialize_from %.loc14_49 to %.loc14_50.5
+// CHECK:STDOUT:   %.loc14_50.6: init i32 = initialize_from %.loc14_49 to %.loc14_50.5 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc14_50.7: init (i32, (i32, i32, i32), i32) = tuple_init (%.loc14_50.4, %.loc14_45, %.loc14_50.6) to %v.var
 // CHECK:STDOUT:   %.loc14_50.8: init (i32, (i32, i32, i32), i32) = converted %.loc14_50.2, %.loc14_50.7
 // CHECK:STDOUT:   assign %v.var, %.loc14_50.8

+ 3 - 2
toolchain/check/testdata/tuples/one_element.carbon

@@ -13,6 +13,7 @@ var y: (i32,) = x;
 // CHECK:STDOUT:   %.1: type = tuple_type (type) [template]
 // CHECK:STDOUT:   %.2: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.3: i32 = int_literal 4 [template]
+// CHECK:STDOUT:   %.4: (i32,) = tuple_value (%.3) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -23,8 +24,8 @@ var y: (i32,) = x;
 // CHECK:STDOUT:   %x: ref (i32,) = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_18: i32 = int_literal 4 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc7_20.1: (i32,) = tuple_literal (%.loc7_18)
-// CHECK:STDOUT:   %.loc7_20.2: init (i32,) = tuple_init (%.loc7_18) to %x.var
-// CHECK:STDOUT:   %.loc7_20.3: init (i32,) = converted %.loc7_20.1, %.loc7_20.2
+// CHECK:STDOUT:   %.loc7_20.2: init (i32,) = tuple_init (%.loc7_18) to %x.var [template = constants.%.4]
+// CHECK:STDOUT:   %.loc7_20.3: init (i32,) = converted %.loc7_20.1, %.loc7_20.2 [template = constants.%.4]
 // CHECK:STDOUT:   assign %x.var, %.loc7_20.3
 // CHECK:STDOUT:   %.loc8_13.1: (type,) = tuple_literal (i32)
 // CHECK:STDOUT:   %.loc8_13.2: type = converted %.loc8_13.1, constants.%.2 [template = constants.%.2]

+ 4 - 4
toolchain/check/testdata/tuples/two_elements.carbon

@@ -43,11 +43,11 @@ var y: (i32, i32) = x;
 // CHECK:STDOUT:   %.loc10_25: i32 = int_literal 102 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc10_28.1: (i32, i32) = tuple_literal (%.loc10_22, %.loc10_25)
 // CHECK:STDOUT:   %.loc10_28.2: ref i32 = tuple_access %x.var, element0
-// CHECK:STDOUT:   %.loc10_28.3: init i32 = initialize_from %.loc10_22 to %.loc10_28.2
+// CHECK:STDOUT:   %.loc10_28.3: init i32 = initialize_from %.loc10_22 to %.loc10_28.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc10_28.4: ref i32 = tuple_access %x.var, element1
-// CHECK:STDOUT:   %.loc10_28.5: init i32 = initialize_from %.loc10_25 to %.loc10_28.4
-// CHECK:STDOUT:   %.loc10_28.6: init (i32, i32) = tuple_init (%.loc10_28.3, %.loc10_28.5) to %x.var
-// CHECK:STDOUT:   %.loc10_28.7: init (i32, i32) = converted %.loc10_28.1, %.loc10_28.6
+// CHECK:STDOUT:   %.loc10_28.5: init i32 = initialize_from %.loc10_25 to %.loc10_28.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc10_28.6: init (i32, i32) = tuple_init (%.loc10_28.3, %.loc10_28.5) to %x.var [template = constants.%.6]
+// CHECK:STDOUT:   %.loc10_28.7: init (i32, i32) = converted %.loc10_28.1, %.loc10_28.6 [template = constants.%.6]
 // CHECK:STDOUT:   assign %x.var, %.loc10_28.7
 // CHECK:STDOUT:   %.loc11_17.1: (type, type) = tuple_literal (i32, i32)
 // CHECK:STDOUT:   %.loc11_17.2: type = converted %.loc11_17.1, constants.%.2 [template = constants.%.2]

+ 1 - 0
toolchain/sem_ir/inst_profile.cpp

@@ -112,6 +112,7 @@ auto ProfileConstant(llvm::FoldingSetNodeID& id, const File& sem_ir, Inst inst)
   };
 
   inst.kind().Profile(id);
+  id.AddInteger(inst.type_id().index);
   ProfileFunctions[inst.kind().AsInt()](id, sem_ir, inst.arg0(), inst.arg1());
 }
 

+ 22 - 0
toolchain/sem_ir/typed_insts.h

@@ -73,6 +73,28 @@ struct ArrayIndex {
   InstId index_id;
 };
 
+// Common representation for all kinds of aggregate initialization.
+struct AnyAggregateInit {
+  static constexpr InstKind Kinds[] = {InstKind::ArrayInit, InstKind::ClassInit,
+                                       InstKind::StructInit,
+                                       InstKind::TupleInit};
+
+  InstKind kind;
+  TypeId type_id;
+  InstBlockId elements_id;
+  InstId dest_id;
+};
+
+// Common representation for all kinds of aggregate value.
+struct AnyAggregateValue {
+  static constexpr InstKind Kinds[] = {InstKind::StructValue,
+                                       InstKind::TupleValue};
+
+  InstKind kind;
+  TypeId type_id;
+  InstBlockId elements_id;
+};
+
 // Initializes an array from a tuple. `tuple_id` is the source tuple
 // expression. `inits_id` contains one initializer per array element.
 // `dest_id` is the destination array object for the initialization.