Jelajahi Sumber

Make `Core.Float` a class. Add missing builtins for float support. (#5932)

Add missing builtins for float compound assignment, for building a
FloatType, and for converting a float literal to FloatType. Switch
`Core.Float` to being a class and add impls for the various
floating-point operators.

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
Richard Smith 8 bulan lalu
induk
melakukan
694c00c7eb
66 mengubah file dengan 2158 tambahan dan 583 penghapusan
  1. 1 2
      core/prelude/types.carbon
  2. 89 0
      core/prelude/types/float.carbon
  3. 7 0
      core/prelude/types/float_literal.carbon
  4. 30 8
      toolchain/check/eval.cpp
  5. 0 5
      toolchain/check/handle_literal.cpp
  6. 16 0
      toolchain/check/import_ref.cpp
  7. 12 12
      toolchain/check/testdata/basics/numeric_literals.carbon
  8. 59 14
      toolchain/check/testdata/basics/type_literals.carbon
  9. 8 6
      toolchain/check/testdata/builtins/float/add.carbon
  10. 44 0
      toolchain/check/testdata/builtins/float/add_assign.carbon
  11. 880 0
      toolchain/check/testdata/builtins/float/convert_checked.carbon
  12. 8 6
      toolchain/check/testdata/builtins/float/div.carbon
  13. 44 0
      toolchain/check/testdata/builtins/float/div_assign.carbon
  14. 5 3
      toolchain/check/testdata/builtins/float/eq.carbon
  15. 5 3
      toolchain/check/testdata/builtins/float/greater.carbon
  16. 5 3
      toolchain/check/testdata/builtins/float/greater_eq.carbon
  17. 5 3
      toolchain/check/testdata/builtins/float/less.carbon
  18. 5 3
      toolchain/check/testdata/builtins/float/less_eq.carbon
  19. 1 6
      toolchain/check/testdata/builtins/float/make_type.carbon
  20. 8 6
      toolchain/check/testdata/builtins/float/mul.carbon
  21. 44 0
      toolchain/check/testdata/builtins/float/mul_assign.carbon
  22. 7 5
      toolchain/check/testdata/builtins/float/negate.carbon
  23. 5 3
      toolchain/check/testdata/builtins/float/neq.carbon
  24. 8 6
      toolchain/check/testdata/builtins/float/sub.carbon
  25. 44 0
      toolchain/check/testdata/builtins/float/sub_assign.carbon
  26. 63 0
      toolchain/check/testdata/builtins/float_literal/make_type.carbon
  27. 69 53
      toolchain/check/testdata/deduce/int_float.carbon
  28. 4 4
      toolchain/check/testdata/function/call/fail_param_type.carbon
  29. 43 22
      toolchain/check/testdata/function/call/fail_return_type_mismatch.carbon
  30. 7 8
      toolchain/check/testdata/impl/fail_impl_bad_interface.carbon
  31. 4 4
      toolchain/check/testdata/index/fail_array_non_int_indexing.carbon
  32. 45 29
      toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon
  33. 4 4
      toolchain/check/testdata/interop/cpp/function/param_unsupported.carbon
  34. 10 16
      toolchain/check/testdata/operators/builtin/fail_and_or_not_in_function.carbon
  35. 4 4
      toolchain/check/testdata/operators/builtin/fail_type_mismatch_assignment.carbon
  36. 3 3
      toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon
  37. 4 4
      toolchain/check/testdata/pointer/fail_address_of_value.carbon
  38. 49 25
      toolchain/check/testdata/return/fail_returned_var_type.carbon
  39. 4 4
      toolchain/check/testdata/return/fail_type_mismatch.carbon
  40. 3 3
      toolchain/check/testdata/struct/fail_field_type_mismatch.carbon
  41. 46 21
      toolchain/check/testdata/struct/fail_member_access_type.carbon
  42. 58 39
      toolchain/check/testdata/struct/member_access.carbon
  43. 32 39
      toolchain/check/testdata/struct/reorder_fields.carbon
  44. 2 2
      toolchain/check/testdata/tuple/element_access.carbon
  45. 28 26
      toolchain/lower/handle_call.cpp
  46. 4 4
      toolchain/lower/testdata/array/base.carbon
  47. 8 8
      toolchain/lower/testdata/basics/numeric_literals.carbon
  48. 112 36
      toolchain/lower/testdata/builtins/float.carbon
  49. 8 6
      toolchain/lower/testdata/builtins/types.carbon
  50. 3 3
      toolchain/lower/testdata/function/generic/call.carbon
  51. 14 14
      toolchain/lower/testdata/function/generic/call_basic.carbon
  52. 9 9
      toolchain/lower/testdata/function/generic/call_deref_ptr.carbon
  53. 9 9
      toolchain/lower/testdata/function/generic/call_different_specific.carbon
  54. 4 4
      toolchain/lower/testdata/function/generic/call_recursive_basic.carbon
  55. 15 15
      toolchain/lower/testdata/function/generic/call_recursive_diamond.carbon
  56. 7 7
      toolchain/lower/testdata/function/generic/call_recursive_mutual.carbon
  57. 4 4
      toolchain/lower/testdata/function/generic/call_recursive_reorder_more.carbon
  58. 25 25
      toolchain/lower/testdata/function/generic/call_recursive_sccs_deep.carbon
  59. 9 9
      toolchain/lower/testdata/function/generic/call_specific_in_class.carbon
  60. 2 2
      toolchain/lower/testdata/struct/member_access.carbon
  61. 49 7
      toolchain/sem_ir/builtin_function_kind.cpp
  62. 10 0
      toolchain/sem_ir/builtin_function_kind.def
  63. 2 1
      toolchain/sem_ir/stringify.cpp
  64. 15 15
      toolchain/sem_ir/typed_insts.h
  65. 18 1
      toolchain/testing/testdata/min_prelude/parts/float.carbon
  66. 9 0
      toolchain/testing/testdata/min_prelude/parts/float_literal.carbon

+ 1 - 2
core/prelude/types.carbon

@@ -10,5 +10,4 @@ export import library "prelude/types/int";
 export import library "prelude/types/int_literal";
 export import library "prelude/types/optional";
 export import library "prelude/types/uint";
-
-fn Float(size: IntLiteral()) -> type = "float.make_type";
+export import library "prelude/types/float";

+ 89 - 0
core/prelude/types/float.carbon

@@ -0,0 +1,89 @@
+// 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
+
+package Core library "prelude/types/float";
+
+import library "prelude/destroy";
+import library "prelude/operators";
+import library "prelude/types/float_literal";
+import library "prelude/types/int_literal";
+
+private fn MakeFloat(size: IntLiteral()) -> type = "float.make_type";
+
+class Float(N:! IntLiteral()) {
+  adapt MakeFloat(N);
+}
+
+// Conversions.
+// TODO: Support mixed-size conversions.
+// TODO: Support int-to-float conversions.
+impl forall [N:! IntLiteral()] FloatLiteral() as ImplicitAs(Float(N)) {
+  fn Convert[self: Self]() -> Float(N) = "float.convert_checked";
+}
+
+// TODO: Remove this once ImplicitAs extends As.
+impl forall [N:! IntLiteral()] FloatLiteral() as As(Float(N)) {
+  fn Convert[self: Self]() -> Float(N) = "float.convert_checked";
+}
+
+// Comparisons.
+// TODO: Support mixed-type comparisons.
+final impl forall [N:! IntLiteral()] Float(N) as EqWith(Float(N)) {
+  fn Equal[self: Self](other: Float(N)) -> bool = "float.eq";
+  fn NotEqual[self: Self](other: Float(N)) -> bool = "float.neq";
+}
+
+final impl forall [N:! IntLiteral()] Float(N) as OrderedWith(Float(N)) {
+  fn Less[self: Self](other: Float(N)) -> bool = "float.less";
+  fn LessOrEquivalent[self: Self](other: Float(N)) -> bool = "float.less_eq";
+  fn Greater[self: Self](other: Float(N)) -> bool = "float.greater";
+  fn GreaterOrEquivalent[self: Self](other: Float(N)) -> bool = "float.greater_eq";
+}
+
+// Arithmetic.
+final impl forall [N:! IntLiteral()]
+    Float(N) as AddWith(Self) where .Result = Self {
+  fn Op[self: Self](other: Self) -> Self = "float.add";
+}
+
+final impl forall [N:! IntLiteral()]
+    Float(N) as DivWith(Self) where .Result = Self {
+  fn Op[self: Self](other: Self) -> Self = "float.div";
+}
+
+final impl forall [N:! IntLiteral()]
+    Float(N) as MulWith(Self) where .Result = Self {
+  fn Op[self: Self](other: Self) -> Self = "float.mul";
+}
+
+final impl forall [N:! IntLiteral()]
+    Float(N) as Negate where .Result = Self {
+  fn Op[self: Self]() -> Self = "float.negate";
+}
+
+final impl forall [N:! IntLiteral()]
+    Float(N) as SubWith(Self) where .Result = Self {
+  fn Op[self: Self](other: Self) -> Self = "float.sub";
+}
+
+// Compound assignments.
+final impl forall [N:! IntLiteral()]
+    Float(N) as AddAssignWith(Self) {
+  fn Op[addr self: Self*](other: Self) = "float.add_assign";
+}
+
+final impl forall [N:! IntLiteral()]
+    Float(N) as DivAssignWith(Self) {
+  fn Op[addr self: Self*](other: Self) = "float.div_assign";
+}
+
+final impl forall [N:! IntLiteral()]
+    Float(N) as MulAssignWith(Self) {
+  fn Op[addr self: Self*](other: Self) = "float.mul_assign";
+}
+
+final impl forall [N:! IntLiteral()]
+    Float(N) as SubAssignWith(Self) {
+  fn Op[addr self: Self*](other: Self) = "float.sub_assign";
+}

+ 7 - 0
core/prelude/types/float_literal.carbon

@@ -0,0 +1,7 @@
+// 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
+
+package Core library "prelude/types/float_literal";
+
+fn FloatLiteral() -> type = "float_literal.make_type";

+ 30 - 8
toolchain/check/eval.cpp

@@ -997,6 +997,20 @@ static auto MakeIntTypeResult(Context& context, SemIR::LocId loc_id,
   return MakeConstantResult(context, result, phase);
 }
 
+// Forms a constant float type as an evaluation result. Requires that width_id
+// is constant.
+static auto MakeFloatTypeResult(Context& context, SemIR::LocId loc_id,
+                                SemIR::InstId width_id, Phase phase)
+    -> SemIR::ConstantId {
+  auto result = SemIR::FloatType{
+      .type_id = GetSingletonType(context, SemIR::TypeType::TypeInstId),
+      .bit_width_id = width_id};
+  if (!ValidateFloatType(context, loc_id, result)) {
+    return SemIR::ErrorInst::ConstantId;
+  }
+  return MakeConstantResult(context, result, phase);
+}
+
 // Performs a conversion between integer types, truncating if the value doesn't
 // fit in the destination type.
 static auto PerformIntConvert(Context& context, SemIR::InstId arg_id,
@@ -1556,6 +1570,10 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context,
     case SemIR::BuiltinFunctionKind::PrintChar:
     case SemIR::BuiltinFunctionKind::PrintInt:
     case SemIR::BuiltinFunctionKind::ReadChar:
+    case SemIR::BuiltinFunctionKind::FloatAddAssign:
+    case SemIR::BuiltinFunctionKind::FloatSubAssign:
+    case SemIR::BuiltinFunctionKind::FloatMulAssign:
+    case SemIR::BuiltinFunctionKind::FloatDivAssign:
     case SemIR::BuiltinFunctionKind::IntSAddAssign:
     case SemIR::BuiltinFunctionKind::IntSSubAssign:
     case SemIR::BuiltinFunctionKind::IntSMulAssign:
@@ -1625,6 +1643,10 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context,
       return context.constant_values().Get(SemIR::CharLiteralType::TypeInstId);
     }
 
+    case SemIR::BuiltinFunctionKind::FloatLiteralMakeType: {
+      return context.constant_values().Get(SemIR::LegacyFloatType::TypeInstId);
+    }
+
     case SemIR::BuiltinFunctionKind::IntLiteralMakeType: {
       return context.constant_values().Get(SemIR::IntLiteralType::TypeInstId);
     }
@@ -1640,14 +1662,7 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context,
     }
 
     case SemIR::BuiltinFunctionKind::FloatMakeType: {
-      // TODO: Support a symbolic constant width.
-      if (phase != Phase::Concrete) {
-        break;
-      }
-      if (!ValidateFloatBitWidth(context, loc_id, arg_ids[0])) {
-        return SemIR::ErrorInst::ConstantId;
-      }
-      return context.constant_values().Get(SemIR::LegacyFloatType::TypeInstId);
+      return MakeFloatTypeResult(context, loc_id, arg_ids[0], phase);
     }
 
     case SemIR::BuiltinFunctionKind::BoolMakeType: {
@@ -1734,6 +1749,13 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context,
                                          arg_ids[1], call.type_id);
     }
 
+    // Floating-point conversions.
+    case SemIR::BuiltinFunctionKind::FloatConvertChecked: {
+      // TODO: Perform a conversion if necessary. For now, all FloatValues are
+      // represented as double-precision APFloats, so no conversion is needed.
+      return context.constant_values().Get(arg_ids[0]);
+    }
+
     // Unary float -> float operations.
     case SemIR::BuiltinFunctionKind::FloatNegate: {
       if (phase != Phase::Concrete) {

+ 0 - 5
toolchain/check/handle_literal.cpp

@@ -152,11 +152,6 @@ auto HandleParseNode(Context& context, Parse::UnsignedIntTypeLiteralId node_id)
 
 auto HandleParseNode(Context& context, Parse::FloatTypeLiteralId node_id)
     -> bool {
-  auto text =
-      context.tokens().GetTokenText(context.parse_tree().node_token(node_id));
-  if (text != "f64") {
-    return context.TODO(node_id, "Currently only f64 is allowed");
-  }
   auto tok_id = context.parse_tree().node_token(node_id);
   auto size_id = context.tokens().GetTypeLiteralSize(tok_id);
   auto type_inst_id =

+ 16 - 0
toolchain/check/import_ref.cpp

@@ -1828,6 +1828,19 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
        .index = inst.index});
 }
 
+static auto TryResolveTypedInst(ImportRefResolver& resolver,
+                                SemIR::FloatType inst) -> ResolveResult {
+  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);
+  auto bit_width_id = GetLocalConstantInstId(resolver, inst.bit_width_id);
+  if (resolver.HasNewWork()) {
+    return ResolveResult::Retry();
+  }
+
+  return ResolveAsDeduplicated<SemIR::FloatType>(
+      resolver,
+      {.type_id = SemIR::TypeType::TypeId, .bit_width_id = bit_width_id});
+}
+
 // Make a declaration of a function. This is done as a separate step from
 // importing the function declaration in order to resolve cycles.
 static auto MakeFunctionDecl(ImportContext& context,
@@ -3031,6 +3044,9 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
     case CARBON_KIND(SemIR::FieldDecl inst): {
       return TryResolveTypedInst(resolver, inst, inst_id);
     }
+    case CARBON_KIND(SemIR::FloatType inst): {
+      return TryResolveTypedInst(resolver, inst);
+    }
     case CARBON_KIND(SemIR::FunctionDecl inst): {
       return TryResolveTypedInst(resolver, inst, const_id);
     }

+ 12 - 12
toolchain/check/testdata/basics/numeric_literals.carbon

@@ -95,12 +95,12 @@ let e: f64 = 5.0e39999999999999999993;
 // CHECK:STDOUT:   %int_8.b85: Core.IntLiteral = int_value 8 [concrete]
 // CHECK:STDOUT:   %int_9.988: Core.IntLiteral = int_value 9 [concrete]
 // CHECK:STDOUT:   %int_2147483647.d89: Core.IntLiteral = int_value 2147483647 [concrete]
-// CHECK:STDOUT:   %float.2c5: f64 = float_value 0.90000000000000002 [concrete]
-// CHECK:STDOUT:   %float.613: f64 = float_value 8 [concrete]
-// CHECK:STDOUT:   %float.707: f64 = float_value 80 [concrete]
-// CHECK:STDOUT:   %float.213: f64 = float_value 1.0E+7 [concrete]
-// CHECK:STDOUT:   %float.577: f64 = float_value 1.0E+8 [concrete]
-// CHECK:STDOUT:   %float.ef9: f64 = float_value 1.0E-8 [concrete]
+// CHECK:STDOUT:   %float.8ca: Core.FloatLiteral = float_value 0.90000000000000002 [concrete]
+// CHECK:STDOUT:   %float.fde: Core.FloatLiteral = float_value 8 [concrete]
+// CHECK:STDOUT:   %float.7a6: Core.FloatLiteral = float_value 80 [concrete]
+// CHECK:STDOUT:   %float.23b: Core.FloatLiteral = float_value 1.0E+7 [concrete]
+// CHECK:STDOUT:   %float.b98: Core.FloatLiteral = float_value 1.0E+8 [concrete]
+// CHECK:STDOUT:   %float.34d: Core.FloatLiteral = float_value 1.0E-8 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -116,12 +116,12 @@ let e: f64 = 5.0e39999999999999999993;
 // CHECK:STDOUT:   %int_2147483647.loc13: Core.IntLiteral = int_value 2147483647 [concrete = constants.%int_2147483647.d89]
 // CHECK:STDOUT:   %int_2147483647.loc14: Core.IntLiteral = int_value 2147483647 [concrete = constants.%int_2147483647.d89]
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %float.loc19: f64 = float_value 0.90000000000000002 [concrete = constants.%float.2c5]
-// CHECK:STDOUT:   %float.loc20: f64 = float_value 8 [concrete = constants.%float.613]
-// CHECK:STDOUT:   %float.loc21: f64 = float_value 80 [concrete = constants.%float.707]
-// CHECK:STDOUT:   %float.loc22: f64 = float_value 1.0E+7 [concrete = constants.%float.213]
-// CHECK:STDOUT:   %float.loc23: f64 = float_value 1.0E+8 [concrete = constants.%float.577]
-// CHECK:STDOUT:   %float.loc24: f64 = float_value 1.0E-8 [concrete = constants.%float.ef9]
+// CHECK:STDOUT:   %float.loc19: Core.FloatLiteral = float_value 0.90000000000000002 [concrete = constants.%float.8ca]
+// CHECK:STDOUT:   %float.loc20: Core.FloatLiteral = float_value 8 [concrete = constants.%float.fde]
+// CHECK:STDOUT:   %float.loc21: Core.FloatLiteral = float_value 80 [concrete = constants.%float.7a6]
+// CHECK:STDOUT:   %float.loc22: Core.FloatLiteral = float_value 1.0E+7 [concrete = constants.%float.23b]
+// CHECK:STDOUT:   %float.loc23: Core.FloatLiteral = float_value 1.0E+8 [concrete = constants.%float.b98]
+// CHECK:STDOUT:   %float.loc24: Core.FloatLiteral = float_value 1.0E-8 [concrete = constants.%float.34d]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 59 - 14
toolchain/check/testdata/basics/type_literals.carbon

@@ -37,16 +37,33 @@ library "[[@TEST_NAME]]";
 var test_f64: f64;
 //@dump-sem-ir-end
 
-// --- fail_fN_todo_unsupported.carbon
+// --- fail_todo_fN_unsupported.carbon
 library "[[@TEST_NAME]]";
 
 // TODO: Some or all of these should eventually work.
-// CHECK:STDERR: fail_fN_todo_unsupported.carbon:[[@LINE+4]]:15: error: semantics TODO: `Currently only f64 is allowed` [SemanticsTodo]
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_fN_unsupported.carbon:[[@LINE+4]]:15: note: in `f16` used here [ResolvingSpecificHere]
 // CHECK:STDERR: var test_f16: f16;
 // CHECK:STDERR:               ^~~
 // CHECK:STDERR:
 var test_f16: f16;
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_fN_unsupported.carbon:[[@LINE+4]]:15: note: in `f32` used here [ResolvingSpecificHere]
+// CHECK:STDERR: var test_f32: f32;
+// CHECK:STDERR:               ^~~
+// CHECK:STDERR:
 var test_f32: f32;
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_fN_unsupported.carbon:[[@LINE+4]]:16: note: in `f128` used here [ResolvingSpecificHere]
+// CHECK:STDERR: var test_f128: f128;
+// CHECK:STDERR:                ^~~~
+// CHECK:STDERR:
 var test_f128: f128;
 
 // --- string.carbon
@@ -147,14 +164,45 @@ library "[[@TEST_NAME]]";
 // CHECK:STDERR:              ^~
 // CHECK:STDERR:
 var test_f0: f0;
-// CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:14: error: semantics TODO: `Currently only f64 is allowed` [SemanticsTodo]
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:14: note: in `f1` used here [ResolvingSpecificHere]
 // CHECK:STDERR: var test_f1: f1;
 // CHECK:STDERR:              ^~
 // CHECK:STDERR:
 var test_f1: f1;
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:15: note: in `f15` used here [ResolvingSpecificHere]
+// CHECK:STDERR: var test_f15: f15;
+// CHECK:STDERR:               ^~~
+// CHECK:STDERR:
 var test_f15: f15;
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:16: note: in `f100` used here [ResolvingSpecificHere]
+// CHECK:STDERR: var test_f100: f100;
+// CHECK:STDERR:                ^~~~
+// CHECK:STDERR:
 var test_f100: f100;
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:23: note: in `f1000000000` used here [ResolvingSpecificHere]
+// CHECK:STDERR: var test_f1000000000: f1000000000;
+// CHECK:STDERR:                       ^~~~~~~~~~~
+// CHECK:STDERR:
 var test_f1000000000: f1000000000;
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:26: note: in `f1000000000000` used here [ResolvingSpecificHere]
+// CHECK:STDERR: var test_f1000000000000: f1000000000000;
+// CHECK:STDERR:                          ^~~~~~~~~~~~~~
+// CHECK:STDERR:
 var test_f1000000000000: f1000000000000;
 
 // --- fail_non_type_as_type.carbon
@@ -300,9 +348,8 @@ var x: type = 42;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
-// CHECK:STDOUT:   %pattern_type.3de: type = pattern_type f64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -310,17 +357,15 @@ var x: type = 42;
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   name_binding_decl {
-// CHECK:STDOUT:     %test_f64.patt: %pattern_type.3de = binding_pattern test_f64 [concrete]
-// CHECK:STDOUT:     %test_f64.var_patt: %pattern_type.3de = var_pattern %test_f64.patt [concrete]
+// CHECK:STDOUT:     %test_f64.patt: %pattern_type.0ae = binding_pattern test_f64 [concrete]
+// CHECK:STDOUT:     %test_f64.var_patt: %pattern_type.0ae = var_pattern %test_f64.patt [concrete]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %test_f64.var: ref f64 = var %test_f64.var_patt [concrete]
-// CHECK:STDOUT:   %.loc4_15.1: type = splice_block %.loc4_15.3 [concrete = f64] {
+// CHECK:STDOUT:   %test_f64.var: ref %f64.d77 = var %test_f64.var_patt [concrete]
+// CHECK:STDOUT:   %.loc4: type = splice_block %f64 [concrete = constants.%f64.d77] {
 // CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:     %.loc4_15.2: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:     %.loc4_15.3: type = converted %Float.call, %.loc4_15.2 [concrete = f64]
+// CHECK:STDOUT:     %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %test_f64: ref f64 = bind_name test_f64, %test_f64.var [concrete = %test_f64.var]
+// CHECK:STDOUT:   %test_f64: ref %f64.d77 = bind_name test_f64, %test_f64.var [concrete = %test_f64.var]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- string.carbon

+ 8 - 6
toolchain/check/testdata/builtins/float/add.carbon

@@ -60,6 +60,8 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: --- float_add.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %Add.type: type = fn_type @Add [concrete]
 // CHECK:STDOUT:   %Add: %Add.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -67,14 +69,14 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> f64 {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> %f64.d77 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Add.ref: %Add.type = name_ref Add, file.%Add.decl [concrete = constants.%Add]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: f64 = name_ref b, %b
-// CHECK:STDOUT:   %Add.call: init f64 = call %Add.ref(%a.ref, %b.ref)
-// CHECK:STDOUT:   %.loc8_19.1: f64 = value_of_initializer %Add.call
-// CHECK:STDOUT:   %.loc8_19.2: f64 = converted %Add.call, %.loc8_19.1
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b
+// CHECK:STDOUT:   %Add.call: init %f64.d77 = call %Add.ref(%a.ref, %b.ref)
+// CHECK:STDOUT:   %.loc8_19.1: %f64.d77 = value_of_initializer %Add.call
+// CHECK:STDOUT:   %.loc8_19.2: %f64.d77 = converted %Add.call, %.loc8_19.1
 // CHECK:STDOUT:   return %.loc8_19.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 44 - 0
toolchain/check/testdata/builtins/float/add_assign.carbon

@@ -0,0 +1,44 @@
+// 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
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/add_assign.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/add_assign.carbon
+
+// --- call.carbon
+
+library "call";
+
+fn Builtin(a: f64*, b: f64) = "float.add_assign";
+
+fn Call(a: f64*, b: f64) {
+  Builtin(a, b);
+}
+
+// --- fail_bad_decl.carbon
+
+library "fail_bad_decl";
+
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.add_assign" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn NotPtr(a: f64, b: f64) = "float.add_assign";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn NotPtr(a: f64, b: f64) = "float.add_assign";
+
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+8]]:24: note: in `f32` used here [ResolvingSpecificHere]
+// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.add_assign";
+// CHECK:STDERR:                        ^~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.add_assign" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.add_assign";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn MixedTypes(a: f64*, b: f32) = "float.add_assign";

+ 880 - 0
toolchain/check/testdata/builtins/float/convert_checked.carbon

@@ -0,0 +1,880 @@
+// 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
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/convert_checked.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/convert_checked.carbon
+
+// --- literal.carbon
+
+library "[[@TEST_NAME]]";
+
+fn FloatLiteral() -> type = "float_literal.make_type";
+
+fn FloatLiteralToFloatLiteral(a: FloatLiteral()) -> FloatLiteral() =
+    "float.convert_checked";
+
+// --- identity_literal.carbon
+
+library "[[@TEST_NAME]]";
+import library "literal";
+
+//@dump-sem-ir-begin
+let f: FloatLiteral() = FloatLiteralToFloatLiteral(1.0);
+//@dump-sem-ir-end
+
+// --- f64.carbon
+
+library "[[@TEST_NAME]]";
+export import library "literal";
+
+fn Float64ToFloat64(a: f64) -> f64 = "float.convert_checked";
+fn Float64ToFloatLiteral(a: f64) -> FloatLiteral() = "float.convert_checked";
+fn FloatLiteralToFloat64(a: FloatLiteral()) -> f64 = "float.convert_checked";
+
+// --- fail_todo_f32.carbon
+
+library "[[@TEST_NAME]]";
+export import library "literal";
+
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+8]]:29: note: in `f32` used here [ResolvingSpecificHere]
+// CHECK:STDERR: fn Float32ToFloat32(a: f32) -> f32 = "float.convert_checked";
+// CHECK:STDERR:                             ^~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.convert_checked" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn Float32ToFloat32(a: f32) -> f32 = "float.convert_checked";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn Float32ToFloat32(a: f32) -> f32 = "float.convert_checked";
+// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.convert_checked" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn Float32ToFloatLiteral(a: f32) -> FloatLiteral() = "float.convert_checked";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn Float32ToFloatLiteral(a: f32) -> FloatLiteral() = "float.convert_checked";
+// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.convert_checked" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn FloatLiteralToFloat32(a: FloatLiteral()) -> f32 = "float.convert_checked";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn FloatLiteralToFloat32(a: FloatLiteral()) -> f32 = "float.convert_checked";
+
+// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.convert_checked" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn Float32ToFloat64(a: f32) -> f64 = "float.convert_checked";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn Float32ToFloat64(a: f32) -> f64 = "float.convert_checked";
+// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.convert_checked" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn Float64ToFloat32(a: f64) -> f32 = "float.convert_checked";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn Float64ToFloat32(a: f64) -> f32 = "float.convert_checked";
+
+// --- literal_f64.carbon
+
+library "[[@TEST_NAME]]";
+import library "f64";
+
+//@dump-sem-ir-begin
+let a: f64 = FloatLiteralToFloat64(0.0);
+let b: f64 = FloatLiteralToFloat64(1.0);
+let c: f64 = FloatLiteralToFloat64(1.0e308);
+//@dump-sem-ir-end
+
+// --- fail_todo_literal_f32.carbon
+
+library "[[@TEST_NAME]]";
+import library "f32";
+
+//@dump-sem-ir-begin
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_literal_f32.carbon:[[@LINE+4]]:8: note: in `f32` used here [ResolvingSpecificHere]
+// CHECK:STDERR: let a: f32 = FloatLiteralToFloat32(0.0);
+// CHECK:STDERR:        ^~~
+// CHECK:STDERR:
+let a: f32 = FloatLiteralToFloat32(0.0);
+let b: f32 = FloatLiteralToFloat32(1.0);
+let c: f32 = FloatLiteralToFloat32(1.0e38);
+//@dump-sem-ir-end
+
+// --- identity_f64.carbon
+
+library "[[@TEST_NAME]]";
+import library "f64";
+
+//@dump-sem-ir-begin
+let a: f64 = Float64ToFloat64(0.0);
+let b: f64 = Float64ToFloat64(1.0);
+let c: f64 = Float64ToFloat64(1.0e308);
+//@dump-sem-ir-end
+
+// --- fail_todo_identity_f32.carbon
+
+library "[[@TEST_NAME]]";
+import library "f32";
+
+//@dump-sem-ir-begin
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_identity_f32.carbon:[[@LINE+4]]:8: note: in `f32` used here [ResolvingSpecificHere]
+// CHECK:STDERR: let a: f32 = Float32ToFloat32(0.0);
+// CHECK:STDERR:        ^~~
+// CHECK:STDERR:
+let a: f32 = Float32ToFloat32(0.0);
+let b: f32 = Float32ToFloat32(1.0);
+let c: f32 = Float32ToFloat32(1.0e38);
+//@dump-sem-ir-end
+
+// --- fail_todo_truncate.carbon
+
+library "[[@TEST_NAME]]";
+import library "f32";
+
+//@dump-sem-ir-begin
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_truncate.carbon:[[@LINE+4]]:8: note: in `f32` used here [ResolvingSpecificHere]
+// CHECK:STDERR: let a: f32 = Float64ToFloat32(1.0);
+// CHECK:STDERR:        ^~~
+// CHECK:STDERR:
+let a: f32 = Float64ToFloat32(1.0);
+//@dump-sem-ir-end
+
+// --- fail_truncate_overflow.carbon
+
+library "[[@TEST_NAME]]";
+import library "f32";
+import library "f64";
+
+//@dump-sem-ir-begin
+// TODO: These should all produce an error that the source value doesn't fit in
+// the destination type.
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_truncate_overflow.carbon:[[@LINE+4]]:8: note: in `f32` used here [ResolvingSpecificHere]
+// CHECK:STDERR: let a: f32 = Float64ToFloat32(1.0e39);
+// CHECK:STDERR:        ^~~
+// CHECK:STDERR:
+let a: f32 = Float64ToFloat32(1.0e39);
+let b: f32 = FloatLiteralToFloat32(1.0e39);
+let c: f64 = FloatLiteralToFloat64(1.0e309);
+//@dump-sem-ir-end
+
+// --- extend.carbon
+
+library "[[@TEST_NAME]]";
+import library "f32";
+
+//@dump-sem-ir-begin
+let a: f64 = Float32ToFloat64(1.0);
+let b: f64 = Float32ToFloat64(1.0e30);
+//@dump-sem-ir-end
+
+// --- fail_not_constant.carbon
+
+library "[[@TEST_NAME]]";
+import library "f64";
+
+//@dump-sem-ir-begin
+let not_constant_64: f64 = 0.0;
+// CHECK:STDERR: fail_not_constant.carbon:[[@LINE+8]]:33: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
+// CHECK:STDERR: let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
+// CHECK:STDERR:                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: fail_not_constant.carbon:[[@LINE-7]]:1: in import [InImport]
+// CHECK:STDERR: f64.carbon:5:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
+// CHECK:STDERR: fn Float64ToFloat64(a: f64) -> f64 = "float.convert_checked";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
+//@dump-sem-ir-end
+
+// CHECK:STDOUT: --- identity_literal.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %FloatLiteral.type: type = fn_type @FloatLiteral [concrete]
+// CHECK:STDOUT:   %FloatLiteral: %FloatLiteral.type = struct_value () [concrete]
+// CHECK:STDOUT:   %pattern_type.dab: type = pattern_type Core.FloatLiteral [concrete]
+// CHECK:STDOUT:   %FloatLiteralToFloatLiteral.type: type = fn_type @FloatLiteralToFloatLiteral [concrete]
+// CHECK:STDOUT:   %FloatLiteralToFloatLiteral: %FloatLiteralToFloatLiteral.type = struct_value () [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.FloatLiteral: %FloatLiteral.type = import_ref Main//literal, FloatLiteral, loaded [concrete = constants.%FloatLiteral]
+// CHECK:STDOUT:   %Main.FloatLiteralToFloatLiteral: %FloatLiteralToFloatLiteral.type = import_ref Main//literal, FloatLiteralToFloatLiteral, loaded [concrete = constants.%FloatLiteralToFloatLiteral]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %f.patt: %pattern_type.dab = binding_pattern f [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc6_21.1: type = splice_block %.loc6_21.3 [concrete = Core.FloatLiteral] {
+// CHECK:STDOUT:     %FloatLiteral.ref: %FloatLiteral.type = name_ref FloatLiteral, imports.%Main.FloatLiteral [concrete = constants.%FloatLiteral]
+// CHECK:STDOUT:     %FloatLiteral.call: init type = call %FloatLiteral.ref() [concrete = Core.FloatLiteral]
+// CHECK:STDOUT:     %.loc6_21.2: type = value_of_initializer %FloatLiteral.call [concrete = Core.FloatLiteral]
+// CHECK:STDOUT:     %.loc6_21.3: type = converted %FloatLiteral.call, %.loc6_21.2 [concrete = Core.FloatLiteral]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc6_55.1: Core.FloatLiteral = value_of_initializer @__global_init.%FloatLiteralToFloatLiteral.call [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc6_55.2: Core.FloatLiteral = converted @__global_init.%FloatLiteralToFloatLiteral.call, %.loc6_55.1 [concrete = constants.%float]
+// CHECK:STDOUT:   %f: Core.FloatLiteral = bind_name f, %.loc6_55.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %FloatLiteralToFloatLiteral.ref: %FloatLiteralToFloatLiteral.type = name_ref FloatLiteralToFloatLiteral, imports.%Main.FloatLiteralToFloatLiteral [concrete = constants.%FloatLiteralToFloatLiteral]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %FloatLiteralToFloatLiteral.call: init Core.FloatLiteral = call %FloatLiteralToFloatLiteral.ref(%float) [concrete = constants.%float]
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- literal_f64.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
+// CHECK:STDOUT:   %FloatLiteralToFloat64.type: type = fn_type @FloatLiteralToFloat64 [concrete]
+// CHECK:STDOUT:   %FloatLiteralToFloat64: %FloatLiteralToFloat64.type = struct_value () [concrete]
+// CHECK:STDOUT:   %float.be6: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %float.a31: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float.9a4: Core.FloatLiteral = float_value 1.0E+308 [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.FloatLiteralToFloat64: %FloatLiteralToFloat64.type = import_ref Main//f64, FloatLiteralToFloat64, loaded [concrete = constants.%FloatLiteralToFloat64]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %pattern_type.0ae = binding_pattern a [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc6_8: type = splice_block %f64.loc6 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64.loc6: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64.loc6: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc6_39.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call.loc6 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %.loc6_39.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call.loc6, %.loc6_39.1 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %a: %f64.d77 = bind_name a, %.loc6_39.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %pattern_type.0ae = binding_pattern b [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc7_8: type = splice_block %f64.loc7 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64.loc7: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64.loc7: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc7_39.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call.loc7 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %.loc7_39.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call.loc7, %.loc7_39.1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %b: %f64.d77 = bind_name b, %.loc7_39.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %pattern_type.0ae = binding_pattern c [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc8_8: type = splice_block %f64.loc8 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64.loc8: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64.loc8: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc8_43.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call.loc8 [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %.loc8_43.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call.loc8, %.loc8_43.1 [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %c: %f64.d77 = bind_name c, %.loc8_43.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %FloatLiteralToFloat64.ref.loc6: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]
+// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_value 0 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %FloatLiteralToFloat64.call.loc6: init %f64.d77 = call %FloatLiteralToFloat64.ref.loc6(%float.loc6) [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %FloatLiteralToFloat64.ref.loc7: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]
+// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_value 1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %FloatLiteralToFloat64.call.loc7: init %f64.d77 = call %FloatLiteralToFloat64.ref.loc7(%float.loc7) [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %FloatLiteralToFloat64.ref.loc8: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]
+// CHECK:STDOUT:   %float.loc8: Core.FloatLiteral = float_value 1.0E+308 [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %FloatLiteralToFloat64.call.loc8: init %f64.d77 = call %FloatLiteralToFloat64.ref.loc8(%float.loc8) [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_todo_literal_f32.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %f32: type = class_type @Float, @Float(%int_32) [concrete]
+// CHECK:STDOUT:   %pattern_type.201: type = pattern_type %f32 [concrete]
+// CHECK:STDOUT:   %FloatLiteralToFloat32.type: type = fn_type @FloatLiteralToFloat32 [concrete]
+// CHECK:STDOUT:   %FloatLiteralToFloat32: %FloatLiteralToFloat32.type = struct_value () [concrete]
+// CHECK:STDOUT:   %float.be6: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %float.a31: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float.cf6: Core.FloatLiteral = float_value 9.9999999999999997E+37 [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.FloatLiteralToFloat32: %FloatLiteralToFloat32.type = import_ref Main//f32, FloatLiteralToFloat32, loaded [concrete = constants.%FloatLiteralToFloat32]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %pattern_type.201 = binding_pattern a [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc13_8: type = splice_block %f32.loc13 [concrete = constants.%f32] {
+// CHECK:STDOUT:     %int_32.loc13: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %f32.loc13: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc13_39.1: %f32 = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc13
+// CHECK:STDOUT:   %.loc13_39.2: %f32 = converted @__global_init.%FloatLiteralToFloat32.call.loc13, %.loc13_39.1
+// CHECK:STDOUT:   %a: %f32 = bind_name a, %.loc13_39.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %pattern_type.201 = binding_pattern b [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc14_8: type = splice_block %f32.loc14 [concrete = constants.%f32] {
+// CHECK:STDOUT:     %int_32.loc14: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %f32.loc14: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc14_39.1: %f32 = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc14
+// CHECK:STDOUT:   %.loc14_39.2: %f32 = converted @__global_init.%FloatLiteralToFloat32.call.loc14, %.loc14_39.1
+// CHECK:STDOUT:   %b: %f32 = bind_name b, %.loc14_39.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %pattern_type.201 = binding_pattern c [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc15_8: type = splice_block %f32.loc15 [concrete = constants.%f32] {
+// CHECK:STDOUT:     %int_32.loc15: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %f32.loc15: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc15_42.1: %f32 = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc15
+// CHECK:STDOUT:   %.loc15_42.2: %f32 = converted @__global_init.%FloatLiteralToFloat32.call.loc15, %.loc15_42.1
+// CHECK:STDOUT:   %c: %f32 = bind_name c, %.loc15_42.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %FloatLiteralToFloat32.ref.loc13: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32]
+// CHECK:STDOUT:   %float.loc13: Core.FloatLiteral = float_value 0 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %FloatLiteralToFloat32.call.loc13: init %f32 = call %FloatLiteralToFloat32.ref.loc13(%float.loc13)
+// CHECK:STDOUT:   %FloatLiteralToFloat32.ref.loc14: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32]
+// CHECK:STDOUT:   %float.loc14: Core.FloatLiteral = float_value 1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %FloatLiteralToFloat32.call.loc14: init %f32 = call %FloatLiteralToFloat32.ref.loc14(%float.loc14)
+// CHECK:STDOUT:   %FloatLiteralToFloat32.ref.loc15: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32]
+// CHECK:STDOUT:   %float.loc15: Core.FloatLiteral = float_value 9.9999999999999997E+37 [concrete = constants.%float.cf6]
+// CHECK:STDOUT:   %FloatLiteralToFloat32.call.loc15: init %f32 = call %FloatLiteralToFloat32.ref.loc15(%float.loc15)
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- identity_f64.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
+// CHECK:STDOUT:   %Float64ToFloat64.type: type = fn_type @Float64ToFloat64 [concrete]
+// CHECK:STDOUT:   %Float64ToFloat64: %Float64ToFloat64.type = struct_value () [concrete]
+// CHECK:STDOUT:   %float.be6: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
+// CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness.857: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
+// CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.93b: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
+// CHECK:STDOUT:   %bound_method.71f: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %float.a31: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.64b: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %bound_method.20c: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %float.9a4: Core.FloatLiteral = float_value 1.0E+308 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.260: <bound method> = bound_method %float.9a4, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %bound_method.aa0: <bound method> = bound_method %float.9a4, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.Float64ToFloat64: %Float64ToFloat64.type = import_ref Main//f64, Float64ToFloat64, loaded [concrete = constants.%Float64ToFloat64]
+// CHECK:STDOUT:   %Core.import_ref.c0c: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644) = import_ref Core//prelude/parts/float, loc15_41, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45)]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.c0c), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %pattern_type.0ae = binding_pattern a [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc6_8: type = splice_block %f64.loc6 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64.loc6: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64.loc6: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc6_34.1: %f64.d77 = value_of_initializer @__global_init.%Float64ToFloat64.call.loc6 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %.loc6_34.2: %f64.d77 = converted @__global_init.%Float64ToFloat64.call.loc6, %.loc6_34.1 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %a: %f64.d77 = bind_name a, %.loc6_34.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %pattern_type.0ae = binding_pattern b [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc7_8: type = splice_block %f64.loc7 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64.loc7: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64.loc7: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc7_34.1: %f64.d77 = value_of_initializer @__global_init.%Float64ToFloat64.call.loc7 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %.loc7_34.2: %f64.d77 = converted @__global_init.%Float64ToFloat64.call.loc7, %.loc7_34.1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %b: %f64.d77 = bind_name b, %.loc7_34.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %pattern_type.0ae = binding_pattern c [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc8_8: type = splice_block %f64.loc8 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64.loc8: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64.loc8: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc8_38.1: %f64.d77 = value_of_initializer @__global_init.%Float64ToFloat64.call.loc8 [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %.loc8_38.2: %f64.d77 = converted @__global_init.%Float64ToFloat64.call.loc8, %.loc8_38.1 [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %c: %f64.d77 = bind_name c, %.loc8_38.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %Float64ToFloat64.ref.loc6: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]
+// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_value 0 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %impl.elem0.loc6: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
+// CHECK:STDOUT:   %bound_method.loc6_31.1: <bound method> = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.93b]
+// CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc6_31.2: <bound method> = bound_method %float.loc6, %specific_fn.loc6 [concrete = constants.%bound_method.71f]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %f64.d77 = call %bound_method.loc6_31.2(%float.loc6) [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %.loc6_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %.loc6_31.2: %f64.d77 = converted %float.loc6, %.loc6_31.1 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %Float64ToFloat64.call.loc6: init %f64.d77 = call %Float64ToFloat64.ref.loc6(%.loc6_31.2) [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %Float64ToFloat64.ref.loc7: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]
+// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_value 1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %impl.elem0.loc7: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
+// CHECK:STDOUT:   %bound_method.loc7_31.1: <bound method> = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.64b]
+// CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc7_31.2: <bound method> = bound_method %float.loc7, %specific_fn.loc7 [concrete = constants.%bound_method.20c]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %f64.d77 = call %bound_method.loc7_31.2(%float.loc7) [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %.loc7_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %.loc7_31.2: %f64.d77 = converted %float.loc7, %.loc7_31.1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %Float64ToFloat64.call.loc7: init %f64.d77 = call %Float64ToFloat64.ref.loc7(%.loc7_31.2) [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %Float64ToFloat64.ref.loc8: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]
+// CHECK:STDOUT:   %float.loc8: Core.FloatLiteral = float_value 1.0E+308 [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %impl.elem0.loc8: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
+// CHECK:STDOUT:   %bound_method.loc8_31.1: <bound method> = bound_method %float.loc8, %impl.elem0.loc8 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.260]
+// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc8_31.2: <bound method> = bound_method %float.loc8, %specific_fn.loc8 [concrete = constants.%bound_method.aa0]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc8: init %f64.d77 = call %bound_method.loc8_31.2(%float.loc8) [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %.loc8_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc8 [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %.loc8_31.2: %f64.d77 = converted %float.loc8, %.loc8_31.1 [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %Float64ToFloat64.call.loc8: init %f64.d77 = call %Float64ToFloat64.ref.loc8(%.loc8_31.2) [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_todo_identity_f32.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %f32: type = class_type @Float, @Float(%int_32) [concrete]
+// CHECK:STDOUT:   %pattern_type.201: type = pattern_type %f32 [concrete]
+// CHECK:STDOUT:   %Float32ToFloat32.type: type = fn_type @Float32ToFloat32 [concrete]
+// CHECK:STDOUT:   %Float32ToFloat32: %Float32ToFloat32.type = struct_value () [concrete]
+// CHECK:STDOUT:   %float.be6: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.31d: type = facet_type <@ImplicitAs, @ImplicitAs(%f32)> [concrete]
+// CHECK:STDOUT:   %ImplicitAs.Convert.type.b8c: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f32) [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness.e3f: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_32) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.43b: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_32) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.43b = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.31d = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.e3f) [concrete]
+// CHECK:STDOUT:   %.a5d: type = fn_type_with_self_type %ImplicitAs.Convert.type.b8c, %ImplicitAs.facet [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.02c: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
+// CHECK:STDOUT:   %bound_method.a33: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %float.a31: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.bcb: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
+// CHECK:STDOUT:   %bound_method.495: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %float.cf6: Core.FloatLiteral = float_value 9.9999999999999997E+37 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.82a: <bound method> = bound_method %float.cf6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
+// CHECK:STDOUT:   %bound_method.492: <bound method> = bound_method %float.cf6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.Float32ToFloat32: %Float32ToFloat32.type = import_ref Main//f32, Float32ToFloat32, loaded [concrete = constants.%Float32ToFloat32]
+// CHECK:STDOUT:   %Core.import_ref.c0c: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644) = import_ref Core//prelude/parts/float, loc15_41, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45)]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.c0c), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %pattern_type.201 = binding_pattern a [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc13_8: type = splice_block %f32.loc13 [concrete = constants.%f32] {
+// CHECK:STDOUT:     %int_32.loc13: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %f32.loc13: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc13_34.1: %f32 = value_of_initializer @__global_init.%Float32ToFloat32.call.loc13
+// CHECK:STDOUT:   %.loc13_34.2: %f32 = converted @__global_init.%Float32ToFloat32.call.loc13, %.loc13_34.1
+// CHECK:STDOUT:   %a: %f32 = bind_name a, %.loc13_34.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %pattern_type.201 = binding_pattern b [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc14_8: type = splice_block %f32.loc14 [concrete = constants.%f32] {
+// CHECK:STDOUT:     %int_32.loc14: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %f32.loc14: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc14_34.1: %f32 = value_of_initializer @__global_init.%Float32ToFloat32.call.loc14
+// CHECK:STDOUT:   %.loc14_34.2: %f32 = converted @__global_init.%Float32ToFloat32.call.loc14, %.loc14_34.1
+// CHECK:STDOUT:   %b: %f32 = bind_name b, %.loc14_34.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %pattern_type.201 = binding_pattern c [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc15_8: type = splice_block %f32.loc15 [concrete = constants.%f32] {
+// CHECK:STDOUT:     %int_32.loc15: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %f32.loc15: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc15_37.1: %f32 = value_of_initializer @__global_init.%Float32ToFloat32.call.loc15
+// CHECK:STDOUT:   %.loc15_37.2: %f32 = converted @__global_init.%Float32ToFloat32.call.loc15, %.loc15_37.1
+// CHECK:STDOUT:   %c: %f32 = bind_name c, %.loc15_37.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %Float32ToFloat32.ref.loc13: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32]
+// CHECK:STDOUT:   %float.loc13: Core.FloatLiteral = float_value 0 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %impl.elem0.loc13: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3]
+// CHECK:STDOUT:   %bound_method.loc13_31.1: <bound method> = bound_method %float.loc13, %impl.elem0.loc13 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.02c]
+// CHECK:STDOUT:   %specific_fn.loc13: <specific function> = specific_function %impl.elem0.loc13, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc13_31.2: <bound method> = bound_method %float.loc13, %specific_fn.loc13 [concrete = constants.%bound_method.a33]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc13: init %f32 = call %bound_method.loc13_31.2(%float.loc13) [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %.loc13_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc13 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %.loc13_31.2: %f32 = converted %float.loc13, %.loc13_31.1 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %Float32ToFloat32.call.loc13: init %f32 = call %Float32ToFloat32.ref.loc13(%.loc13_31.2)
+// CHECK:STDOUT:   %Float32ToFloat32.ref.loc14: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32]
+// CHECK:STDOUT:   %float.loc14: Core.FloatLiteral = float_value 1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %impl.elem0.loc14: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3]
+// CHECK:STDOUT:   %bound_method.loc14_31.1: <bound method> = bound_method %float.loc14, %impl.elem0.loc14 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.bcb]
+// CHECK:STDOUT:   %specific_fn.loc14: <specific function> = specific_function %impl.elem0.loc14, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc14_31.2: <bound method> = bound_method %float.loc14, %specific_fn.loc14 [concrete = constants.%bound_method.495]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc14: init %f32 = call %bound_method.loc14_31.2(%float.loc14) [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %.loc14_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc14 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %.loc14_31.2: %f32 = converted %float.loc14, %.loc14_31.1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %Float32ToFloat32.call.loc14: init %f32 = call %Float32ToFloat32.ref.loc14(%.loc14_31.2)
+// CHECK:STDOUT:   %Float32ToFloat32.ref.loc15: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32]
+// CHECK:STDOUT:   %float.loc15: Core.FloatLiteral = float_value 9.9999999999999997E+37 [concrete = constants.%float.cf6]
+// CHECK:STDOUT:   %impl.elem0.loc15: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3]
+// CHECK:STDOUT:   %bound_method.loc15_31.1: <bound method> = bound_method %float.loc15, %impl.elem0.loc15 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.82a]
+// CHECK:STDOUT:   %specific_fn.loc15: <specific function> = specific_function %impl.elem0.loc15, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc15_31.2: <bound method> = bound_method %float.loc15, %specific_fn.loc15 [concrete = constants.%bound_method.492]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc15: init %f32 = call %bound_method.loc15_31.2(%float.loc15) [concrete = constants.%float.cf6]
+// CHECK:STDOUT:   %.loc15_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc15 [concrete = constants.%float.cf6]
+// CHECK:STDOUT:   %.loc15_31.2: %f32 = converted %float.loc15, %.loc15_31.1 [concrete = constants.%float.cf6]
+// CHECK:STDOUT:   %Float32ToFloat32.call.loc15: init %f32 = call %Float32ToFloat32.ref.loc15(%.loc15_31.2)
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_todo_truncate.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %f32: type = class_type @Float, @Float(%int_32) [concrete]
+// CHECK:STDOUT:   %pattern_type.201: type = pattern_type %f32 [concrete]
+// CHECK:STDOUT:   %Float64ToFloat32.type: type = fn_type @Float64ToFloat32 [concrete]
+// CHECK:STDOUT:   %Float64ToFloat32: %Float64ToFloat32.type = struct_value () [concrete]
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
+// CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness.857: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
+// CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.Float64ToFloat32: %Float64ToFloat32.type = import_ref Main//f32, Float64ToFloat32, loaded [concrete = constants.%Float64ToFloat32]
+// CHECK:STDOUT:   %Core.import_ref.c0c: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644) = import_ref Core//prelude/parts/float, loc15_41, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45)]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.c0c), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %pattern_type.201 = binding_pattern a [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc13_8: type = splice_block %f32 [concrete = constants.%f32] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %f32: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc13_34.1: %f32 = value_of_initializer @__global_init.%Float64ToFloat32.call
+// CHECK:STDOUT:   %.loc13_34.2: %f32 = converted @__global_init.%Float64ToFloat32.call, %.loc13_34.1
+// CHECK:STDOUT:   %a: %f32 = bind_name a, %.loc13_34.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %Float64ToFloat32.ref: %Float64ToFloat32.type = name_ref Float64ToFloat32, imports.%Main.Float64ToFloat32 [concrete = constants.%Float64ToFloat32]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %impl.elem0: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
+// CHECK:STDOUT:   %bound_method.loc13_31.1: <bound method> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc13_31.2: <bound method> = bound_method %float, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc13_31.2(%float) [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc13_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc13_31.2: %f64.d77 = converted %float, %.loc13_31.1 [concrete = constants.%float]
+// CHECK:STDOUT:   %Float64ToFloat32.call: init %f32 = call %Float64ToFloat32.ref(%.loc13_31.2)
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_truncate_overflow.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %f32: type = class_type @Float, @Float(%int_32) [concrete]
+// CHECK:STDOUT:   %pattern_type.201: type = pattern_type %f32 [concrete]
+// CHECK:STDOUT:   %Float64ToFloat32.type: type = fn_type @Float64ToFloat32 [concrete]
+// CHECK:STDOUT:   %Float64ToFloat32: %Float64ToFloat32.type = struct_value () [concrete]
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
+// CHECK:STDOUT:   %float.629: Core.FloatLiteral = float_value 9.9999999999999994E+38 [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
+// CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness.857: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
+// CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.629, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.629, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %FloatLiteralToFloat32.type: type = fn_type @FloatLiteralToFloat32 [concrete]
+// CHECK:STDOUT:   %FloatLiteralToFloat32: %FloatLiteralToFloat32.type = struct_value () [concrete]
+// CHECK:STDOUT:   %FloatLiteralToFloat64.type: type = fn_type @FloatLiteralToFloat64 [concrete]
+// CHECK:STDOUT:   %FloatLiteralToFloat64: %FloatLiteralToFloat64.type = struct_value () [concrete]
+// CHECK:STDOUT:   %float.669: Core.FloatLiteral = float_value +Inf [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.FloatLiteralToFloat32: %FloatLiteralToFloat32.type = import_ref Main//f32, FloatLiteralToFloat32, loaded [concrete = constants.%FloatLiteralToFloat32]
+// CHECK:STDOUT:   %Main.Float64ToFloat32: %Float64ToFloat32.type = import_ref Main//f32, Float64ToFloat32, loaded [concrete = constants.%Float64ToFloat32]
+// CHECK:STDOUT:   %Main.FloatLiteralToFloat64: %FloatLiteralToFloat64.type = import_ref Main//f64, FloatLiteralToFloat64, loaded [concrete = constants.%FloatLiteralToFloat64]
+// CHECK:STDOUT:   %Core.import_ref.c0c: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644) = import_ref Core//prelude/parts/float, loc15_41, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45)]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.c0c), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %pattern_type.201 = binding_pattern a [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc16_8: type = splice_block %f32.loc16 [concrete = constants.%f32] {
+// CHECK:STDOUT:     %int_32.loc16: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %f32.loc16: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc16_37.1: %f32 = value_of_initializer @__global_init.%Float64ToFloat32.call
+// CHECK:STDOUT:   %.loc16_37.2: %f32 = converted @__global_init.%Float64ToFloat32.call, %.loc16_37.1
+// CHECK:STDOUT:   %a: %f32 = bind_name a, %.loc16_37.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %pattern_type.201 = binding_pattern b [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc17_8: type = splice_block %f32.loc17 [concrete = constants.%f32] {
+// CHECK:STDOUT:     %int_32.loc17: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %f32.loc17: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc17_42.1: %f32 = value_of_initializer @__global_init.%FloatLiteralToFloat32.call
+// CHECK:STDOUT:   %.loc17_42.2: %f32 = converted @__global_init.%FloatLiteralToFloat32.call, %.loc17_42.1
+// CHECK:STDOUT:   %b: %f32 = bind_name b, %.loc17_42.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %pattern_type.0ae = binding_pattern c [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc18_8: type = splice_block %f64 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc18_43.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call [concrete = constants.%float.669]
+// CHECK:STDOUT:   %.loc18_43.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call, %.loc18_43.1 [concrete = constants.%float.669]
+// CHECK:STDOUT:   %c: %f64.d77 = bind_name c, %.loc18_43.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %Float64ToFloat32.ref: %Float64ToFloat32.type = name_ref Float64ToFloat32, imports.%Main.Float64ToFloat32 [concrete = constants.%Float64ToFloat32]
+// CHECK:STDOUT:   %float.loc16: Core.FloatLiteral = float_value 9.9999999999999994E+38 [concrete = constants.%float.629]
+// CHECK:STDOUT:   %impl.elem0: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
+// CHECK:STDOUT:   %bound_method.loc16_31.1: <bound method> = bound_method %float.loc16, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc16_31.2: <bound method> = bound_method %float.loc16, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc16_31.2(%float.loc16) [concrete = constants.%float.629]
+// CHECK:STDOUT:   %.loc16_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.629]
+// CHECK:STDOUT:   %.loc16_31.2: %f64.d77 = converted %float.loc16, %.loc16_31.1 [concrete = constants.%float.629]
+// CHECK:STDOUT:   %Float64ToFloat32.call: init %f32 = call %Float64ToFloat32.ref(%.loc16_31.2)
+// CHECK:STDOUT:   %FloatLiteralToFloat32.ref: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32]
+// CHECK:STDOUT:   %float.loc17: Core.FloatLiteral = float_value 9.9999999999999994E+38 [concrete = constants.%float.629]
+// CHECK:STDOUT:   %FloatLiteralToFloat32.call: init %f32 = call %FloatLiteralToFloat32.ref(%float.loc17)
+// CHECK:STDOUT:   %FloatLiteralToFloat64.ref: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]
+// CHECK:STDOUT:   %float.loc18: Core.FloatLiteral = float_value +Inf [concrete = constants.%float.669]
+// CHECK:STDOUT:   %FloatLiteralToFloat64.call: init %f64.d77 = call %FloatLiteralToFloat64.ref(%float.loc18) [concrete = constants.%float.669]
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- extend.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
+// CHECK:STDOUT:   %Float32ToFloat64.type: type = fn_type @Float32ToFloat64 [concrete]
+// CHECK:STDOUT:   %Float32ToFloat64: %Float32ToFloat64.type = struct_value () [concrete]
+// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %f32: type = class_type @Float, @Float(%int_32) [concrete]
+// CHECK:STDOUT:   %float.a31: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.31d: type = facet_type <@ImplicitAs, @ImplicitAs(%f32)> [concrete]
+// CHECK:STDOUT:   %ImplicitAs.Convert.type.b8c: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f32) [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness.e3f: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_32) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.43b: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_32) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.43b = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.31d = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.e3f) [concrete]
+// CHECK:STDOUT:   %.a5d: type = fn_type_with_self_type %ImplicitAs.Convert.type.b8c, %ImplicitAs.facet [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.bcb: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
+// CHECK:STDOUT:   %bound_method.495: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %float.f26: Core.FloatLiteral = float_value 9.9999999999999988E+29 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6ef: <bound method> = bound_method %float.f26, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
+// CHECK:STDOUT:   %bound_method.f39: <bound method> = bound_method %float.f26, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.Float32ToFloat64: %Float32ToFloat64.type = import_ref Main//f32, Float32ToFloat64, loaded [concrete = constants.%Float32ToFloat64]
+// CHECK:STDOUT:   %Core.import_ref.c0c: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644) = import_ref Core//prelude/parts/float, loc15_41, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45)]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.c0c), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %pattern_type.0ae = binding_pattern a [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc6_8: type = splice_block %f64.loc6 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64.loc6: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64.loc6: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc6_34.1: %f64.d77 = value_of_initializer @__global_init.%Float32ToFloat64.call.loc6
+// CHECK:STDOUT:   %.loc6_34.2: %f64.d77 = converted @__global_init.%Float32ToFloat64.call.loc6, %.loc6_34.1
+// CHECK:STDOUT:   %a: %f64.d77 = bind_name a, %.loc6_34.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %pattern_type.0ae = binding_pattern b [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc7_8: type = splice_block %f64.loc7 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64.loc7: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64.loc7: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc7_37.1: %f64.d77 = value_of_initializer @__global_init.%Float32ToFloat64.call.loc7
+// CHECK:STDOUT:   %.loc7_37.2: %f64.d77 = converted @__global_init.%Float32ToFloat64.call.loc7, %.loc7_37.1
+// CHECK:STDOUT:   %b: %f64.d77 = bind_name b, %.loc7_37.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %Float32ToFloat64.ref.loc6: %Float32ToFloat64.type = name_ref Float32ToFloat64, imports.%Main.Float32ToFloat64 [concrete = constants.%Float32ToFloat64]
+// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_value 1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %impl.elem0.loc6: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3]
+// CHECK:STDOUT:   %bound_method.loc6_31.1: <bound method> = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.bcb]
+// CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc6_31.2: <bound method> = bound_method %float.loc6, %specific_fn.loc6 [concrete = constants.%bound_method.495]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %f32 = call %bound_method.loc6_31.2(%float.loc6) [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %.loc6_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %.loc6_31.2: %f32 = converted %float.loc6, %.loc6_31.1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %Float32ToFloat64.call.loc6: init %f64.d77 = call %Float32ToFloat64.ref.loc6(%.loc6_31.2)
+// CHECK:STDOUT:   %Float32ToFloat64.ref.loc7: %Float32ToFloat64.type = name_ref Float32ToFloat64, imports.%Main.Float32ToFloat64 [concrete = constants.%Float32ToFloat64]
+// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_value 9.9999999999999988E+29 [concrete = constants.%float.f26]
+// CHECK:STDOUT:   %impl.elem0.loc7: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3]
+// CHECK:STDOUT:   %bound_method.loc7_31.1: <bound method> = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6ef]
+// CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc7_31.2: <bound method> = bound_method %float.loc7, %specific_fn.loc7 [concrete = constants.%bound_method.f39]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %f32 = call %bound_method.loc7_31.2(%float.loc7) [concrete = constants.%float.f26]
+// CHECK:STDOUT:   %.loc7_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%float.f26]
+// CHECK:STDOUT:   %.loc7_31.2: %f32 = converted %float.loc7, %.loc7_31.1 [concrete = constants.%float.f26]
+// CHECK:STDOUT:   %Float32ToFloat64.call.loc7: init %f64.d77 = call %Float32ToFloat64.ref.loc7(%.loc7_31.2)
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_not_constant.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
+// CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness.857: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
+// CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %Float64ToFloat64.type: type = fn_type @Float64ToFloat64 [concrete]
+// CHECK:STDOUT:   %Float64ToFloat64: %Float64ToFloat64.type = struct_value () [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.Float64ToFloat64: %Float64ToFloat64.type = import_ref Main//f64, Float64ToFloat64, loaded [concrete = constants.%Float64ToFloat64]
+// CHECK:STDOUT:   %Core.import_ref.c0c: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644) = import_ref Core//prelude/parts/float, loc15_41, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45)]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.c0c), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %not_constant_64.patt: %pattern_type.0ae = binding_pattern not_constant_64 [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc6_22: type = splice_block %f64.loc6 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64.loc6: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64.loc6: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %impl.elem0: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
+// CHECK:STDOUT:   %bound_method.loc6_28.1: <bound method> = bound_method @__global_init.%float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc6_28.2: <bound method> = bound_method @__global_init.%float, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc6_28.2(@__global_init.%float) [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc6_28.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc6_28.2: %f64.d77 = converted @__global_init.%float, %.loc6_28.1 [concrete = constants.%float]
+// CHECK:STDOUT:   %not_constant_64: %f64.d77 = bind_name not_constant_64, %.loc6_28.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %convert_not_constant.patt: %pattern_type.0ae = binding_pattern convert_not_constant [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc15_27: type = splice_block %f64.loc15 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:     %int_64.loc15: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
+// CHECK:STDOUT:     %f64.loc15: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc15_65.1: %f64.d77 = value_of_initializer @__global_init.%Float64ToFloat64.call
+// CHECK:STDOUT:   %.loc15_65.2: %f64.d77 = converted @__global_init.%Float64ToFloat64.call, %.loc15_65.1
+// CHECK:STDOUT:   %convert_not_constant: %f64.d77 = bind_name convert_not_constant, %.loc15_65.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0 [concrete = constants.%float]
+// CHECK:STDOUT:   %Float64ToFloat64.ref: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]
+// CHECK:STDOUT:   %not_constant_64.ref: %f64.d77 = name_ref not_constant_64, file.%not_constant_64
+// CHECK:STDOUT:   %Float64ToFloat64.call: init %f64.d77 = call %Float64ToFloat64.ref(%not_constant_64.ref)
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 8 - 6
toolchain/check/testdata/builtins/float/div.carbon

@@ -69,6 +69,8 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: --- float_div.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %Div.type: type = fn_type @Div [concrete]
 // CHECK:STDOUT:   %Div: %Div.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -76,14 +78,14 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> f64 {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> %f64.d77 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Div.ref: %Div.type = name_ref Div, file.%Div.decl [concrete = constants.%Div]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: f64 = name_ref b, %b
-// CHECK:STDOUT:   %Div.call: init f64 = call %Div.ref(%a.ref, %b.ref)
-// CHECK:STDOUT:   %.loc8_19.1: f64 = value_of_initializer %Div.call
-// CHECK:STDOUT:   %.loc8_19.2: f64 = converted %Div.call, %.loc8_19.1
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b
+// CHECK:STDOUT:   %Div.call: init %f64.d77 = call %Div.ref(%a.ref, %b.ref)
+// CHECK:STDOUT:   %.loc8_19.1: %f64.d77 = value_of_initializer %Div.call
+// CHECK:STDOUT:   %.loc8_19.2: %f64.d77 = converted %Div.call, %.loc8_19.1
 // CHECK:STDOUT:   return %.loc8_19.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 44 - 0
toolchain/check/testdata/builtins/float/div_assign.carbon

@@ -0,0 +1,44 @@
+// 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
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/div_assign.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/div_assign.carbon
+
+// --- call.carbon
+
+library "call";
+
+fn Builtin(a: f64*, b: f64) = "float.div_assign";
+
+fn Call(a: f64*, b: f64) {
+  Builtin(a, b);
+}
+
+// --- fail_bad_decl.carbon
+
+library "fail_bad_decl";
+
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.div_assign" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn NotPtr(a: f64, b: f64) = "float.div_assign";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn NotPtr(a: f64, b: f64) = "float.div_assign";
+
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+8]]:24: note: in `f32` used here [ResolvingSpecificHere]
+// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.div_assign";
+// CHECK:STDERR:                        ^~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.div_assign" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.div_assign";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn MixedTypes(a: f64*, b: f32) = "float.div_assign";

+ 5 - 3
toolchain/check/testdata/builtins/float/eq.carbon

@@ -41,6 +41,8 @@ fn WrongResult(a: f64, b: f64) -> f64 = "float.eq";
 // CHECK:STDOUT: --- float_eq.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %Eq.type: type = fn_type @Eq [concrete]
 // CHECK:STDOUT:   %Eq: %Eq.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -48,11 +50,11 @@ fn WrongResult(a: f64, b: f64) -> f64 = "float.eq";
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> bool {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> bool {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Eq.ref: %Eq.type = name_ref Eq, file.%Eq.decl [concrete = constants.%Eq]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: f64 = name_ref b, %b
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b
 // CHECK:STDOUT:   %Eq.call: init bool = call %Eq.ref(%a.ref, %b.ref)
 // CHECK:STDOUT:   %.loc14_18.1: bool = value_of_initializer %Eq.call
 // CHECK:STDOUT:   %.loc14_18.2: bool = converted %Eq.call, %.loc14_18.1

+ 5 - 3
toolchain/check/testdata/builtins/float/greater.carbon

@@ -35,6 +35,8 @@ fn RuntimeCallIsValid(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: --- float_greater.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %Greater.type: type = fn_type @Greater [concrete]
 // CHECK:STDOUT:   %Greater: %Greater.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -42,11 +44,11 @@ fn RuntimeCallIsValid(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> bool {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> bool {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Greater.ref: %Greater.type = name_ref Greater, file.%Greater.decl [concrete = constants.%Greater]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: f64 = name_ref b, %b
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b
 // CHECK:STDOUT:   %Greater.call: init bool = call %Greater.ref(%a.ref, %b.ref)
 // CHECK:STDOUT:   %.loc18_23.1: bool = value_of_initializer %Greater.call
 // CHECK:STDOUT:   %.loc18_23.2: bool = converted %Greater.call, %.loc18_23.1

+ 5 - 3
toolchain/check/testdata/builtins/float/greater_eq.carbon

@@ -35,6 +35,8 @@ fn RuntimeCallIsValid(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: --- float_greater_eq.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %GreaterEq.type: type = fn_type @GreaterEq [concrete]
 // CHECK:STDOUT:   %GreaterEq: %GreaterEq.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -42,11 +44,11 @@ fn RuntimeCallIsValid(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> bool {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> bool {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %GreaterEq.ref: %GreaterEq.type = name_ref GreaterEq, file.%GreaterEq.decl [concrete = constants.%GreaterEq]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: f64 = name_ref b, %b
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b
 // CHECK:STDOUT:   %GreaterEq.call: init bool = call %GreaterEq.ref(%a.ref, %b.ref)
 // CHECK:STDOUT:   %.loc18_25.1: bool = value_of_initializer %GreaterEq.call
 // CHECK:STDOUT:   %.loc18_25.2: bool = converted %GreaterEq.call, %.loc18_25.1

+ 5 - 3
toolchain/check/testdata/builtins/float/less.carbon

@@ -35,6 +35,8 @@ fn RuntimeCallIsValid(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: --- float_less.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %Less.type: type = fn_type @Less [concrete]
 // CHECK:STDOUT:   %Less: %Less.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -42,11 +44,11 @@ fn RuntimeCallIsValid(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> bool {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> bool {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Less.ref: %Less.type = name_ref Less, file.%Less.decl [concrete = constants.%Less]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: f64 = name_ref b, %b
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b
 // CHECK:STDOUT:   %Less.call: init bool = call %Less.ref(%a.ref, %b.ref)
 // CHECK:STDOUT:   %.loc18_20.1: bool = value_of_initializer %Less.call
 // CHECK:STDOUT:   %.loc18_20.2: bool = converted %Less.call, %.loc18_20.1

+ 5 - 3
toolchain/check/testdata/builtins/float/less_eq.carbon

@@ -35,6 +35,8 @@ fn RuntimeCallIsValid(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: --- float_less_eq.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %LessEq.type: type = fn_type @LessEq [concrete]
 // CHECK:STDOUT:   %LessEq: %LessEq.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -42,11 +44,11 @@ fn RuntimeCallIsValid(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> bool {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> bool {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %LessEq.ref: %LessEq.type = name_ref LessEq, file.%LessEq.decl [concrete = constants.%LessEq]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: f64 = name_ref b, %b
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b
 // CHECK:STDOUT:   %LessEq.call: init bool = call %LessEq.ref(%a.ref, %b.ref)
 // CHECK:STDOUT:   %.loc18_22.1: bool = value_of_initializer %LessEq.call
 // CHECK:STDOUT:   %.loc18_22.2: bool = converted %LessEq.call, %.loc18_22.1

+ 1 - 6
toolchain/check/testdata/builtins/float/make_type.carbon

@@ -22,7 +22,7 @@ library "[[@TEST_NAME]]";
 
 import library "types";
 
-var f: Float(64) = 0.0;
+var f: Float(64);
 
 fn GetFloat(dyn_size: i32) -> type {
   //@dump-sem-ir-begin
@@ -78,8 +78,3 @@ var dyn: Float(dyn_size);
 // CHECK:STDOUT:   return %.loc10_25.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @__global_init() {
-// CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   <elided>
-// CHECK:STDOUT: }
-// CHECK:STDOUT:

+ 8 - 6
toolchain/check/testdata/builtins/float/mul.carbon

@@ -69,6 +69,8 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: --- mul_sub.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %Mul.type: type = fn_type @Mul [concrete]
 // CHECK:STDOUT:   %Mul: %Mul.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -76,14 +78,14 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> f64 {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> %f64.d77 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Mul.ref: %Mul.type = name_ref Mul, file.%Mul.decl [concrete = constants.%Mul]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: f64 = name_ref b, %b
-// CHECK:STDOUT:   %Mul.call: init f64 = call %Mul.ref(%a.ref, %b.ref)
-// CHECK:STDOUT:   %.loc8_19.1: f64 = value_of_initializer %Mul.call
-// CHECK:STDOUT:   %.loc8_19.2: f64 = converted %Mul.call, %.loc8_19.1
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b
+// CHECK:STDOUT:   %Mul.call: init %f64.d77 = call %Mul.ref(%a.ref, %b.ref)
+// CHECK:STDOUT:   %.loc8_19.1: %f64.d77 = value_of_initializer %Mul.call
+// CHECK:STDOUT:   %.loc8_19.2: %f64.d77 = converted %Mul.call, %.loc8_19.1
 // CHECK:STDOUT:   return %.loc8_19.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 44 - 0
toolchain/check/testdata/builtins/float/mul_assign.carbon

@@ -0,0 +1,44 @@
+// 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
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/mul_assign.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/mul_assign.carbon
+
+// --- call.carbon
+
+library "call";
+
+fn Builtin(a: f64*, b: f64) = "float.mul_assign";
+
+fn Call(a: f64*, b: f64) {
+  Builtin(a, b);
+}
+
+// --- fail_bad_decl.carbon
+
+library "fail_bad_decl";
+
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.mul_assign" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn NotPtr(a: f64, b: f64) = "float.mul_assign";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn NotPtr(a: f64, b: f64) = "float.mul_assign";
+
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+8]]:24: note: in `f32` used here [ResolvingSpecificHere]
+// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.mul_assign";
+// CHECK:STDERR:                        ^~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.mul_assign" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.mul_assign";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn MixedTypes(a: f64*, b: f32) = "float.mul_assign";

+ 7 - 5
toolchain/check/testdata/builtins/float/negate.carbon

@@ -69,6 +69,8 @@ fn RuntimeCallIsValidBadReturnType(a: f64) -> bool {
 // CHECK:STDOUT: --- float_negate.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %Negate.type: type = fn_type @Negate [concrete]
 // CHECK:STDOUT:   %Negate: %Negate.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -76,13 +78,13 @@ fn RuntimeCallIsValidBadReturnType(a: f64) -> bool {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> f64 {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> %f64.d77 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Negate.ref: %Negate.type = name_ref Negate, file.%Negate.decl [concrete = constants.%Negate]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %Negate.call: init f64 = call %Negate.ref(%a.ref)
-// CHECK:STDOUT:   %.loc8_19.1: f64 = value_of_initializer %Negate.call
-// CHECK:STDOUT:   %.loc8_19.2: f64 = converted %Negate.call, %.loc8_19.1
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %Negate.call: init %f64.d77 = call %Negate.ref(%a.ref)
+// CHECK:STDOUT:   %.loc8_19.1: %f64.d77 = value_of_initializer %Negate.call
+// CHECK:STDOUT:   %.loc8_19.2: %f64.d77 = converted %Negate.call, %.loc8_19.1
 // CHECK:STDOUT:   return %.loc8_19.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 5 - 3
toolchain/check/testdata/builtins/float/neq.carbon

@@ -43,6 +43,8 @@ fn WrongResult(a: f64, b: f64) -> f64 = "float.neq";
 // CHECK:STDOUT: --- float_neq.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %Neq.type: type = fn_type @Neq [concrete]
 // CHECK:STDOUT:   %Neq: %Neq.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -50,11 +52,11 @@ fn WrongResult(a: f64, b: f64) -> f64 = "float.neq";
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> bool {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> bool {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Neq.ref: %Neq.type = name_ref Neq, file.%Neq.decl [concrete = constants.%Neq]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: f64 = name_ref b, %b
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b
 // CHECK:STDOUT:   %Neq.call: init bool = call %Neq.ref(%a.ref, %b.ref)
 // CHECK:STDOUT:   %.loc16_19.1: bool = value_of_initializer %Neq.call
 // CHECK:STDOUT:   %.loc16_19.2: bool = converted %Neq.call, %.loc16_19.1

+ 8 - 6
toolchain/check/testdata/builtins/float/sub.carbon

@@ -69,6 +69,8 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: --- float_sub.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %Sub.type: type = fn_type @Sub [concrete]
 // CHECK:STDOUT:   %Sub: %Sub.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -76,14 +78,14 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: f64, %b.param: f64) -> f64 {
+// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> %f64.d77 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Sub.ref: %Sub.type = name_ref Sub, file.%Sub.decl [concrete = constants.%Sub]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: f64 = name_ref b, %b
-// CHECK:STDOUT:   %Sub.call: init f64 = call %Sub.ref(%a.ref, %b.ref)
-// CHECK:STDOUT:   %.loc8_19.1: f64 = value_of_initializer %Sub.call
-// CHECK:STDOUT:   %.loc8_19.2: f64 = converted %Sub.call, %.loc8_19.1
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b
+// CHECK:STDOUT:   %Sub.call: init %f64.d77 = call %Sub.ref(%a.ref, %b.ref)
+// CHECK:STDOUT:   %.loc8_19.1: %f64.d77 = value_of_initializer %Sub.call
+// CHECK:STDOUT:   %.loc8_19.2: %f64.d77 = converted %Sub.call, %.loc8_19.1
 // CHECK:STDOUT:   return %.loc8_19.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 44 - 0
toolchain/check/testdata/builtins/float/sub_assign.carbon

@@ -0,0 +1,44 @@
+// 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
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/sub_assign.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/sub_assign.carbon
+
+// --- call.carbon
+
+library "call";
+
+fn Builtin(a: f64*, b: f64) = "float.sub_assign";
+
+fn Call(a: f64*, b: f64) {
+  Builtin(a, b);
+}
+
+// --- fail_bad_decl.carbon
+
+library "fail_bad_decl";
+
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.sub_assign" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn NotPtr(a: f64, b: f64) = "float.sub_assign";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn NotPtr(a: f64, b: f64) = "float.sub_assign";
+
+// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth]
+// CHECK:STDERR:   adapt MakeFloat(N);
+// CHECK:STDERR:         ^~~~~~~~~~~~
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+8]]:24: note: in `f32` used here [ResolvingSpecificHere]
+// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.sub_assign";
+// CHECK:STDERR:                        ^~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.sub_assign" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.sub_assign";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+fn MixedTypes(a: f64*, b: f32) = "float.sub_assign";

+ 63 - 0
toolchain/check/testdata/builtins/float_literal/make_type.carbon

@@ -0,0 +1,63 @@
+// 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
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float_literal/make_type.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float_literal/make_type.carbon
+
+// --- types.carbon
+
+library "[[@TEST_NAME]]";
+
+fn FloatLiteral() -> type = "float_literal.make_type";
+
+// --- use_types.carbon
+
+library "[[@TEST_NAME]]";
+
+import library "types";
+
+//@dump-sem-ir-begin
+var f: FloatLiteral() = 1.0;
+//@dump-sem-ir-end
+
+// CHECK:STDOUT: --- use_types.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %FloatLiteral.type: type = fn_type @FloatLiteral [concrete]
+// CHECK:STDOUT:   %FloatLiteral: %FloatLiteral.type = struct_value () [concrete]
+// CHECK:STDOUT:   %pattern_type.dab: type = pattern_type Core.FloatLiteral [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.FloatLiteral: %FloatLiteral.type = import_ref Main//types, FloatLiteral, loaded [concrete = constants.%FloatLiteral]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %f.patt: %pattern_type.dab = binding_pattern f [concrete]
+// CHECK:STDOUT:     %f.var_patt: %pattern_type.dab = var_pattern %f.patt [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %f.var: ref Core.FloatLiteral = var %f.var_patt [concrete]
+// CHECK:STDOUT:   %.loc7_21.1: type = splice_block %.loc7_21.3 [concrete = Core.FloatLiteral] {
+// CHECK:STDOUT:     %FloatLiteral.ref: %FloatLiteral.type = name_ref FloatLiteral, imports.%Main.FloatLiteral [concrete = constants.%FloatLiteral]
+// CHECK:STDOUT:     %FloatLiteral.call: init type = call %FloatLiteral.ref() [concrete = Core.FloatLiteral]
+// CHECK:STDOUT:     %.loc7_21.2: type = value_of_initializer %FloatLiteral.call [concrete = Core.FloatLiteral]
+// CHECK:STDOUT:     %.loc7_21.3: type = converted %FloatLiteral.call, %.loc7_21.2 [concrete = Core.FloatLiteral]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %f: ref Core.FloatLiteral = bind_name f, %f.var [concrete = %f.var]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   assign file.%f.var, %float
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 69 - 53
toolchain/check/testdata/deduce/int_float.carbon

@@ -24,15 +24,10 @@ fn G(a: i64) -> Core.IntLiteral() {
   return F(a);
 }
 
-// --- fail_todo_float.carbon
+// --- float.carbon
 
 library "[[@TEST_NAME]]";
 
-// TODO: This should pass once we accept symbolic widths for Core.Float.
-// CHECK:STDERR: fail_todo_float.carbon:[[@LINE+4]]:32: error: cannot evaluate type expression [TypeExprEvaluationFailure]
-// CHECK:STDERR: fn F[N:! Core.IntLiteral()](n: Core.Float(N)) -> Core.IntLiteral() {
-// CHECK:STDERR:                                ^~~~~~~~~~~~~
-// CHECK:STDERR:
 fn F[N:! Core.IntLiteral()](n: Core.Float(N)) -> Core.IntLiteral() {
   return N;
 }
@@ -177,21 +172,28 @@ fn G(a: f64) -> Core.IntLiteral() {
 // CHECK:STDOUT:   %require_complete => constants.%complete_type.4a1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_todo_float.carbon
+// CHECK:STDOUT: --- float.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]
 // CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]
 // CHECK:STDOUT:   %N: Core.IntLiteral = bind_symbolic_name N, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Float.type: type = generic_class_type @Float [concrete]
+// CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Float: type = class_type @Float, @Float(%N) [symbolic]
+// CHECK:STDOUT:   %pattern_type.f08: type = pattern_type %Float [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
+// CHECK:STDOUT:   %require_complete.957: <witness> = require_complete_type %Float [symbolic]
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %pattern_type.3de: type = pattern_type f64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
+// CHECK:STDOUT:   %f64.cae: type = float_type %int_64 [concrete]
+// CHECK:STDOUT:   %complete_type.3f9: <witness> = complete_type_witness %f64.cae [concrete]
+// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%int_64) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -202,7 +204,7 @@ fn G(a: f64) -> Core.IntLiteral() {
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/parts/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]
-// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float]
+// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float.generic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -214,81 +216,95 @@ fn G(a: f64) -> Core.IntLiteral() {
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
 // CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = symbolic_binding_pattern N, 0 [concrete]
-// CHECK:STDOUT:     %n.patt: <error> = binding_pattern n [concrete]
-// CHECK:STDOUT:     %n.param_patt: <error> = value_param_pattern %n.patt, call_param0 [concrete]
+// CHECK:STDOUT:     %n.patt: @F.%pattern_type (%pattern_type.f08) = binding_pattern n [concrete]
+// CHECK:STDOUT:     %n.param_patt: @F.%pattern_type (%pattern_type.f08) = value_param_pattern %n.patt, call_param0 [concrete]
 // CHECK:STDOUT:     %return.patt: %pattern_type.dc0 = return_slot_pattern [concrete]
 // CHECK:STDOUT:     %return.param_patt: %pattern_type.dc0 = out_param_pattern %return.patt, call_param1 [concrete]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %Core.ref.loc9_50: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]
-// CHECK:STDOUT:     %IntLiteral.ref.loc9_54: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]
-// CHECK:STDOUT:     %IntLiteral.call.loc9_66: init type = call %IntLiteral.ref.loc9_54() [concrete = Core.IntLiteral]
-// CHECK:STDOUT:     %.loc9_66.1: type = value_of_initializer %IntLiteral.call.loc9_66 [concrete = Core.IntLiteral]
-// CHECK:STDOUT:     %.loc9_66.2: type = converted %IntLiteral.call.loc9_66, %.loc9_66.1 [concrete = Core.IntLiteral]
-// CHECK:STDOUT:     %.loc9_26.1: type = splice_block %.loc9_26.3 [concrete = Core.IntLiteral] {
-// CHECK:STDOUT:       %Core.ref.loc9_10: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]
-// CHECK:STDOUT:       %IntLiteral.ref.loc9_14: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]
-// CHECK:STDOUT:       %IntLiteral.call.loc9_26: init type = call %IntLiteral.ref.loc9_14() [concrete = Core.IntLiteral]
-// CHECK:STDOUT:       %.loc9_26.2: type = value_of_initializer %IntLiteral.call.loc9_26 [concrete = Core.IntLiteral]
-// CHECK:STDOUT:       %.loc9_26.3: type = converted %IntLiteral.call.loc9_26, %.loc9_26.2 [concrete = Core.IntLiteral]
+// CHECK:STDOUT:     %Core.ref.loc4_50: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]
+// CHECK:STDOUT:     %IntLiteral.ref.loc4_54: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]
+// CHECK:STDOUT:     %IntLiteral.call.loc4_66: init type = call %IntLiteral.ref.loc4_54() [concrete = Core.IntLiteral]
+// CHECK:STDOUT:     %.loc4_66.1: type = value_of_initializer %IntLiteral.call.loc4_66 [concrete = Core.IntLiteral]
+// CHECK:STDOUT:     %.loc4_66.2: type = converted %IntLiteral.call.loc4_66, %.loc4_66.1 [concrete = Core.IntLiteral]
+// CHECK:STDOUT:     %.loc4_26.1: type = splice_block %.loc4_26.3 [concrete = Core.IntLiteral] {
+// CHECK:STDOUT:       %Core.ref.loc4_10: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]
+// CHECK:STDOUT:       %IntLiteral.ref.loc4_14: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]
+// CHECK:STDOUT:       %IntLiteral.call.loc4_26: init type = call %IntLiteral.ref.loc4_14() [concrete = Core.IntLiteral]
+// CHECK:STDOUT:       %.loc4_26.2: type = value_of_initializer %IntLiteral.call.loc4_26 [concrete = Core.IntLiteral]
+// CHECK:STDOUT:       %.loc4_26.3: type = converted %IntLiteral.call.loc4_26, %.loc4_26.2 [concrete = Core.IntLiteral]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %N.loc9_6.2: Core.IntLiteral = bind_symbolic_name N, 0 [symbolic = %N.loc9_6.1 (constants.%N)]
-// CHECK:STDOUT:     %n.param: <error> = value_param call_param0
-// CHECK:STDOUT:     %.1: <error> = splice_block <error> [concrete = <error>] {
-// CHECK:STDOUT:       %Core.ref.loc9_32: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]
-// CHECK:STDOUT:       %Float.ref: %Float.type = name_ref Float, imports.%Core.Float [concrete = constants.%Float]
-// CHECK:STDOUT:       %N.ref.loc9: Core.IntLiteral = name_ref N, %N.loc9_6.2 [symbolic = %N.loc9_6.1 (constants.%N)]
-// CHECK:STDOUT:       %Float.call: init type = call %Float.ref(%N.ref.loc9)
-// CHECK:STDOUT:       %.loc9_44.1: type = value_of_initializer %Float.call
-// CHECK:STDOUT:       %.loc9_44.2: type = converted %Float.call, %.loc9_44.1
+// CHECK:STDOUT:     %N.loc4_6.2: Core.IntLiteral = bind_symbolic_name N, 0 [symbolic = %N.loc4_6.1 (constants.%N)]
+// CHECK:STDOUT:     %n.param: @F.%Float.loc4_44.1 (%Float) = value_param call_param0
+// CHECK:STDOUT:     %.loc4_44: type = splice_block %Float.loc4_44.2 [symbolic = %Float.loc4_44.1 (constants.%Float)] {
+// CHECK:STDOUT:       %Core.ref.loc4_32: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]
+// CHECK:STDOUT:       %Float.ref: %Float.type = name_ref Float, imports.%Core.Float [concrete = constants.%Float.generic]
+// CHECK:STDOUT:       %N.ref.loc4: Core.IntLiteral = name_ref N, %N.loc4_6.2 [symbolic = %N.loc4_6.1 (constants.%N)]
+// CHECK:STDOUT:       %Float.loc4_44.2: type = class_type @Float, @Float(constants.%N) [symbolic = %Float.loc4_44.1 (constants.%Float)]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %n: <error> = bind_name n, %n.param
+// CHECK:STDOUT:     %n: @F.%Float.loc4_44.1 (%Float) = bind_name n, %n.param
 // CHECK:STDOUT:     %return.param: ref Core.IntLiteral = out_param call_param1
 // CHECK:STDOUT:     %return: ref Core.IntLiteral = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {
-// CHECK:STDOUT:     %a.patt: %pattern_type.3de = binding_pattern a [concrete]
-// CHECK:STDOUT:     %a.param_patt: %pattern_type.3de = value_param_pattern %a.patt, call_param0 [concrete]
+// CHECK:STDOUT:     %a.patt: %pattern_type.0ae = binding_pattern a [concrete]
+// CHECK:STDOUT:     %a.param_patt: %pattern_type.0ae = value_param_pattern %a.patt, call_param0 [concrete]
 // CHECK:STDOUT:     %return.patt: %pattern_type.dc0 = return_slot_pattern [concrete]
 // CHECK:STDOUT:     %return.param_patt: %pattern_type.dc0 = out_param_pattern %return.patt, call_param1 [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]
 // CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]
 // CHECK:STDOUT:     %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]
-// CHECK:STDOUT:     %.loc13_33.1: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]
-// CHECK:STDOUT:     %.loc13_33.2: type = converted %IntLiteral.call, %.loc13_33.1 [concrete = Core.IntLiteral]
-// CHECK:STDOUT:     %a.param: f64 = value_param call_param0
-// CHECK:STDOUT:     %.loc13_9.1: type = splice_block %.loc13_9.3 [concrete = f64] {
+// CHECK:STDOUT:     %.loc8_33.1: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]
+// CHECK:STDOUT:     %.loc8_33.2: type = converted %IntLiteral.call, %.loc8_33.1 [concrete = Core.IntLiteral]
+// CHECK:STDOUT:     %a.param: %f64.d77 = value_param call_param0
+// CHECK:STDOUT:     %.loc8_9: type = splice_block %f64 [concrete = constants.%f64.d77] {
 // CHECK:STDOUT:       %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:       %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:       %.loc13_9.2: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:       %.loc13_9.3: type = converted %Float.call, %.loc13_9.2 [concrete = f64]
+// CHECK:STDOUT:       %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %a: f64 = bind_name a, %a.param
+// CHECK:STDOUT:     %a: %f64.d77 = bind_name a, %a.param
 // CHECK:STDOUT:     %return.param: ref Core.IntLiteral = out_param call_param1
 // CHECK:STDOUT:     %return: ref Core.IntLiteral = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic fn @F(%N.loc9_6.2: Core.IntLiteral) {
-// CHECK:STDOUT:   %N.loc9_6.1: Core.IntLiteral = bind_symbolic_name N, 0 [symbolic = %N.loc9_6.1 (constants.%N)]
+// CHECK:STDOUT: generic fn @F(%N.loc4_6.2: Core.IntLiteral) {
+// CHECK:STDOUT:   %N.loc4_6.1: Core.IntLiteral = bind_symbolic_name N, 0 [symbolic = %N.loc4_6.1 (constants.%N)]
+// CHECK:STDOUT:   %Float.loc4_44.1: type = class_type @Float, @Float(%N.loc4_6.1) [symbolic = %Float.loc4_44.1 (constants.%Float)]
+// CHECK:STDOUT:   %pattern_type: type = pattern_type %Float.loc4_44.1 [symbolic = %pattern_type (constants.%pattern_type.f08)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Float.loc4_44.1 [symbolic = %require_complete (constants.%require_complete.957)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%n.param: <error>) -> Core.IntLiteral {
+// CHECK:STDOUT:   fn(%n.param: @F.%Float.loc4_44.1 (%Float)) -> Core.IntLiteral {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %N.ref.loc10: Core.IntLiteral = name_ref N, %N.loc9_6.2 [symbolic = %N.loc9_6.1 (constants.%N)]
-// CHECK:STDOUT:     return %N.ref.loc10
+// CHECK:STDOUT:     %N.ref.loc5: Core.IntLiteral = name_ref N, %N.loc4_6.2 [symbolic = %N.loc4_6.1 (constants.%N)]
+// CHECK:STDOUT:     return %N.ref.loc5
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @G(%a.param: f64) -> Core.IntLiteral {
+// CHECK:STDOUT: fn @G(%a.param: %f64.d77) -> Core.IntLiteral {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
-// CHECK:STDOUT:   %a.ref: f64 = name_ref a, %a
-// CHECK:STDOUT:   return <error>
+// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a
+// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%int_64) [concrete = constants.%F.specific_fn]
+// CHECK:STDOUT:   %F.call: init Core.IntLiteral = call %F.specific_fn(%a.ref)
+// CHECK:STDOUT:   %.loc9_14.1: Core.IntLiteral = value_of_initializer %F.call
+// CHECK:STDOUT:   %.loc9_14.2: Core.IntLiteral = converted %F.call, %.loc9_14.1
+// CHECK:STDOUT:   return %.loc9_14.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F(constants.%N) {
-// CHECK:STDOUT:   %N.loc9_6.1 => constants.%N
+// CHECK:STDOUT:   %N.loc4_6.1 => constants.%N
+// CHECK:STDOUT:   %Float.loc4_44.1 => constants.%Float
+// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.f08
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @F(constants.%int_64) {
+// CHECK:STDOUT:   %N.loc4_6.1 => constants.%int_64
+// CHECK:STDOUT:   %Float.loc4_44.1 => constants.%f64.d77
+// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.0ae
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.3f9
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 4
toolchain/check/testdata/function/call/fail_param_type.carbon

@@ -15,10 +15,10 @@
 fn G(a: i32) {}
 
 fn F() {
-  // CHECK:STDERR: fail_param_type.carbon:[[@LINE+10]]:5: error: cannot implicitly convert expression of type `f64` to `i32` [ConversionFailure]
+  // CHECK:STDERR: fail_param_type.carbon:[[@LINE+10]]:5: error: cannot implicitly convert expression of type `Core.FloatLiteral` to `i32` [ConversionFailure]
   // CHECK:STDERR:   G(1.0);
   // CHECK:STDERR:     ^~~
-  // CHECK:STDERR: fail_param_type.carbon:[[@LINE+7]]:5: note: type `f64` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote]
+  // CHECK:STDERR: fail_param_type.carbon:[[@LINE+7]]:5: note: type `Core.FloatLiteral` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote]
   // CHECK:STDERR:   G(1.0);
   // CHECK:STDERR:     ^~~
   // CHECK:STDERR: fail_param_type.carbon:[[@LINE-9]]:6: note: initializing function parameter [InCallToFunctionParam]
@@ -41,7 +41,7 @@ fn F() {
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 1 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
 // CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -86,7 +86,7 @@ fn F() {
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]
-// CHECK:STDOUT:   %float: f64 = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
 // CHECK:STDOUT:   %.loc28: %i32 = converted %float, <error> [concrete = <error>]
 // CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.ref(<error>)
 // CHECK:STDOUT:   return

+ 43 - 22
toolchain/check/testdata/function/call/fail_return_type_mismatch.carbon

@@ -29,13 +29,30 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
-// CHECK:STDOUT:   %pattern_type.3de: type = pattern_type f64 [concrete]
-// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]
+// CHECK:STDOUT:   %Float.type: type = generic_class_type @Float [concrete]
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
+// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]
 // CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 1 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
+// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
+// CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness.857: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.f22, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
+// CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]
 // CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
@@ -43,9 +60,6 @@ fn Run() {
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
-// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
-// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
-// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
 // CHECK:STDOUT:   %T.as.Destroy.impl.Op.type.a17: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%i32) [concrete]
 // CHECK:STDOUT:   %T.as.Destroy.impl.Op.e6a: %T.as.Destroy.impl.Op.type.a17 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
@@ -55,15 +69,17 @@ fn Run() {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Float = %Core.Float
-// CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float]
-// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
+// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float.generic]
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
+// CHECK:STDOUT:   %Core.import_ref.c0c: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644) = import_ref Core//prelude/parts/float, loc15_41, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45)]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.f22 = impl_witness_table (%Core.import_ref.c0c), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]
+// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
 // CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -75,23 +91,28 @@ fn Run() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {
-// CHECK:STDOUT:     %return.patt: %pattern_type.3de = return_slot_pattern [concrete]
-// CHECK:STDOUT:     %return.param_patt: %pattern_type.3de = out_param_pattern %return.patt, call_param0 [concrete]
+// CHECK:STDOUT:     %return.patt: %pattern_type.0ae = return_slot_pattern [concrete]
+// CHECK:STDOUT:     %return.param_patt: %pattern_type.0ae = out_param_pattern %return.patt, call_param0 [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:     %.loc15_13.1: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:     %.loc15_13.2: type = converted %Float.call, %.loc15_13.1 [concrete = f64]
-// CHECK:STDOUT:     %return.param: ref f64 = out_param call_param0
-// CHECK:STDOUT:     %return: ref f64 = return_slot %return.param
+// CHECK:STDOUT:     %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:     %return.param: ref %f64.d77 = out_param call_param0
+// CHECK:STDOUT:     %return: ref %f64.d77 = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Foo() -> f64 {
+// CHECK:STDOUT: fn @Foo() -> %f64.d77 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: f64 = float_value 1 [concrete = constants.%float]
-// CHECK:STDOUT:   return %float
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %impl.elem0: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
+// CHECK:STDOUT:   %bound_method.loc15_29.1: <bound method> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc15_29.2: <bound method> = bound_method %float, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc15_29.2(%float) [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc15_29.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc15_29.2: %f64.d77 = converted %float, %.loc15_29.1 [concrete = constants.%float]
+// CHECK:STDOUT:   return %.loc15_29.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
@@ -102,7 +123,7 @@ fn Run() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x.var: ref %i32 = var %x.var_patt
 // CHECK:STDOUT:   %Foo.ref: %Foo.type = name_ref Foo, file.%Foo.decl [concrete = constants.%Foo]
-// CHECK:STDOUT:   %Foo.call: init f64 = call %Foo.ref()
+// CHECK:STDOUT:   %Foo.call: init %f64.d77 = call %Foo.ref()
 // CHECK:STDOUT:   %.loc25_3: %i32 = converted %Foo.call, <error> [concrete = <error>]
 // CHECK:STDOUT:   assign %x.var, <error>
 // CHECK:STDOUT:   %.loc25_10: type = splice_block %i32 [concrete = constants.%i32] {

+ 7 - 8
toolchain/check/testdata/impl/fail_impl_bad_interface.carbon

@@ -135,8 +135,9 @@ impl {.a: bool} as type where .Self impls I {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Float.type: type = generic_class_type @Float [concrete]
+// CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %f64: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %.Self: type = bind_symbolic_name .Self [symbolic_self]
 // CHECK:STDOUT:   %type: type = facet_type <type> [concrete]
 // CHECK:STDOUT: }
@@ -147,7 +148,7 @@ impl {.a: bool} as type where .Self impls I {}
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float]
+// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float.generic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -157,19 +158,17 @@ impl {.a: bool} as type where .Self impls I {}
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   impl_decl @f64.as.<error>.impl [concrete] {} {
 // CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:     %.loc8_6.1: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:     %.loc8_6.2: type = converted %Float.call, %.loc8_6.1 [concrete = f64]
+// CHECK:STDOUT:     %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64]
 // CHECK:STDOUT:     %.Self: type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
 // CHECK:STDOUT:     %.Self.ref: type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
-// CHECK:STDOUT:     %.loc8_18: type = where_expr %.Self [concrete = constants.%type] {
+// CHECK:STDOUT:     %.loc8: type = where_expr %.Self [concrete = constants.%type] {
 // CHECK:STDOUT:       requirement_base_facet_type type
 // CHECK:STDOUT:       requirement_impls %.Self.ref, type
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @f64.as.<error>.impl: %.loc8_6.2 as %.loc8_18 {
+// CHECK:STDOUT: impl @f64.as.<error>.impl: %f64 as %.loc8 {
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   witness = <error>
 // CHECK:STDOUT: }

+ 4 - 4
toolchain/check/testdata/index/fail_array_non_int_indexing.carbon

@@ -13,10 +13,10 @@
 // TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/index/fail_array_non_int_indexing.carbon
 
 var a: array(i32, 1) = (12,);
-// CHECK:STDERR: fail_array_non_int_indexing.carbon:[[@LINE+7]]:16: error: cannot implicitly convert expression of type `f64` to `i32` [ConversionFailure]
+// CHECK:STDERR: fail_array_non_int_indexing.carbon:[[@LINE+7]]:16: error: cannot implicitly convert expression of type `Core.FloatLiteral` to `i32` [ConversionFailure]
 // CHECK:STDERR: var b: i32 = a[2.6];
 // CHECK:STDERR:                ^~~
-// CHECK:STDERR: fail_array_non_int_indexing.carbon:[[@LINE+4]]:16: note: type `f64` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote]
+// CHECK:STDERR: fail_array_non_int_indexing.carbon:[[@LINE+4]]:16: note: type `Core.FloatLiteral` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote]
 // CHECK:STDERR: var b: i32 = a[2.6];
 // CHECK:STDERR:                ^~~
 // CHECK:STDERR:
@@ -53,7 +53,7 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_12.6a3, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_12.1e1: %i32 = int_value 12 [concrete]
 // CHECK:STDOUT:   %array: %array_type = tuple_value (%int_12.1e1) [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 2.6000000000000001 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 2.6000000000000001 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -117,7 +117,7 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:   %.loc15_1: init %array_type = converted %.loc15_28.1, %.loc15_28.5 [concrete = constants.%array]
 // CHECK:STDOUT:   assign file.%a.var, %.loc15_1
 // CHECK:STDOUT:   %a.ref: ref %array_type = name_ref a, file.%a [concrete = file.%a.var]
-// CHECK:STDOUT:   %float: f64 = float_value 2.6000000000000001 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 2.6000000000000001 [concrete = constants.%float]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
 // CHECK:STDOUT:   %.loc23_16: %i32 = converted %float, <error> [concrete = <error>]

+ 45 - 29
toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon

@@ -1336,16 +1336,28 @@ fn F() {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %foo.type: type = fn_type @foo [concrete]
 // CHECK:STDOUT:   %foo: %foo.type = struct_value () [concrete]
-// CHECK:STDOUT:   %ptr.ef1: type = ptr_type f64 [concrete]
+// CHECK:STDOUT:   %ptr.bcc: type = ptr_type %f64.d77 [concrete]
 // CHECK:STDOUT:   %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
 // CHECK:STDOUT:   %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 0.80000000000000004 [concrete]
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.type.3ef: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(f64) [concrete]
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.868: %T.as.Destroy.impl.Op.type.3ef = struct_value () [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0.80000000000000004 [concrete]
+// CHECK:STDOUT:   %As.type.6d2: type = facet_type <@As, @As(%f64.d77)> [concrete]
+// CHECK:STDOUT:   %As.Convert.type.8fc: type = fn_type @As.Convert, @As(%f64.d77) [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.type.6a5: type = fn_type @Core.FloatLiteral.as.As.impl.Convert, @Core.FloatLiteral.as.As.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.6af: %Core.FloatLiteral.as.As.impl.Convert.type.6a5 = struct_value () [symbolic]
+// CHECK:STDOUT:   %As.impl_witness.a23: <witness> = impl_witness imports.%As.impl_witness_table, @Core.FloatLiteral.as.As.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.type.12c: type = fn_type @Core.FloatLiteral.as.As.impl.Convert, @Core.FloatLiteral.as.As.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.6ae: %Core.FloatLiteral.as.As.impl.Convert.type.12c = struct_value () [concrete]
+// CHECK:STDOUT:   %As.facet: %As.type.6d2 = facet_value Core.FloatLiteral, (%As.impl_witness.a23) [concrete]
+// CHECK:STDOUT:   %.d03: type = fn_type_with_self_type %As.Convert.type.8fc, %As.facet [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.bound: <bound method> = bound_method %float, %Core.FloatLiteral.as.As.impl.Convert.6ae [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.As.impl.Convert.6ae, @Core.FloatLiteral.as.As.impl.Convert(%int_64) [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float, %Core.FloatLiteral.as.As.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.type.efe: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%f64.d77) [concrete]
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.c51: %T.as.Destroy.impl.Op.type.efe = struct_value () [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -1363,26 +1375,33 @@ fn F() {
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     <elided>
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core.import_ref.2c9: @Core.FloatLiteral.as.As.impl.%Core.FloatLiteral.as.As.impl.Convert.type (%Core.FloatLiteral.as.As.impl.Convert.type.6a5) = import_ref Core//prelude/parts/float, loc20_41, loaded [symbolic = @Core.FloatLiteral.as.As.impl.%Core.FloatLiteral.as.As.impl.Convert (constants.%Core.FloatLiteral.as.As.impl.Convert.6af)]
+// CHECK:STDOUT:   %As.impl_witness_table = impl_witness_table (%Core.import_ref.2c9), @Core.FloatLiteral.as.As.impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
-// CHECK:STDOUT:   %float: f64 = float_value 0.80000000000000004 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0.80000000000000004 [concrete = constants.%float]
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:   %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:   %.loc8_18.1: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:   %.loc8_18.2: type = converted %Float.call, %.loc8_18.1 [concrete = f64]
-// CHECK:STDOUT:   %.loc8_11.1: ref f64 = temporary_storage
-// CHECK:STDOUT:   %.loc8_11.2: ref f64 = temporary %.loc8_11.1, %float
-// CHECK:STDOUT:   %addr.loc8_21: %ptr.ef1 = addr_of %.loc8_11.2
+// CHECK:STDOUT:   %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:   %impl.elem0: %.d03 = impl_witness_access constants.%As.impl_witness.a23, element0 [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.6ae]
+// CHECK:STDOUT:   %bound_method.loc8_15.1: <bound method> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.bound]
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.As.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc8_15.2: <bound method> = bound_method %float, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.call: init %f64.d77 = call %bound_method.loc8_15.2(%float) [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc8_15.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.As.impl.Convert.call [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc8_15.2: %f64.d77 = converted %float, %.loc8_15.1 [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc8_15.3: ref %f64.d77 = temporary_storage
+// CHECK:STDOUT:   %.loc8_15.4: ref %f64.d77 = temporary %.loc8_15.3, %.loc8_15.2
+// CHECK:STDOUT:   %addr.loc8_21: %ptr.bcc = addr_of %.loc8_15.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_21)
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_11.1, constants.%T.as.Destroy.impl.Op.868
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_15.3, constants.%T.as.Destroy.impl.Op.c51
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %.loc8_11.1, %T.as.Destroy.impl.Op.specific_fn
-// CHECK:STDOUT:   %addr.loc8_11: %ptr.ef1 = addr_of %.loc8_11.1
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr.loc8_11)
+// CHECK:STDOUT:   %bound_method.loc8_15.3: <bound method> = bound_method %.loc8_15.3, %T.as.Destroy.impl.Op.specific_fn
+// CHECK:STDOUT:   %addr.loc8_15: %ptr.bcc = addr_of %.loc8_15.3
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc8_15.3(%addr.loc8_15)
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -1565,9 +1584,8 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
-// CHECK:STDOUT:   %pattern_type.3de: type = pattern_type f64 [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
 // CHECK:STDOUT:   %foo_double.type: type = fn_type @foo_double [concrete]
 // CHECK:STDOUT:   %foo_double: %foo_double.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -1587,20 +1605,18 @@ fn F() {
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   name_binding_decl {
-// CHECK:STDOUT:     %x.patt: %pattern_type.3de = binding_pattern x [concrete]
+// CHECK:STDOUT:     %x.patt: %pattern_type.0ae = binding_pattern x [concrete]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %foo_double.ref: %foo_double.type = name_ref foo_double, imports.%foo_double.decl [concrete = constants.%foo_double]
-// CHECK:STDOUT:   %foo_double.call: init f64 = call %foo_double.ref()
-// CHECK:STDOUT:   %.loc8_10.1: type = splice_block %.loc8_10.3 [concrete = f64] {
+// CHECK:STDOUT:   %foo_double.call: init %f64.d77 = call %foo_double.ref()
+// CHECK:STDOUT:   %.loc8_10: type = splice_block %f64 [concrete = constants.%f64.d77] {
 // CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:     %.loc8_10.2: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:     %.loc8_10.3: type = converted %Float.call, %.loc8_10.2 [concrete = f64]
+// CHECK:STDOUT:     %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc8_31.1: f64 = value_of_initializer %foo_double.call
-// CHECK:STDOUT:   %.loc8_31.2: f64 = converted %foo_double.call, %.loc8_31.1
-// CHECK:STDOUT:   %x: f64 = bind_name x, %.loc8_31.2
+// CHECK:STDOUT:   %.loc8_31.1: %f64.d77 = value_of_initializer %foo_double.call
+// CHECK:STDOUT:   %.loc8_31.2: %f64.d77 = converted %foo_double.call, %.loc8_31.1
+// CHECK:STDOUT:   %x: %f64.d77 = bind_name x, %.loc8_31.2
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 4
toolchain/check/testdata/interop/cpp/function/param_unsupported.carbon

@@ -67,7 +67,7 @@ fn F() {
 // CHECK:STDOUT: --- fail_todo_import_unsupported_primitive_type.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %float: f64 = float_value 1.1000000000000001 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1.1000000000000001 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -81,7 +81,7 @@ fn F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
-// CHECK:STDOUT:   %float: f64 = float_value 1.1000000000000001 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1.1000000000000001 [concrete = constants.%float]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -89,7 +89,7 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 2 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 2 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -104,7 +104,7 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]
-// CHECK:STDOUT:   %float: f64 = float_value 2 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 2 [concrete = constants.%float]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 10 - 16
toolchain/check/testdata/operators/builtin/fail_and_or_not_in_function.carbon

@@ -93,8 +93,7 @@ fn F() {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %f64: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%b.param: bool) -> type {
@@ -109,14 +108,12 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.else:
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:   %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:   %.loc6_24.1: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:   %.loc6_24.2: type = converted %Float.call, %.loc6_24.1 [concrete = f64]
-// CHECK:STDOUT:   br !if.expr.result(%.loc6_24.2)
+// CHECK:STDOUT:   %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64]
+// CHECK:STDOUT:   br !if.expr.result(%f64)
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.result:
-// CHECK:STDOUT:   %.loc6_10: type = block_arg !if.expr.result
-// CHECK:STDOUT:   return %.loc6_10
+// CHECK:STDOUT:   %.loc6: type = block_arg !if.expr.result
+// CHECK:STDOUT:   return %.loc6
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_and_val.carbon
@@ -130,8 +127,7 @@ fn F() {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %f64: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%b.param: bool) -> type {
@@ -146,14 +142,12 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.else:
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:   %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:   %.loc6_24.1: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:   %.loc6_24.2: type = converted %Float.call, %.loc6_24.1 [concrete = f64]
-// CHECK:STDOUT:   br !if.expr.result(%.loc6_24.2)
+// CHECK:STDOUT:   %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64]
+// CHECK:STDOUT:   br !if.expr.result(%f64)
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.result:
-// CHECK:STDOUT:   %.loc6_10: type = block_arg !if.expr.result
-// CHECK:STDOUT:   return %.loc6_10
+// CHECK:STDOUT:   %.loc6: type = block_arg !if.expr.result
+// CHECK:STDOUT:   return %.loc6
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_or_val.carbon

+ 4 - 4
toolchain/check/testdata/operators/builtin/fail_type_mismatch_assignment.carbon

@@ -14,10 +14,10 @@
 
 fn Main() {
   var a: i32 = 3;
-  // CHECK:STDERR: fail_type_mismatch_assignment.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `f64` to `i32` [ConversionFailure]
+  // CHECK:STDERR: fail_type_mismatch_assignment.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `Core.FloatLiteral` to `i32` [ConversionFailure]
   // CHECK:STDERR:   a = 5.6;
   // CHECK:STDERR:   ^~~~~~~
-  // CHECK:STDERR: fail_type_mismatch_assignment.carbon:[[@LINE+4]]:3: note: type `f64` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote]
+  // CHECK:STDERR: fail_type_mismatch_assignment.carbon:[[@LINE+4]]:3: note: type `Core.FloatLiteral` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote]
   // CHECK:STDERR:   a = 5.6;
   // CHECK:STDERR:   ^~~~~~~
   // CHECK:STDERR:
@@ -53,7 +53,7 @@ fn Main() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.956, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 5.6000000000000005 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 5.6000000000000005 [concrete]
 // CHECK:STDOUT:   %T.as.Destroy.impl.Op.type.a17: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%i32) [concrete]
 // CHECK:STDOUT:   %T.as.Destroy.impl.Op.e6a: %T.as.Destroy.impl.Op.type.a17 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
@@ -105,7 +105,7 @@ fn Main() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %i32 = bind_name a, %a.var
 // CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a
-// CHECK:STDOUT:   %float: f64 = float_value 5.6000000000000005 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 5.6000000000000005 [concrete = constants.%float]
 // CHECK:STDOUT:   %.loc24: %i32 = converted %float, <error> [concrete = <error>]
 // CHECK:STDOUT:   assign %a.ref, <error>
 // CHECK:STDOUT:   %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %a.var, constants.%T.as.Destroy.impl.Op.e6a

+ 3 - 3
toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon

@@ -15,7 +15,7 @@
 fn Main() -> i32 {
   // The following line has two mismatches, but after the first, it shouldn't
   // keep erroring.
-  // CHECK:STDERR: fail_type_mismatch_once.carbon:[[@LINE+4]]:10: error: cannot access member of interface `Core.AddWith(f64)` in type `{}` that does not implement that interface [MissingImplInMemberAccess]
+  // CHECK:STDERR: fail_type_mismatch_once.carbon:[[@LINE+4]]:10: error: cannot access member of interface `Core.AddWith(Core.FloatLiteral)` in type `{}` that does not implement that interface [MissingImplInMemberAccess]
   // CHECK:STDERR:   return {} + 3.4 + 12;
   // CHECK:STDERR:          ^~~~~~~~
   // CHECK:STDERR:
@@ -33,7 +33,7 @@ fn Main() -> i32 {
 // CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]
 // CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 3.4000000000000004 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 3.4000000000000004 [concrete]
 // CHECK:STDOUT:   %AddWith.type.e05: type = generic_interface_type @AddWith [concrete]
 // CHECK:STDOUT:   %AddWith.generic: %AddWith.type.e05 = struct_value () [concrete]
 // CHECK:STDOUT:   %int_12: Core.IntLiteral = int_value 12 [concrete]
@@ -70,7 +70,7 @@ fn Main() -> i32 {
 // CHECK:STDOUT: fn @Main() -> %i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc22: %empty_struct_type = struct_literal ()
-// CHECK:STDOUT:   %float: f64 = float_value 3.4000000000000004 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 3.4000000000000004 [concrete = constants.%float]
 // CHECK:STDOUT:   %int_12: Core.IntLiteral = int_value 12 [concrete = constants.%int_12]
 // CHECK:STDOUT:   %impl.elem1: <error> = impl_witness_access <error>, element1 [concrete = <error>]
 // CHECK:STDOUT:   return <error>

+ 4 - 4
toolchain/check/testdata/pointer/fail_address_of_value.carbon

@@ -125,8 +125,8 @@ fn AddressOfParam(param: i32) {
 // CHECK:STDOUT:   %ptr.1d1: type = ptr_type Core.IntLiteral [concrete]
 // CHECK:STDOUT:   %true: bool = bool_literal true [concrete]
 // CHECK:STDOUT:   %ptr.bb2: type = ptr_type bool [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 1 [concrete]
-// CHECK:STDOUT:   %ptr.ef1: type = ptr_type f64 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %ptr.5f5: type = ptr_type Core.FloatLiteral [concrete]
 // CHECK:STDOUT:   %ptr.a45: type = ptr_type String [concrete]
 // CHECK:STDOUT:   %str: String = string_literal "Hello" [concrete]
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]
@@ -235,8 +235,8 @@ fn AddressOfParam(param: i32) {
 // CHECK:STDOUT:   %addr.loc24: %ptr.1d1 = addr_of <error> [concrete = <error>]
 // CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]
 // CHECK:STDOUT:   %addr.loc29: %ptr.bb2 = addr_of <error> [concrete = <error>]
-// CHECK:STDOUT:   %float: f64 = float_value 1 [concrete = constants.%float]
-// CHECK:STDOUT:   %addr.loc34: %ptr.ef1 = addr_of <error> [concrete = <error>]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %addr.loc34: %ptr.5f5 = addr_of <error> [concrete = <error>]
 // CHECK:STDOUT:   %str: String = string_literal "Hello" [concrete = constants.%str]
 // CHECK:STDOUT:   %addr.loc39: %ptr.a45 = addr_of <error> [concrete = <error>]
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]

+ 49 - 25
toolchain/check/testdata/return/fail_returned_var_type.carbon

@@ -36,27 +36,47 @@ fn Mismatch() -> i32 {
 // CHECK:STDOUT:   %Mismatch.type: type = fn_type @Mismatch [concrete]
 // CHECK:STDOUT:   %Mismatch: %Mismatch.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
-// CHECK:STDOUT:   %pattern_type.3de: type = pattern_type f64 [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 0 [concrete]
+// CHECK:STDOUT:   %Float.type: type = generic_class_type @Float [concrete]
+// CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
+// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
+// CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
 // CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.type.3ef: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(f64) [concrete]
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.868: %T.as.Destroy.impl.Op.type.3ef = struct_value () [concrete]
-// CHECK:STDOUT:   %ptr.ef1: type = ptr_type f64 [concrete]
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function %T.as.Destroy.impl.Op.868, @T.as.Destroy.impl.Op(f64) [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness.857: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
+// CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.type.efe: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%f64.d77) [concrete]
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.c51: %T.as.Destroy.impl.Op.type.efe = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.bcc: type = ptr_type %f64.d77 [concrete]
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function %T.as.Destroy.impl.Op.c51, @T.as.Destroy.impl.Op(%f64.d77) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .Float = %Core.Float
+// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
 // CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
-// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float]
+// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float.generic]
+// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
+// CHECK:STDOUT:   %Core.import_ref.c0c: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644) = import_ref Core//prelude/parts/float, loc15_41, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45)]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.c0c), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]
 // CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -80,25 +100,29 @@ fn Mismatch() -> i32 {
 // CHECK:STDOUT: fn @Mismatch() -> %i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   name_binding_decl {
-// CHECK:STDOUT:     %v.patt: %pattern_type.3de = binding_pattern v [concrete]
-// CHECK:STDOUT:     %v.var_patt: %pattern_type.3de = var_pattern %v.patt [concrete]
+// CHECK:STDOUT:     %v.patt: %pattern_type.0ae = binding_pattern v [concrete]
+// CHECK:STDOUT:     %v.var_patt: %pattern_type.0ae = var_pattern %v.patt [concrete]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %v.var: ref f64 = var %v.var_patt
-// CHECK:STDOUT:   %float: f64 = float_value 0 [concrete = constants.%float]
-// CHECK:STDOUT:   assign %v.var, %float
-// CHECK:STDOUT:   %.loc23_19.1: type = splice_block %.loc23_19.3 [concrete = f64] {
+// CHECK:STDOUT:   %v.var: ref %f64.d77 = var %v.var_patt
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0 [concrete = constants.%float]
+// CHECK:STDOUT:   %impl.elem0: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
+// CHECK:STDOUT:   %bound_method.loc23_12.1: <bound method> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc23_12.2: <bound method> = bound_method %float, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc23_12.2(%float) [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc23_12: init %f64.d77 = converted %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float]
+// CHECK:STDOUT:   assign %v.var, %.loc23_12
+// CHECK:STDOUT:   %.loc23_19: type = splice_block %f64 [concrete = constants.%f64.d77] {
 // CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:     %.loc23_19.2: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:     %.loc23_19.3: type = converted %Float.call, %.loc23_19.2 [concrete = f64]
+// CHECK:STDOUT:     %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %v: ref f64 = bind_name v, %v.var
-// CHECK:STDOUT:   %.loc23_16: f64 = bind_value %v
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %v.var, constants.%T.as.Destroy.impl.Op.868
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.Destroy.impl.Op.868, @T.as.Destroy.impl.Op(f64) [concrete = constants.%T.as.Destroy.impl.Op.specific_fn]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %v.var, %T.as.Destroy.impl.Op.specific_fn
-// CHECK:STDOUT:   %addr: %ptr.ef1 = addr_of %v.var
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr)
+// CHECK:STDOUT:   %v: ref %f64.d77 = bind_name v, %v.var
+// CHECK:STDOUT:   %.loc23_16: %f64.d77 = bind_value %v
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %v.var, constants.%T.as.Destroy.impl.Op.c51
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.Destroy.impl.Op.c51, @T.as.Destroy.impl.Op(constants.%f64.d77) [concrete = constants.%T.as.Destroy.impl.Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc23_12.3: <bound method> = bound_method %v.var, %T.as.Destroy.impl.Op.specific_fn
+// CHECK:STDOUT:   %addr: %ptr.bcc = addr_of %v.var
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc23_12.3(%addr)
 // CHECK:STDOUT:   return %.loc23_16
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 4
toolchain/check/testdata/return/fail_type_mismatch.carbon

@@ -13,10 +13,10 @@
 // TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/return/fail_type_mismatch.carbon
 
 fn Main() -> i32 {
-  // CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `f64` to `i32` [ConversionFailure]
+  // CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `Core.FloatLiteral` to `i32` [ConversionFailure]
   // CHECK:STDERR:   return 1.0;
   // CHECK:STDERR:   ^~~~~~~~~~~
-  // CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+4]]:3: note: type `f64` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote]
+  // CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+4]]:3: note: type `Core.FloatLiteral` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote]
   // CHECK:STDERR:   return 1.0;
   // CHECK:STDERR:   ^~~~~~~~~~~
   // CHECK:STDERR:
@@ -33,7 +33,7 @@ fn Main() -> i32 {
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
 // CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]
 // CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 1 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
 // CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -68,7 +68,7 @@ fn Main() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Main() -> %i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: f64 = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
 // CHECK:STDOUT:   %.loc23: %i32 = converted %float, <error> [concrete = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }

+ 3 - 3
toolchain/check/testdata/struct/fail_field_type_mismatch.carbon

@@ -27,8 +27,8 @@ var x: {.a: i32} = {.b = 1.0};
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %i32} [concrete]
 // CHECK:STDOUT:   %pattern_type.268: type = pattern_type %struct_type.a [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 1 [concrete]
-// CHECK:STDOUT:   %struct_type.b: type = struct_type {.b: f64} [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %struct_type.b: type = struct_type {.b: Core.FloatLiteral} [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -61,7 +61,7 @@ var x: {.a: i32} = {.b = 1.0};
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: f64 = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
 // CHECK:STDOUT:   %.loc19: %struct_type.b = struct_literal (%float)
 // CHECK:STDOUT:   assign file.%x.var, <error>
 // CHECK:STDOUT:   return

+ 46 - 21
toolchain/check/testdata/struct/fail_member_access_type.carbon

@@ -23,12 +23,29 @@ var y: i32 = x.b;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
-// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: f64} [concrete]
-// CHECK:STDOUT:   %pattern_type.d08: type = pattern_type %struct_type.a [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 4 [concrete]
-// CHECK:STDOUT:   %struct: %struct_type.a = struct_value (%float) [concrete]
+// CHECK:STDOUT:   %Float.type: type = generic_class_type @Float [concrete]
+// CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %struct_type.a.5e8: type = struct_type {.a: %f64.d77} [concrete]
+// CHECK:STDOUT:   %pattern_type.8ce: type = pattern_type %struct_type.a.5e8 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 4 [concrete]
+// CHECK:STDOUT:   %struct_type.a.b4b: type = struct_type {.a: Core.FloatLiteral} [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
+// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
+// CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness.857: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
+// CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %struct: %struct_type.a.5e8 = struct_value (%float) [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
@@ -39,11 +56,15 @@ var y: i32 = x.b;
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Float = %Core.Float
+// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float]
+// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float.generic]
+// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
+// CHECK:STDOUT:   %Core.import_ref.c0c: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644) = import_ref Core//prelude/parts/float, loc15_41, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45)]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.c0c), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -55,18 +76,16 @@ var y: i32 = x.b;
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   name_binding_decl {
-// CHECK:STDOUT:     %x.patt: %pattern_type.d08 = binding_pattern x [concrete]
-// CHECK:STDOUT:     %x.var_patt: %pattern_type.d08 = var_pattern %x.patt [concrete]
+// CHECK:STDOUT:     %x.patt: %pattern_type.8ce = binding_pattern x [concrete]
+// CHECK:STDOUT:     %x.var_patt: %pattern_type.8ce = var_pattern %x.patt [concrete]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %x.var: ref %struct_type.a = var %x.var_patt [concrete]
-// CHECK:STDOUT:   %.loc15_16: type = splice_block %struct_type.a [concrete = constants.%struct_type.a] {
+// CHECK:STDOUT:   %x.var: ref %struct_type.a.5e8 = var %x.var_patt [concrete]
+// CHECK:STDOUT:   %.loc15: type = splice_block %struct_type.a [concrete = constants.%struct_type.a.5e8] {
 // CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:     %.loc15_13.1: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:     %.loc15_13.2: type = converted %Float.call, %.loc15_13.1 [concrete = f64]
-// CHECK:STDOUT:     %struct_type.a: type = struct_type {.a: f64} [concrete = constants.%struct_type.a]
+// CHECK:STDOUT:     %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:     %struct_type.a: type = struct_type {.a: %f64.d77} [concrete = constants.%struct_type.a.5e8]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %x: ref %struct_type.a = bind_name x, %x.var [concrete = %x.var]
+// CHECK:STDOUT:   %x: ref %struct_type.a.5e8 = bind_name x, %x.var [concrete = %x.var]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %y.patt: %pattern_type.7ce = binding_pattern y [concrete]
 // CHECK:STDOUT:     %y.var_patt: %pattern_type.7ce = var_pattern %y.patt [concrete]
@@ -81,12 +100,18 @@ var y: i32 = x.b;
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: f64 = float_value 4 [concrete = constants.%float]
-// CHECK:STDOUT:   %.loc15_29.1: %struct_type.a = struct_literal (%float)
-// CHECK:STDOUT:   %.loc15_29.2: init %struct_type.a = struct_init (%float) to file.%x.var [concrete = constants.%struct]
-// CHECK:STDOUT:   %.loc15_1: init %struct_type.a = converted %.loc15_29.1, %.loc15_29.2 [concrete = constants.%struct]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 4 [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc15_29.1: %struct_type.a.b4b = struct_literal (%float)
+// CHECK:STDOUT:   %impl.elem0: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
+// CHECK:STDOUT:   %bound_method.loc15_29.1: <bound method> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc15_29.2: <bound method> = bound_method %float, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc15_29.2(%float) [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc15_29.2: init %f64.d77 = converted %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc15_29.3: init %struct_type.a.5e8 = struct_init (%.loc15_29.2) to file.%x.var [concrete = constants.%struct]
+// CHECK:STDOUT:   %.loc15_1: init %struct_type.a.5e8 = converted %.loc15_29.1, %.loc15_29.3 [concrete = constants.%struct]
 // CHECK:STDOUT:   assign file.%x.var, %.loc15_1
-// CHECK:STDOUT:   %x.ref: ref %struct_type.a = name_ref x, file.%x [concrete = file.%x.var]
+// CHECK:STDOUT:   %x.ref: ref %struct_type.a.5e8 = name_ref x, file.%x [concrete = file.%x.var]
 // CHECK:STDOUT:   assign file.%y.var, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 58 - 39
toolchain/check/testdata/struct/member_access.carbon

@@ -20,37 +20,50 @@ var z: i32 = y;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Float.type: type = generic_class_type @Float [concrete]
+// CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
-// CHECK:STDOUT:   %struct_type.a.b.ddf: type = struct_type {.a: f64, .b: %i32} [concrete]
-// CHECK:STDOUT:   %pattern_type.7fd: type = pattern_type %struct_type.a.b.ddf [concrete]
-// CHECK:STDOUT:   %float: f64 = float_value 0 [concrete]
+// CHECK:STDOUT:   %struct_type.a.b.d2f: type = struct_type {.a: %f64.d77, .b: %i32} [concrete]
+// CHECK:STDOUT:   %pattern_type.a7a: type = pattern_type %struct_type.a.b.d2f [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0 [concrete]
 // CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
-// CHECK:STDOUT:   %struct_type.a.b.fbb: type = struct_type {.a: f64, .b: Core.IntLiteral} [concrete]
-// CHECK:STDOUT:   %.984: ref f64 = struct_access file.%x.var, element0 [concrete]
-// CHECK:STDOUT:   %.865: ref %i32 = struct_access file.%x.var, element1 [concrete]
+// CHECK:STDOUT:   %struct_type.a.b.0cc: type = struct_type {.a: Core.FloatLiteral, .b: Core.IntLiteral} [concrete]
+// CHECK:STDOUT:   %.bc0: ref %f64.d77 = struct_access file.%x.var, element0 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
 // CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
+// CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
+// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness.857: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.f22, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet.8d0: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
+// CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet.8d0 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
+// CHECK:STDOUT:   %bound_method.71f: <bound method> = bound_method %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %.a00: ref %i32 = struct_access file.%x.var, element1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.205: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]
 // CHECK:STDOUT:   %ImplicitAs.Convert.type.1b6: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%i32) [concrete]
-// CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.0f9: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.f06: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.0f9 = struct_value () [symbolic]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness.c75: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.a2f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.035: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.956: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.035 = struct_value () [concrete]
-// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.205 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.c75) [concrete]
-// CHECK:STDOUT:   %.9c3: type = fn_type_with_self_type %ImplicitAs.Convert.type.1b6, %ImplicitAs.facet [concrete]
+// CHECK:STDOUT:   %ImplicitAs.facet.921: %ImplicitAs.type.205 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.c75) [concrete]
+// CHECK:STDOUT:   %.9c3: type = fn_type_with_self_type %ImplicitAs.Convert.type.1b6, %ImplicitAs.facet.921 [concrete]
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.956 [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.956, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method.9a1: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]
-// CHECK:STDOUT:   %struct: %struct_type.a.b.ddf = struct_value (%float, %int_1.5d2) [concrete]
+// CHECK:STDOUT:   %struct: %struct_type.a.b.d2f = struct_value (%float, %int_1.5d2) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -61,9 +74,11 @@ var z: i32 = y;
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float]
+// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float.generic]
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
+// CHECK:STDOUT:   %Core.import_ref.c0c: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644) = import_ref Core//prelude/parts/float, loc15_41, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45)]
+// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.f22 = impl_witness_table (%Core.import_ref.c0c), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @Core.IntLiteral.as.ImplicitAs.impl [concrete]
 // CHECK:STDOUT: }
@@ -77,20 +92,18 @@ var z: i32 = y;
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   name_binding_decl {
-// CHECK:STDOUT:     %x.patt: %pattern_type.7fd = binding_pattern x [concrete]
-// CHECK:STDOUT:     %x.var_patt: %pattern_type.7fd = var_pattern %x.patt [concrete]
+// CHECK:STDOUT:     %x.patt: %pattern_type.a7a = binding_pattern x [concrete]
+// CHECK:STDOUT:     %x.var_patt: %pattern_type.a7a = var_pattern %x.patt [concrete]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %x.var: ref %struct_type.a.b.ddf = var %x.var_patt [concrete]
-// CHECK:STDOUT:   %.loc15_25: type = splice_block %struct_type.a.b [concrete = constants.%struct_type.a.b.ddf] {
+// CHECK:STDOUT:   %x.var: ref %struct_type.a.b.d2f = var %x.var_patt [concrete]
+// CHECK:STDOUT:   %.loc15: type = splice_block %struct_type.a.b [concrete = constants.%struct_type.a.b.d2f] {
 // CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:     %.loc15_13.1: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:     %.loc15_13.2: type = converted %Float.call, %.loc15_13.1 [concrete = f64]
+// CHECK:STDOUT:     %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
 // CHECK:STDOUT:     %int_32.loc15: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc15: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
-// CHECK:STDOUT:     %struct_type.a.b: type = struct_type {.a: f64, .b: %i32} [concrete = constants.%struct_type.a.b.ddf]
+// CHECK:STDOUT:     %struct_type.a.b: type = struct_type {.a: %f64.d77, .b: %i32} [concrete = constants.%struct_type.a.b.d2f]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %x: ref %struct_type.a.b.ddf = bind_name x, %x.var [concrete = %x.var]
+// CHECK:STDOUT:   %x: ref %struct_type.a.b.d2f = bind_name x, %x.var [concrete = %x.var]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %y.patt: %pattern_type.7ce = binding_pattern y [concrete]
 // CHECK:STDOUT:     %y.var_patt: %pattern_type.7ce = var_pattern %y.patt [concrete]
@@ -115,24 +128,30 @@ var z: i32 = y;
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: f64 = float_value 0 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0 [concrete = constants.%float]
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
-// CHECK:STDOUT:   %.loc15_46.1: %struct_type.a.b.fbb = struct_literal (%float, %int_1)
-// CHECK:STDOUT:   %.loc15_46.2: ref f64 = struct_access file.%x.var, element0 [concrete = constants.%.984]
-// CHECK:STDOUT:   %.loc15_46.3: init f64 = initialize_from %float to %.loc15_46.2 [concrete = constants.%float]
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.956]
-// CHECK:STDOUT:   %bound_method.loc15_46.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc15_46.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]
-// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc15_46.2(%int_1) [concrete = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc15_46.4: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc15_46.5: ref %i32 = struct_access file.%x.var, element1 [concrete = constants.%.865]
-// CHECK:STDOUT:   %.loc15_46.6: init %i32 = initialize_from %.loc15_46.4 to %.loc15_46.5 [concrete = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc15_46.7: init %struct_type.a.b.ddf = struct_init (%.loc15_46.3, %.loc15_46.6) to file.%x.var [concrete = constants.%struct]
-// CHECK:STDOUT:   %.loc15_1: init %struct_type.a.b.ddf = converted %.loc15_46.1, %.loc15_46.7 [concrete = constants.%struct]
+// CHECK:STDOUT:   %.loc15_46.1: %struct_type.a.b.0cc = struct_literal (%float, %int_1)
+// CHECK:STDOUT:   %impl.elem0.loc15_46.1: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
+// CHECK:STDOUT:   %bound_method.loc15_46.1: <bound method> = bound_method %float, %impl.elem0.loc15_46.1 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
+// CHECK:STDOUT:   %specific_fn.loc15_46.1: <specific function> = specific_function %impl.elem0.loc15_46.1, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc15_46.2: <bound method> = bound_method %float, %specific_fn.loc15_46.1 [concrete = constants.%bound_method.71f]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc15_46.2(%float) [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc15_46.2: init %f64.d77 = converted %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float]
+// CHECK:STDOUT:   %.loc15_46.3: ref %f64.d77 = struct_access file.%x.var, element0 [concrete = constants.%.bc0]
+// CHECK:STDOUT:   %.loc15_46.4: init %f64.d77 = initialize_from %.loc15_46.2 to %.loc15_46.3 [concrete = constants.%float]
+// CHECK:STDOUT:   %impl.elem0.loc15_46.2: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.956]
+// CHECK:STDOUT:   %bound_method.loc15_46.3: <bound method> = bound_method %int_1, %impl.elem0.loc15_46.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]
+// CHECK:STDOUT:   %specific_fn.loc15_46.2: <specific function> = specific_function %impl.elem0.loc15_46.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc15_46.4: <bound method> = bound_method %int_1, %specific_fn.loc15_46.2 [concrete = constants.%bound_method.9a1]
+// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc15_46.4(%int_1) [concrete = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc15_46.5: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc15_46.6: ref %i32 = struct_access file.%x.var, element1 [concrete = constants.%.a00]
+// CHECK:STDOUT:   %.loc15_46.7: init %i32 = initialize_from %.loc15_46.5 to %.loc15_46.6 [concrete = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc15_46.8: init %struct_type.a.b.d2f = struct_init (%.loc15_46.4, %.loc15_46.7) to file.%x.var [concrete = constants.%struct]
+// CHECK:STDOUT:   %.loc15_1: init %struct_type.a.b.d2f = converted %.loc15_46.1, %.loc15_46.8 [concrete = constants.%struct]
 // CHECK:STDOUT:   assign file.%x.var, %.loc15_1
-// CHECK:STDOUT:   %x.ref: ref %struct_type.a.b.ddf = name_ref x, file.%x [concrete = file.%x.var]
-// CHECK:STDOUT:   %.loc16_15.1: ref %i32 = struct_access %x.ref, element1 [concrete = constants.%.865]
+// CHECK:STDOUT:   %x.ref: ref %struct_type.a.b.d2f = name_ref x, file.%x [concrete = file.%x.var]
+// CHECK:STDOUT:   %.loc16_15.1: ref %i32 = struct_access %x.ref, element1 [concrete = constants.%.a00]
 // CHECK:STDOUT:   %.loc16_15.2: %i32 = bind_value %.loc16_15.1
 // CHECK:STDOUT:   assign file.%y.var, %.loc16_15.2
 // CHECK:STDOUT:   %y.ref: ref %i32 = name_ref y, file.%y [concrete = file.%y.var]

+ 32 - 39
toolchain/check/testdata/struct/reorder_fields.carbon

@@ -32,17 +32,18 @@ fn F() -> {.a: i32, .b: f64} {
 // CHECK:STDOUT:   %MakeI32.type: type = fn_type @MakeI32 [concrete]
 // CHECK:STDOUT:   %MakeI32: %MakeI32.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]
-// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]
-// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
-// CHECK:STDOUT:   %pattern_type.3de: type = pattern_type f64 [concrete]
+// CHECK:STDOUT:   %Float.type: type = generic_class_type @Float [concrete]
+// CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [concrete]
+// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
+// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
 // CHECK:STDOUT:   %MakeF64.type: type = fn_type @MakeF64 [concrete]
 // CHECK:STDOUT:   %MakeF64: %MakeF64.type = struct_value () [concrete]
-// CHECK:STDOUT:   %struct_type.a.b: type = struct_type {.a: %i32, .b: f64} [concrete]
-// CHECK:STDOUT:   %pattern_type.59f: type = pattern_type %struct_type.a.b [concrete]
+// CHECK:STDOUT:   %struct_type.a.b: type = struct_type {.a: %i32, .b: %f64.d77} [concrete]
+// CHECK:STDOUT:   %pattern_type.a5c: type = pattern_type %struct_type.a.b [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
-// CHECK:STDOUT:   %struct_type.b.a: type = struct_type {.b: f64, .a: %i32} [concrete]
-// CHECK:STDOUT:   %pattern_type.a24: type = pattern_type %struct_type.b.a [concrete]
+// CHECK:STDOUT:   %struct_type.b.a: type = struct_type {.b: %f64.d77, .a: %i32} [concrete]
+// CHECK:STDOUT:   %pattern_type.b43: type = pattern_type %struct_type.b.a [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -53,7 +54,7 @@ fn F() -> {.a: i32, .b: f64} {
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
-// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float]
+// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float.generic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -74,27 +75,23 @@ fn F() -> {.a: i32, .b: f64} {
 // CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %MakeF64.decl: %MakeF64.type = fn_decl @MakeF64 [concrete = constants.%MakeF64] {
-// CHECK:STDOUT:     %return.patt: %pattern_type.3de = return_slot_pattern [concrete]
-// CHECK:STDOUT:     %return.param_patt: %pattern_type.3de = out_param_pattern %return.patt, call_param0 [concrete]
+// CHECK:STDOUT:     %return.patt: %pattern_type.0ae = return_slot_pattern [concrete]
+// CHECK:STDOUT:     %return.param_patt: %pattern_type.0ae = out_param_pattern %return.patt, call_param0 [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
-// CHECK:STDOUT:     %.loc16_17.1: type = value_of_initializer %Float.call [concrete = f64]
-// CHECK:STDOUT:     %.loc16_17.2: type = converted %Float.call, %.loc16_17.1 [concrete = f64]
-// CHECK:STDOUT:     %return.param: ref f64 = out_param call_param0
-// CHECK:STDOUT:     %return: ref f64 = return_slot %return.param
+// CHECK:STDOUT:     %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:     %return.param: ref %f64.d77 = out_param call_param0
+// CHECK:STDOUT:     %return: ref %f64.d77 = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
-// CHECK:STDOUT:     %return.patt: %pattern_type.59f = return_slot_pattern [concrete]
-// CHECK:STDOUT:     %return.param_patt: %pattern_type.59f = out_param_pattern %return.patt, call_param0 [concrete]
+// CHECK:STDOUT:     %return.patt: %pattern_type.a5c = return_slot_pattern [concrete]
+// CHECK:STDOUT:     %return.param_patt: %pattern_type.a5c = out_param_pattern %return.patt, call_param0 [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int_32.loc18: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc18: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
 // CHECK:STDOUT:     %int_64.loc18: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call.loc18: init type = call constants.%Float(%int_64.loc18) [concrete = f64]
-// CHECK:STDOUT:     %.loc18_25.1: type = value_of_initializer %Float.call.loc18 [concrete = f64]
-// CHECK:STDOUT:     %.loc18_25.2: type = converted %Float.call.loc18, %.loc18_25.1 [concrete = f64]
-// CHECK:STDOUT:     %struct_type.a.b.loc18: type = struct_type {.a: %i32, .b: f64} [concrete = constants.%struct_type.a.b]
+// CHECK:STDOUT:     %f64.loc18: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:     %struct_type.a.b.loc18: type = struct_type {.a: %i32, .b: %f64.d77} [concrete = constants.%struct_type.a.b]
 // CHECK:STDOUT:     %return.param: ref %struct_type.a.b = out_param call_param0
 // CHECK:STDOUT:     %return: ref %struct_type.a.b = return_slot %return.param
 // CHECK:STDOUT:   }
@@ -102,15 +99,15 @@ fn F() -> {.a: i32, .b: f64} {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @MakeI32() -> %i32;
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @MakeF64() -> f64;
+// CHECK:STDOUT: fn @MakeF64() -> %f64.d77;
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() -> %return.param: %struct_type.a.b {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   name_binding_decl {
-// CHECK:STDOUT:     %x.patt: %pattern_type.59f = binding_pattern x [concrete]
+// CHECK:STDOUT:     %x.patt: %pattern_type.a5c = binding_pattern x [concrete]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %MakeF64.ref: %MakeF64.type = name_ref MakeF64, file.%MakeF64.decl [concrete = constants.%MakeF64]
-// CHECK:STDOUT:   %MakeF64.call: init f64 = call %MakeF64.ref()
+// CHECK:STDOUT:   %MakeF64.call: init %f64.d77 = call %MakeF64.ref()
 // CHECK:STDOUT:   %MakeI32.ref: %MakeI32.type = name_ref MakeI32, file.%MakeI32.decl [concrete = constants.%MakeI32]
 // CHECK:STDOUT:   %MakeI32.call: init %i32 = call %MakeI32.ref()
 // CHECK:STDOUT:   %.loc19_62.1: %struct_type.b.a = struct_literal (%MakeF64.call, %MakeI32.call)
@@ -118,32 +115,28 @@ fn F() -> {.a: i32, .b: f64} {
 // CHECK:STDOUT:     %int_32.loc19: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc19: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
 // CHECK:STDOUT:     %int_64.loc19: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call.loc19: init type = call constants.%Float(%int_64.loc19) [concrete = f64]
-// CHECK:STDOUT:     %.loc19_24.1: type = value_of_initializer %Float.call.loc19 [concrete = f64]
-// CHECK:STDOUT:     %.loc19_24.2: type = converted %Float.call.loc19, %.loc19_24.1 [concrete = f64]
-// CHECK:STDOUT:     %struct_type.a.b.loc19: type = struct_type {.a: %i32, .b: f64} [concrete = constants.%struct_type.a.b]
+// CHECK:STDOUT:     %f64.loc19: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
+// CHECK:STDOUT:     %struct_type.a.b.loc19: type = struct_type {.a: %i32, .b: %f64.d77} [concrete = constants.%struct_type.a.b]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %.loc19_62.2: %i32 = value_of_initializer %MakeI32.call
 // CHECK:STDOUT:   %.loc19_62.3: %i32 = converted %MakeI32.call, %.loc19_62.2
-// CHECK:STDOUT:   %.loc19_62.4: f64 = value_of_initializer %MakeF64.call
-// CHECK:STDOUT:   %.loc19_62.5: f64 = converted %MakeF64.call, %.loc19_62.4
+// CHECK:STDOUT:   %.loc19_62.4: %f64.d77 = value_of_initializer %MakeF64.call
+// CHECK:STDOUT:   %.loc19_62.5: %f64.d77 = converted %MakeF64.call, %.loc19_62.4
 // CHECK:STDOUT:   %struct.loc19: %struct_type.a.b = struct_value (%.loc19_62.3, %.loc19_62.5)
 // CHECK:STDOUT:   %.loc19_62.6: %struct_type.a.b = converted %.loc19_62.1, %struct.loc19
 // CHECK:STDOUT:   %x: %struct_type.a.b = bind_name x, %.loc19_62.6
 // CHECK:STDOUT:   name_binding_decl {
-// CHECK:STDOUT:     %y.patt: %pattern_type.a24 = binding_pattern y [concrete]
+// CHECK:STDOUT:     %y.patt: %pattern_type.b43 = binding_pattern y [concrete]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x.ref: %struct_type.a.b = name_ref x, %x
 // CHECK:STDOUT:   %.loc20_27: type = splice_block %struct_type.b.a [concrete = constants.%struct_type.b.a] {
 // CHECK:STDOUT:     %int_64.loc20: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
-// CHECK:STDOUT:     %Float.call.loc20: init type = call constants.%Float(%int_64.loc20) [concrete = f64]
-// CHECK:STDOUT:     %.loc20_15.1: type = value_of_initializer %Float.call.loc20 [concrete = f64]
-// CHECK:STDOUT:     %.loc20_15.2: type = converted %Float.call.loc20, %.loc20_15.1 [concrete = f64]
+// CHECK:STDOUT:     %f64.loc20: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77]
 // CHECK:STDOUT:     %int_32.loc20: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc20: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
-// CHECK:STDOUT:     %struct_type.b.a: type = struct_type {.b: f64, .a: %i32} [concrete = constants.%struct_type.b.a]
+// CHECK:STDOUT:     %struct_type.b.a: type = struct_type {.b: %f64.d77, .a: %i32} [concrete = constants.%struct_type.b.a]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc20_31.1: f64 = struct_access %x.ref, element1
+// CHECK:STDOUT:   %.loc20_31.1: %f64.d77 = struct_access %x.ref, element1
 // CHECK:STDOUT:   %.loc20_31.2: %i32 = struct_access %x.ref, element0
 // CHECK:STDOUT:   %struct.loc20: %struct_type.b.a = struct_value (%.loc20_31.1, %.loc20_31.2)
 // CHECK:STDOUT:   %.loc20_31.3: %struct_type.b.a = converted %x.ref, %struct.loc20
@@ -152,9 +145,9 @@ fn F() -> {.a: i32, .b: f64} {
 // CHECK:STDOUT:   %.loc21_10.1: %i32 = struct_access %y.ref, element1
 // CHECK:STDOUT:   %.loc21_10.2: ref %i32 = struct_access %return, element1
 // CHECK:STDOUT:   %.loc21_10.3: init %i32 = initialize_from %.loc21_10.1 to %.loc21_10.2
-// CHECK:STDOUT:   %.loc21_10.4: f64 = struct_access %y.ref, element0
-// CHECK:STDOUT:   %.loc21_10.5: ref f64 = struct_access %return, element0
-// CHECK:STDOUT:   %.loc21_10.6: init f64 = initialize_from %.loc21_10.4 to %.loc21_10.5
+// CHECK:STDOUT:   %.loc21_10.4: %f64.d77 = struct_access %y.ref, element0
+// CHECK:STDOUT:   %.loc21_10.5: ref %f64.d77 = struct_access %return, element0
+// CHECK:STDOUT:   %.loc21_10.6: init %f64.d77 = initialize_from %.loc21_10.4 to %.loc21_10.5
 // CHECK:STDOUT:   %.loc21_10.7: init %struct_type.a.b = struct_init (%.loc21_10.3, %.loc21_10.6) to %return
 // CHECK:STDOUT:   %.loc21_11: init %struct_type.a.b = converted %y.ref, %.loc21_10.7
 // CHECK:STDOUT:   return %.loc21_11 to %return

+ 2 - 2
toolchain/check/testdata/tuple/element_access.carbon

@@ -111,10 +111,10 @@ var c: i32 = a.(b);
 library "[[@TEST_NAME]]";
 
 var a: (i32, i32) = (12, 6);
-// CHECK:STDERR: fail_non_int_indexing.carbon:[[@LINE+7]]:17: error: cannot implicitly convert expression of type `f64` to `Core.IntLiteral` [ConversionFailure]
+// CHECK:STDERR: fail_non_int_indexing.carbon:[[@LINE+7]]:17: error: cannot implicitly convert expression of type `Core.FloatLiteral` to `Core.IntLiteral` [ConversionFailure]
 // CHECK:STDERR: var b: i32 = a.(2.6);
 // CHECK:STDERR:                 ^~~
-// CHECK:STDERR: fail_non_int_indexing.carbon:[[@LINE+4]]:17: note: type `f64` does not implement interface `Core.ImplicitAs(Core.IntLiteral)` [MissingImplInMemberAccessNote]
+// CHECK:STDERR: fail_non_int_indexing.carbon:[[@LINE+4]]:17: note: type `Core.FloatLiteral` does not implement interface `Core.ImplicitAs(Core.IntLiteral)` [MissingImplInMemberAccessNote]
 // CHECK:STDERR: var b: i32 = a.(2.6);
 // CHECK:STDERR:                 ^~~
 // CHECK:STDERR:

+ 28 - 26
toolchain/lower/handle_call.cpp

@@ -236,6 +236,22 @@ static auto CreateBinaryOperatorForBuiltin(
                                 : llvm::Instruction::LShr,
                             lhs, rhs);
     }
+    case SemIR::BuiltinFunctionKind::FloatAdd:
+    case SemIR::BuiltinFunctionKind::FloatAddAssign: {
+      return context.builder().CreateFAdd(lhs, rhs);
+    }
+    case SemIR::BuiltinFunctionKind::FloatSub:
+    case SemIR::BuiltinFunctionKind::FloatSubAssign: {
+      return context.builder().CreateFSub(lhs, rhs);
+    }
+    case SemIR::BuiltinFunctionKind::FloatMul:
+    case SemIR::BuiltinFunctionKind::FloatMulAssign: {
+      return context.builder().CreateFMul(lhs, rhs);
+    }
+    case SemIR::BuiltinFunctionKind::FloatDiv:
+    case SemIR::BuiltinFunctionKind::FloatDivAssign: {
+      return context.builder().CreateFDiv(lhs, rhs);
+    }
     default: {
       CARBON_FATAL("Unexpected binary operator {0}", builtin_kind);
     }
@@ -303,6 +319,7 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id,
 
     case SemIR::BuiltinFunctionKind::BoolMakeType:
     case SemIR::BuiltinFunctionKind::CharLiteralMakeType:
+    case SemIR::BuiltinFunctionKind::FloatLiteralMakeType:
     case SemIR::BuiltinFunctionKind::FloatMakeType:
     case SemIR::BuiltinFunctionKind::IntLiteralMakeType:
     case SemIR::BuiltinFunctionKind::IntMakeTypeSigned:
@@ -361,7 +378,11 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id,
     case SemIR::BuiltinFunctionKind::IntOr:
     case SemIR::BuiltinFunctionKind::IntXor:
     case SemIR::BuiltinFunctionKind::IntLeftShift:
-    case SemIR::BuiltinFunctionKind::IntRightShift: {
+    case SemIR::BuiltinFunctionKind::IntRightShift:
+    case SemIR::BuiltinFunctionKind::FloatAdd:
+    case SemIR::BuiltinFunctionKind::FloatSub:
+    case SemIR::BuiltinFunctionKind::FloatMul:
+    case SemIR::BuiltinFunctionKind::FloatDiv: {
       context.SetLocal(inst_id, CreateBinaryOperatorForBuiltin(
                                     context, inst_id, builtin_kind,
                                     context.GetValue(arg_ids[0]),
@@ -382,7 +403,11 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id,
     case SemIR::BuiltinFunctionKind::IntOrAssign:
     case SemIR::BuiltinFunctionKind::IntXorAssign:
     case SemIR::BuiltinFunctionKind::IntLeftShiftAssign:
-    case SemIR::BuiltinFunctionKind::IntRightShiftAssign: {
+    case SemIR::BuiltinFunctionKind::IntRightShiftAssign:
+    case SemIR::BuiltinFunctionKind::FloatAddAssign:
+    case SemIR::BuiltinFunctionKind::FloatSubAssign:
+    case SemIR::BuiltinFunctionKind::FloatMulAssign:
+    case SemIR::BuiltinFunctionKind::FloatDivAssign: {
       auto* lhs_ptr = context.GetValue(arg_ids[0]);
       auto [lhs_type_file, lhs_type_id] = context.GetTypeIdOfInst(arg_ids[0]);
       auto pointee_type_id = lhs_type_file->GetPointeeType(lhs_type_id);
@@ -417,30 +442,6 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id,
           inst_id, context.builder().CreateFNeg(context.GetValue(arg_ids[0])));
       return;
     }
-    case SemIR::BuiltinFunctionKind::FloatAdd: {
-      context.SetLocal(
-          inst_id, context.builder().CreateFAdd(context.GetValue(arg_ids[0]),
-                                                context.GetValue(arg_ids[1])));
-      return;
-    }
-    case SemIR::BuiltinFunctionKind::FloatSub: {
-      context.SetLocal(
-          inst_id, context.builder().CreateFSub(context.GetValue(arg_ids[0]),
-                                                context.GetValue(arg_ids[1])));
-      return;
-    }
-    case SemIR::BuiltinFunctionKind::FloatMul: {
-      context.SetLocal(
-          inst_id, context.builder().CreateFMul(context.GetValue(arg_ids[0]),
-                                                context.GetValue(arg_ids[1])));
-      return;
-    }
-    case SemIR::BuiltinFunctionKind::FloatDiv: {
-      context.SetLocal(
-          inst_id, context.builder().CreateFDiv(context.GetValue(arg_ids[0]),
-                                                context.GetValue(arg_ids[1])));
-      return;
-    }
     case SemIR::BuiltinFunctionKind::FloatEq:
     case SemIR::BuiltinFunctionKind::FloatNeq:
     case SemIR::BuiltinFunctionKind::FloatLess:
@@ -455,6 +456,7 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id,
     }
 
     case SemIR::BuiltinFunctionKind::CharConvertChecked:
+    case SemIR::BuiltinFunctionKind::FloatConvertChecked:
     case SemIR::BuiltinFunctionKind::IntConvertChecked: {
       // TODO: Check this statically.
       CARBON_CHECK(builtin_kind.IsCompTimeOnly(

+ 4 - 4
toolchain/lower/testdata/array/base.carbon

@@ -22,7 +22,7 @@ fn Run() {
 // CHECK:STDOUT: source_filename = "base.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT: @array.237.loc14_3 = internal constant [1 x i32] [i32 1]
-// CHECK:STDOUT: @array.13b.loc15_3 = internal constant [2 x double] [double 0x4026333333333334, double 2.200000e+00]
+// CHECK:STDOUT: @array.fc9.loc15_3 = internal constant [2 x double] [double 0x4026333333333334, double 2.200000e+00]
 // CHECK:STDOUT: @array.1cb.loc16_3 = internal constant [5 x {}] zeroinitializer
 // CHECK:STDOUT: @tuple.loc17_3 = internal constant { i32, i32, i32 } { i32 1, i32 2, i32 3 }
 // CHECK:STDOUT:
@@ -37,9 +37,9 @@ fn Run() {
 // CHECK:STDOUT:   %.loc14_29.3.array.index = getelementptr inbounds [1 x i32], ptr %a.var, i32 0, i64 0, !dbg !12
 // CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a.var, ptr align 4 @array.237.loc14_3, i64 4, i1 false), !dbg !7
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 16, ptr %b.var), !dbg !8
-// CHECK:STDOUT:   %.loc15_37.2.array.index = getelementptr inbounds [2 x double], ptr %b.var, i32 0, i64 0, !dbg !13
-// CHECK:STDOUT:   %.loc15_37.4.array.index = getelementptr inbounds [2 x double], ptr %b.var, i32 0, i64 1, !dbg !13
-// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 8 %b.var, ptr align 8 @array.13b.loc15_3, i64 16, i1 false), !dbg !8
+// CHECK:STDOUT:   %.loc15_37.3.array.index = getelementptr inbounds [2 x double], ptr %b.var, i32 0, i64 0, !dbg !13
+// CHECK:STDOUT:   %.loc15_37.6.array.index = getelementptr inbounds [2 x double], ptr %b.var, i32 0, i64 1, !dbg !13
+// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 8 %b.var, ptr align 8 @array.fc9.loc15_3, i64 16, i1 false), !dbg !8
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 0, ptr %c.var), !dbg !9
 // CHECK:STDOUT:   %.loc16_45.2.array.index = getelementptr inbounds [5 x {}], ptr %c.var, i32 0, i64 0, !dbg !14
 // CHECK:STDOUT:   %.loc16_45.4.array.index = getelementptr inbounds [5 x {}], ptr %c.var, i32 0, i64 1, !dbg !14

+ 8 - 8
toolchain/lower/testdata/basics/numeric_literals.carbon

@@ -33,7 +33,7 @@ fn F() {
 // CHECK:STDOUT: source_filename = "numeric_literals.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT: @array.712.loc16_3 = internal constant [4 x i32] [i32 8, i32 9, i32 8, i32 8]
-// CHECK:STDOUT: @array.f02.loc22_3 = internal constant [6 x double] [double 9.000000e-01, double 8.000000e+00, double 8.000000e+01, double 1.000000e+07, double 1.000000e+08, double 1.000000e-08]
+// CHECK:STDOUT: @array.165.loc22_3 = internal constant [6 x double] [double 9.000000e-01, double 8.000000e+00, double 8.000000e+01, double 1.000000e+07, double 1.000000e+08, double 1.000000e-08]
 // CHECK:STDOUT:
 // CHECK:STDOUT: define void @_CF.Main() !dbg !4 {
 // CHECK:STDOUT: entry:
@@ -46,13 +46,13 @@ fn F() {
 // CHECK:STDOUT:   %.loc21_3.12.array.index = getelementptr inbounds [4 x i32], ptr %ints.var, i32 0, i64 3, !dbg !9
 // CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %ints.var, ptr align 4 @array.712.loc16_3, i64 16, i1 false), !dbg !7
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 48, ptr %floats.var), !dbg !8
-// CHECK:STDOUT:   %.loc29_3.2.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 0, !dbg !10
-// CHECK:STDOUT:   %.loc29_3.4.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 1, !dbg !10
-// CHECK:STDOUT:   %.loc29_3.6.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 2, !dbg !10
-// CHECK:STDOUT:   %.loc29_3.8.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 3, !dbg !10
-// CHECK:STDOUT:   %.loc29_3.10.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 4, !dbg !10
-// CHECK:STDOUT:   %.loc29_3.12.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 5, !dbg !10
-// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 8 %floats.var, ptr align 8 @array.f02.loc22_3, i64 48, i1 false), !dbg !8
+// CHECK:STDOUT:   %.loc29_3.3.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 0, !dbg !10
+// CHECK:STDOUT:   %.loc29_3.6.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 1, !dbg !10
+// CHECK:STDOUT:   %.loc29_3.9.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 2, !dbg !10
+// CHECK:STDOUT:   %.loc29_3.12.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 3, !dbg !10
+// CHECK:STDOUT:   %.loc29_3.15.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 4, !dbg !10
+// CHECK:STDOUT:   %.loc29_3.18.array.index = getelementptr inbounds [6 x double], ptr %floats.var, i32 0, i64 5, !dbg !10
+// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 8 %floats.var, ptr align 8 @array.165.loc22_3, i64 48, i1 false), !dbg !8
 // CHECK:STDOUT:   ret void, !dbg !11
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 112 - 36
toolchain/lower/testdata/builtins/float.carbon

@@ -10,6 +10,10 @@
 // TIP: To dump output, run:
 // TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/builtins/float.carbon
 
+// --- basic.carbon
+
+library "[[@TEST_NAME]]";
+
 fn Negate(a: f64) -> f64 = "float.negate";
 fn TestNegate(a: f64) -> f64 { return Negate(a); }
 
@@ -43,8 +47,24 @@ fn TestGreater(a: f64, b: f64) -> bool { return Greater(a, b); }
 fn GreaterEq(a: f64, b: f64) -> bool = "float.greater_eq";
 fn TestGreaterEq(a: f64, b: f64) -> bool { return GreaterEq(a, b); }
 
-// CHECK:STDOUT: ; ModuleID = 'float.carbon'
-// CHECK:STDOUT: source_filename = "float.carbon"
+// --- compound_assign.carbon
+
+library "[[@TEST_NAME]]";
+
+fn Add(a: f64*, b: f64) = "float.add_assign";
+fn TestAdd(a: f64*, b: f64) { Add(a, b); }
+
+fn Sub(a: f64*, b: f64) = "float.sub_assign";
+fn TestSub(a: f64*, b: f64) { Sub(a, b); }
+
+fn Mul(a: f64*, b: f64) = "float.mul_assign";
+fn TestMul(a: f64*, b: f64) { Mul(a, b); }
+
+fn Div(a: f64*, b: f64) = "float.div_assign";
+fn TestDiv(a: f64*, b: f64) { Div(a, b); }
+
+// CHECK:STDOUT: ; ModuleID = 'basic.carbon'
+// CHECK:STDOUT: source_filename = "basic.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT: define double @_CTestNegate.Main(double %a) !dbg !4 {
 // CHECK:STDOUT: entry:
@@ -118,39 +138,95 @@ fn TestGreaterEq(a: f64, b: f64) -> bool { return GreaterEq(a, b); }
 // CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
 // CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
 // CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
-// CHECK:STDOUT: !3 = !DIFile(filename: "float.carbon", directory: "")
-// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "TestNegate", linkageName: "_CTestNegate.Main", scope: null, file: !3, line: 14, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !3 = !DIFile(filename: "basic.carbon", directory: "")
+// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "TestNegate", linkageName: "_CTestNegate.Main", scope: null, file: !3, line: 5, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
+// CHECK:STDOUT: !6 = !{}
+// CHECK:STDOUT: !7 = !DILocation(line: 5, column: 39, scope: !4)
+// CHECK:STDOUT: !8 = !DILocation(line: 5, column: 32, scope: !4)
+// CHECK:STDOUT: !9 = distinct !DISubprogram(name: "TestAdd", linkageName: "_CTestAdd.Main", scope: null, file: !3, line: 8, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !10 = !DILocation(line: 8, column: 44, scope: !9)
+// CHECK:STDOUT: !11 = !DILocation(line: 8, column: 37, scope: !9)
+// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "TestSub", linkageName: "_CTestSub.Main", scope: null, file: !3, line: 11, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !13 = !DILocation(line: 11, column: 44, scope: !12)
+// CHECK:STDOUT: !14 = !DILocation(line: 11, column: 37, scope: !12)
+// CHECK:STDOUT: !15 = distinct !DISubprogram(name: "TestMul", linkageName: "_CTestMul.Main", scope: null, file: !3, line: 14, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !16 = !DILocation(line: 14, column: 44, scope: !15)
+// CHECK:STDOUT: !17 = !DILocation(line: 14, column: 37, scope: !15)
+// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "TestDiv", linkageName: "_CTestDiv.Main", scope: null, file: !3, line: 17, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !19 = !DILocation(line: 17, column: 44, scope: !18)
+// CHECK:STDOUT: !20 = !DILocation(line: 17, column: 37, scope: !18)
+// CHECK:STDOUT: !21 = distinct !DISubprogram(name: "TestEq", linkageName: "_CTestEq.Main", scope: null, file: !3, line: 20, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !22 = !DILocation(line: 20, column: 44, scope: !21)
+// CHECK:STDOUT: !23 = !DILocation(line: 20, column: 37, scope: !21)
+// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "TestNeq", linkageName: "_CTestNeq.Main", scope: null, file: !3, line: 23, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !25 = !DILocation(line: 23, column: 45, scope: !24)
+// CHECK:STDOUT: !26 = !DILocation(line: 23, column: 38, scope: !24)
+// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "TestLess", linkageName: "_CTestLess.Main", scope: null, file: !3, line: 26, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !28 = !DILocation(line: 26, column: 46, scope: !27)
+// CHECK:STDOUT: !29 = !DILocation(line: 26, column: 39, scope: !27)
+// CHECK:STDOUT: !30 = distinct !DISubprogram(name: "TestLessEq", linkageName: "_CTestLessEq.Main", scope: null, file: !3, line: 29, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !31 = !DILocation(line: 29, column: 48, scope: !30)
+// CHECK:STDOUT: !32 = !DILocation(line: 29, column: 41, scope: !30)
+// CHECK:STDOUT: !33 = distinct !DISubprogram(name: "TestGreater", linkageName: "_CTestGreater.Main", scope: null, file: !3, line: 32, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !34 = !DILocation(line: 32, column: 49, scope: !33)
+// CHECK:STDOUT: !35 = !DILocation(line: 32, column: 42, scope: !33)
+// CHECK:STDOUT: !36 = distinct !DISubprogram(name: "TestGreaterEq", linkageName: "_CTestGreaterEq.Main", scope: null, file: !3, line: 35, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !37 = !DILocation(line: 35, column: 51, scope: !36)
+// CHECK:STDOUT: !38 = !DILocation(line: 35, column: 44, scope: !36)
+// CHECK:STDOUT: ; ModuleID = 'compound_assign.carbon'
+// CHECK:STDOUT: source_filename = "compound_assign.carbon"
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @_CTestAdd.Main(ptr %a, double %b) !dbg !4 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %Add.call = load double, ptr %a, align 8, !dbg !7
+// CHECK:STDOUT:   %Add.call1 = fadd double %Add.call, %b, !dbg !7
+// CHECK:STDOUT:   store double %Add.call1, ptr %a, align 8, !dbg !7
+// CHECK:STDOUT:   ret void, !dbg !8
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @_CTestSub.Main(ptr %a, double %b) !dbg !9 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %Sub.call = load double, ptr %a, align 8, !dbg !10
+// CHECK:STDOUT:   %Sub.call1 = fsub double %Sub.call, %b, !dbg !10
+// CHECK:STDOUT:   store double %Sub.call1, ptr %a, align 8, !dbg !10
+// CHECK:STDOUT:   ret void, !dbg !11
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @_CTestMul.Main(ptr %a, double %b) !dbg !12 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %Mul.call = load double, ptr %a, align 8, !dbg !13
+// CHECK:STDOUT:   %Mul.call1 = fmul double %Mul.call, %b, !dbg !13
+// CHECK:STDOUT:   store double %Mul.call1, ptr %a, align 8, !dbg !13
+// CHECK:STDOUT:   ret void, !dbg !14
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @_CTestDiv.Main(ptr %a, double %b) !dbg !15 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %Div.call = load double, ptr %a, align 8, !dbg !16
+// CHECK:STDOUT:   %Div.call1 = fdiv double %Div.call, %b, !dbg !16
+// CHECK:STDOUT:   store double %Div.call1, ptr %a, align 8, !dbg !16
+// CHECK:STDOUT:   ret void, !dbg !17
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
+// CHECK:STDOUT: !llvm.dbg.cu = !{!2}
+// CHECK:STDOUT:
+// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
+// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
+// CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+// CHECK:STDOUT: !3 = !DIFile(filename: "compound_assign.carbon", directory: "")
+// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "TestAdd", linkageName: "_CTestAdd.Main", scope: null, file: !3, line: 5, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
 // CHECK:STDOUT: !6 = !{}
-// CHECK:STDOUT: !7 = !DILocation(line: 14, column: 39, scope: !4)
-// CHECK:STDOUT: !8 = !DILocation(line: 14, column: 32, scope: !4)
-// CHECK:STDOUT: !9 = distinct !DISubprogram(name: "TestAdd", linkageName: "_CTestAdd.Main", scope: null, file: !3, line: 17, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !10 = !DILocation(line: 17, column: 44, scope: !9)
-// CHECK:STDOUT: !11 = !DILocation(line: 17, column: 37, scope: !9)
-// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "TestSub", linkageName: "_CTestSub.Main", scope: null, file: !3, line: 20, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !13 = !DILocation(line: 20, column: 44, scope: !12)
-// CHECK:STDOUT: !14 = !DILocation(line: 20, column: 37, scope: !12)
-// CHECK:STDOUT: !15 = distinct !DISubprogram(name: "TestMul", linkageName: "_CTestMul.Main", scope: null, file: !3, line: 23, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !16 = !DILocation(line: 23, column: 44, scope: !15)
-// CHECK:STDOUT: !17 = !DILocation(line: 23, column: 37, scope: !15)
-// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "TestDiv", linkageName: "_CTestDiv.Main", scope: null, file: !3, line: 26, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !19 = !DILocation(line: 26, column: 44, scope: !18)
-// CHECK:STDOUT: !20 = !DILocation(line: 26, column: 37, scope: !18)
-// CHECK:STDOUT: !21 = distinct !DISubprogram(name: "TestEq", linkageName: "_CTestEq.Main", scope: null, file: !3, line: 29, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !22 = !DILocation(line: 29, column: 44, scope: !21)
-// CHECK:STDOUT: !23 = !DILocation(line: 29, column: 37, scope: !21)
-// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "TestNeq", linkageName: "_CTestNeq.Main", scope: null, file: !3, line: 32, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !25 = !DILocation(line: 32, column: 45, scope: !24)
-// CHECK:STDOUT: !26 = !DILocation(line: 32, column: 38, scope: !24)
-// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "TestLess", linkageName: "_CTestLess.Main", scope: null, file: !3, line: 35, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !28 = !DILocation(line: 35, column: 46, scope: !27)
-// CHECK:STDOUT: !29 = !DILocation(line: 35, column: 39, scope: !27)
-// CHECK:STDOUT: !30 = distinct !DISubprogram(name: "TestLessEq", linkageName: "_CTestLessEq.Main", scope: null, file: !3, line: 38, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !31 = !DILocation(line: 38, column: 48, scope: !30)
-// CHECK:STDOUT: !32 = !DILocation(line: 38, column: 41, scope: !30)
-// CHECK:STDOUT: !33 = distinct !DISubprogram(name: "TestGreater", linkageName: "_CTestGreater.Main", scope: null, file: !3, line: 41, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !34 = !DILocation(line: 41, column: 49, scope: !33)
-// CHECK:STDOUT: !35 = !DILocation(line: 41, column: 42, scope: !33)
-// CHECK:STDOUT: !36 = distinct !DISubprogram(name: "TestGreaterEq", linkageName: "_CTestGreaterEq.Main", scope: null, file: !3, line: 44, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !37 = !DILocation(line: 44, column: 51, scope: !36)
-// CHECK:STDOUT: !38 = !DILocation(line: 44, column: 44, scope: !36)
+// CHECK:STDOUT: !7 = !DILocation(line: 5, column: 31, scope: !4)
+// CHECK:STDOUT: !8 = !DILocation(line: 5, column: 1, scope: !4)
+// CHECK:STDOUT: !9 = distinct !DISubprogram(name: "TestSub", linkageName: "_CTestSub.Main", scope: null, file: !3, line: 8, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !10 = !DILocation(line: 8, column: 31, scope: !9)
+// CHECK:STDOUT: !11 = !DILocation(line: 8, column: 1, scope: !9)
+// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "TestMul", linkageName: "_CTestMul.Main", scope: null, file: !3, line: 11, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !13 = !DILocation(line: 11, column: 31, scope: !12)
+// CHECK:STDOUT: !14 = !DILocation(line: 11, column: 1, scope: !12)
+// CHECK:STDOUT: !15 = distinct !DISubprogram(name: "TestDiv", linkageName: "_CTestDiv.Main", scope: null, file: !3, line: 14, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !16 = !DILocation(line: 14, column: 31, scope: !15)
+// CHECK:STDOUT: !17 = !DILocation(line: 14, column: 1, scope: !15)

+ 8 - 6
toolchain/lower/testdata/builtins/types.carbon

@@ -11,14 +11,16 @@
 // TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/builtins/types.carbon
 
 fn IntLiteral() -> type = "int_literal.make_type";
+fn FloatLiteral() -> type = "float_literal.make_type";
 fn Int(size: IntLiteral()) -> type = "int.make_type_signed";
 fn Float(size: IntLiteral()) -> type = "float.make_type";
 fn Bool() -> type = "bool.make_type";
 fn AsI32(n: IntLiteral()) -> Int(32) = "int.convert_checked";
+fn AsF64(f: FloatLiteral()) -> Float(64) = "float.convert_checked";
 
 fn F() {
   var i: Int(32) = AsI32(0);
-  var f: Float(64) = 0.0;
+  var f: Float(64) = AsF64(0.0);
   var b: Bool() = false;
 }
 
@@ -54,10 +56,10 @@ fn F() {
 // CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
 // CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
 // CHECK:STDOUT: !3 = !DIFile(filename: "types.carbon", directory: "")
-// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !3, line: 19, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
 // CHECK:STDOUT: !6 = !{}
-// CHECK:STDOUT: !7 = !DILocation(line: 20, column: 3, scope: !4)
-// CHECK:STDOUT: !8 = !DILocation(line: 21, column: 3, scope: !4)
-// CHECK:STDOUT: !9 = !DILocation(line: 22, column: 3, scope: !4)
-// CHECK:STDOUT: !10 = !DILocation(line: 19, column: 1, scope: !4)
+// CHECK:STDOUT: !7 = !DILocation(line: 22, column: 3, scope: !4)
+// CHECK:STDOUT: !8 = !DILocation(line: 23, column: 3, scope: !4)
+// CHECK:STDOUT: !9 = !DILocation(line: 24, column: 3, scope: !4)
+// CHECK:STDOUT: !10 = !DILocation(line: 21, column: 1, scope: !4)

+ 3 - 3
toolchain/lower/testdata/function/generic/call.carbon

@@ -56,7 +56,7 @@ fn G() {
 // CHECK:STDOUT:   %.loc27 = load i32, ptr %n.var, align 4, !dbg !13
 // CHECK:STDOUT:   call void @_CF.Main.b88d1103f417c6d4(i32 %.loc27), !dbg !14
 // CHECK:STDOUT:   %.loc28 = load double, ptr %m.var, align 8, !dbg !15
-// CHECK:STDOUT:   call void @_CF.Main.66be507887ceee78(double %.loc28), !dbg !16
+// CHECK:STDOUT:   call void @_CF.Main.d4b5665541d5d7a8(double %.loc28), !dbg !16
 // CHECK:STDOUT:   call void @_CF.Main.5754c7a55c7cbe4a(%type zeroinitializer), !dbg !17
 // CHECK:STDOUT:   ret void, !dbg !18
 // CHECK:STDOUT: }
@@ -77,7 +77,7 @@ fn G() {
 // CHECK:STDOUT:   ret void, !dbg !22
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CF.Main.66be507887ceee78(double %x) !dbg !23 {
+// CHECK:STDOUT: define linkonce_odr void @_CF.Main.d4b5665541d5d7a8(double %x) !dbg !23 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   ret void, !dbg !24
 // CHECK:STDOUT: }
@@ -121,7 +121,7 @@ fn G() {
 // CHECK:STDOUT: !20 = !DILocation(line: 13, column: 1, scope: !19)
 // CHECK:STDOUT: !21 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.b88d1103f417c6d4", scope: null, file: !3, line: 13, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !22 = !DILocation(line: 13, column: 1, scope: !21)
-// CHECK:STDOUT: !23 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.66be507887ceee78", scope: null, file: !3, line: 13, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !23 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 13, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !24 = !DILocation(line: 13, column: 1, scope: !23)
 // CHECK:STDOUT: !25 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.5754c7a55c7cbe4a", scope: null, file: !3, line: 13, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !26 = !DILocation(line: 13, column: 1, scope: !25)

+ 14 - 14
toolchain/lower/testdata/function/generic/call_basic.carbon

@@ -77,9 +77,9 @@ fn M() {
 // CHECK:STDOUT:   %G.call.loc52 = call i32 @_CG.Main.b88d1103f417c6d4(i32 %.loc52), !dbg !14
 // CHECK:STDOUT:   store i32 %G.call.loc52, ptr %m.var, align 4, !dbg !15
 // CHECK:STDOUT:   %.loc53 = load double, ptr %p.var, align 8, !dbg !16
-// CHECK:STDOUT:   call void @_CF.Main.66be507887ceee78(double %.loc53), !dbg !17
+// CHECK:STDOUT:   call void @_CF.Main.d4b5665541d5d7a8(double %.loc53), !dbg !17
 // CHECK:STDOUT:   %.loc54 = load double, ptr %p.var, align 8, !dbg !18
-// CHECK:STDOUT:   %G.call.loc54 = call double @_CG.Main.66be507887ceee78(double %.loc54), !dbg !19
+// CHECK:STDOUT:   %G.call.loc54 = call double @_CG.Main.d4b5665541d5d7a8(double %.loc54), !dbg !19
 // CHECK:STDOUT:   store double %G.call.loc54, ptr %q.var, align 8, !dbg !20
 // CHECK:STDOUT:   ret void, !dbg !21
 // CHECK:STDOUT: }
@@ -107,7 +107,7 @@ fn M() {
 // CHECK:STDOUT:   %H.call.loc28 = call i32 @_CH.Main.b88d1103f417c6d4(i32 %G.call), !dbg !35
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 8, ptr %var_f64.var), !dbg !25
 // CHECK:STDOUT:   %.loc32 = load double, ptr %var_f64.var, align 8, !dbg !36
-// CHECK:STDOUT:   %H.call.loc32 = call double @_CH.Main.66be507887ceee78(double %.loc32), !dbg !37
+// CHECK:STDOUT:   %H.call.loc32 = call double @_CH.Main.d4b5665541d5d7a8(double %.loc32), !dbg !37
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 8, ptr %ptr_i32.var), !dbg !26
 // CHECK:STDOUT:   %.loc34 = load ptr, ptr %ptr_i32.var, align 8, !dbg !38
 // CHECK:STDOUT:   %H.call.loc34 = call ptr @_CH.Main.e8193710fd35b608(ptr %.loc34), !dbg !39
@@ -123,12 +123,12 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %x, !dbg !44
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CF.Main.66be507887ceee78(double %x) !dbg !45 {
+// CHECK:STDOUT: define linkonce_odr void @_CF.Main.d4b5665541d5d7a8(double %x) !dbg !45 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   ret void, !dbg !46
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CG.Main.66be507887ceee78(double %x) !dbg !47 {
+// CHECK:STDOUT: define linkonce_odr double @_CG.Main.d4b5665541d5d7a8(double %x) !dbg !47 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %var_f64.var = alloca double, align 8, !dbg !48
 // CHECK:STDOUT:   %ptr_i32.var = alloca ptr, align 8, !dbg !49
@@ -136,14 +136,14 @@ fn M() {
 // CHECK:STDOUT:   %ptr_i8.var = alloca ptr, align 8, !dbg !51
 // CHECK:STDOUT:   %c.var = alloca {}, align 8, !dbg !52
 // CHECK:STDOUT:   %.loc40_6.1.temp = alloca {}, align 8, !dbg !53
-// CHECK:STDOUT:   %H.call.loc25 = call double @_CH.Main.66be507887ceee78(double %x), !dbg !54
+// CHECK:STDOUT:   %H.call.loc25 = call double @_CH.Main.d4b5665541d5d7a8(double %x), !dbg !54
 // CHECK:STDOUT:   %H.call.loc26 = call %type @_CH.Main.5754c7a55c7cbe4a(%type zeroinitializer), !dbg !55
 // CHECK:STDOUT:   %H.call.loc27 = call %type @_CH.Main.5754c7a55c7cbe4a(%type zeroinitializer), !dbg !56
-// CHECK:STDOUT:   %G.call = call double @_CG.Main.66be507887ceee78(double %x), !dbg !57
-// CHECK:STDOUT:   %H.call.loc28 = call double @_CH.Main.66be507887ceee78(double %G.call), !dbg !58
+// CHECK:STDOUT:   %G.call = call double @_CG.Main.d4b5665541d5d7a8(double %x), !dbg !57
+// CHECK:STDOUT:   %H.call.loc28 = call double @_CH.Main.d4b5665541d5d7a8(double %G.call), !dbg !58
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 8, ptr %var_f64.var), !dbg !48
 // CHECK:STDOUT:   %.loc32 = load double, ptr %var_f64.var, align 8, !dbg !59
-// CHECK:STDOUT:   %H.call.loc32 = call double @_CH.Main.66be507887ceee78(double %.loc32), !dbg !60
+// CHECK:STDOUT:   %H.call.loc32 = call double @_CH.Main.d4b5665541d5d7a8(double %.loc32), !dbg !60
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 8, ptr %ptr_i32.var), !dbg !49
 // CHECK:STDOUT:   %.loc34 = load ptr, ptr %ptr_i32.var, align 8, !dbg !61
 // CHECK:STDOUT:   %H.call.loc34 = call ptr @_CH.Main.e8193710fd35b608(ptr %.loc34), !dbg !62
@@ -169,7 +169,7 @@ fn M() {
 // CHECK:STDOUT:   ret %type %x, !dbg !71
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CH.Main.66be507887ceee78(double %x) !dbg !72 {
+// CHECK:STDOUT: define linkonce_odr double @_CH.Main.d4b5665541d5d7a8(double %x) !dbg !72 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   ret double %x, !dbg !73
 // CHECK:STDOUT: }
@@ -188,7 +188,7 @@ fn M() {
 // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 14, 13, 12 }
 // CHECK:STDOUT: uselistorder ptr @_CH.Main.b88d1103f417c6d4, { 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @_CH.Main.5754c7a55c7cbe4a, { 3, 2, 1, 0 }
-// CHECK:STDOUT: uselistorder ptr @_CH.Main.66be507887ceee78, { 3, 2, 1, 0 }
+// CHECK:STDOUT: uselistorder ptr @_CH.Main.d4b5665541d5d7a8, { 3, 2, 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @_CH.Main.e8193710fd35b608, { 5, 2, 0, 4, 3, 1 }
 // CHECK:STDOUT: uselistorder ptr @_CH.Main.15b1f98bd9cc0c5b, { 1, 0 }
 // CHECK:STDOUT:
@@ -242,9 +242,9 @@ fn M() {
 // CHECK:STDOUT: !42 = !DILocation(line: 38, column: 5, scope: !24)
 // CHECK:STDOUT: !43 = !DILocation(line: 38, column: 3, scope: !24)
 // CHECK:STDOUT: !44 = !DILocation(line: 42, column: 3, scope: !24)
-// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.66be507887ceee78", scope: null, file: !3, line: 15, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 15, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !46 = !DILocation(line: 15, column: 1, scope: !45)
-// CHECK:STDOUT: !47 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.66be507887ceee78", scope: null, file: !3, line: 24, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !47 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 24, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !48 = !DILocation(line: 31, column: 3, scope: !47)
 // CHECK:STDOUT: !49 = !DILocation(line: 33, column: 3, scope: !47)
 // CHECK:STDOUT: !50 = !DILocation(line: 35, column: 3, scope: !47)
@@ -269,7 +269,7 @@ fn M() {
 // CHECK:STDOUT: !69 = !DILocation(line: 19, column: 3, scope: !68)
 // CHECK:STDOUT: !70 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.5754c7a55c7cbe4a", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !71 = !DILocation(line: 19, column: 3, scope: !70)
-// CHECK:STDOUT: !72 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.66be507887ceee78", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !72 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !73 = !DILocation(line: 19, column: 3, scope: !72)
 // CHECK:STDOUT: !74 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.e8193710fd35b608", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !75 = !DILocation(line: 19, column: 3, scope: !74)

+ 9 - 9
toolchain/lower/testdata/function/generic/call_deref_ptr.carbon

@@ -55,7 +55,7 @@ fn M() {
 // CHECK:STDOUT:   %.loc39 = load ptr, ptr %ptr_i32.var, align 8, !dbg !9
 // CHECK:STDOUT:   call void @_CF.Main.b88d1103f417c6d4(ptr %.loc39), !dbg !10
 // CHECK:STDOUT:   %.loc40 = load ptr, ptr %ptr_f64.var, align 8, !dbg !11
-// CHECK:STDOUT:   call void @_CF.Main.66be507887ceee78(ptr %.loc40), !dbg !12
+// CHECK:STDOUT:   call void @_CF.Main.d4b5665541d5d7a8(ptr %.loc40), !dbg !12
 // CHECK:STDOUT:   ret void, !dbg !13
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -69,10 +69,10 @@ fn M() {
 // CHECK:STDOUT:   ret void, !dbg !17
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CF.Main.66be507887ceee78(ptr %x) !dbg !18 {
+// CHECK:STDOUT: define linkonce_odr void @_CF.Main.d4b5665541d5d7a8(ptr %x) !dbg !18 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %A.call = call %type @_CA.Main.5754c7a55c7cbe4a(%type zeroinitializer), !dbg !19
-// CHECK:STDOUT:   call void @_CB.Main.66be507887ceee78(ptr %x), !dbg !20
+// CHECK:STDOUT:   call void @_CB.Main.d4b5665541d5d7a8(ptr %x), !dbg !20
 // CHECK:STDOUT:   ret void, !dbg !21
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -88,10 +88,10 @@ fn M() {
 // CHECK:STDOUT:   ret void, !dbg !27
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CB.Main.66be507887ceee78(ptr %x) !dbg !28 {
+// CHECK:STDOUT: define linkonce_odr void @_CB.Main.d4b5665541d5d7a8(ptr %x) !dbg !28 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %.loc27_5.2 = load double, ptr %x, align 8, !dbg !29
-// CHECK:STDOUT:   %D.call = call double @_CD.Main.66be507887ceee78(double %.loc27_5.2), !dbg !30
+// CHECK:STDOUT:   %D.call = call double @_CD.Main.d4b5665541d5d7a8(double %.loc27_5.2), !dbg !30
 // CHECK:STDOUT:   ret void, !dbg !31
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -100,7 +100,7 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %x, !dbg !33
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CD.Main.66be507887ceee78(double %x) !dbg !34 {
+// CHECK:STDOUT: define linkonce_odr double @_CD.Main.d4b5665541d5d7a8(double %x) !dbg !34 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   ret double %x, !dbg !35
 // CHECK:STDOUT: }
@@ -132,7 +132,7 @@ fn M() {
 // CHECK:STDOUT: !15 = !DILocation(line: 31, column: 3, scope: !14)
 // CHECK:STDOUT: !16 = !DILocation(line: 32, column: 3, scope: !14)
 // CHECK:STDOUT: !17 = !DILocation(line: 30, column: 1, scope: !14)
-// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.66be507887ceee78", scope: null, file: !3, line: 30, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 30, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !19 = !DILocation(line: 31, column: 3, scope: !18)
 // CHECK:STDOUT: !20 = !DILocation(line: 32, column: 3, scope: !18)
 // CHECK:STDOUT: !21 = !DILocation(line: 30, column: 1, scope: !18)
@@ -142,11 +142,11 @@ fn M() {
 // CHECK:STDOUT: !25 = !DILocation(line: 27, column: 5, scope: !24)
 // CHECK:STDOUT: !26 = !DILocation(line: 27, column: 3, scope: !24)
 // CHECK:STDOUT: !27 = !DILocation(line: 26, column: 1, scope: !24)
-// CHECK:STDOUT: !28 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.66be507887ceee78", scope: null, file: !3, line: 26, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !28 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 26, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !29 = !DILocation(line: 27, column: 5, scope: !28)
 // CHECK:STDOUT: !30 = !DILocation(line: 27, column: 3, scope: !28)
 // CHECK:STDOUT: !31 = !DILocation(line: 26, column: 1, scope: !28)
 // CHECK:STDOUT: !32 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.b88d1103f417c6d4", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !33 = !DILocation(line: 23, column: 3, scope: !32)
-// CHECK:STDOUT: !34 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.66be507887ceee78", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !34 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !35 = !DILocation(line: 23, column: 3, scope: !34)

+ 9 - 9
toolchain/lower/testdata/function/generic/call_different_specific.carbon

@@ -62,7 +62,7 @@ fn M() {
 // CHECK:STDOUT:   %.loc46 = load ptr, ptr %ptr_i32.var, align 8, !dbg !9
 // CHECK:STDOUT:   call void @_CF.Main.b88d1103f417c6d4(ptr %.loc46), !dbg !10
 // CHECK:STDOUT:   %.loc47 = load ptr, ptr %ptr_f64.var, align 8, !dbg !11
-// CHECK:STDOUT:   call void @_CF.Main.66be507887ceee78(ptr %.loc47), !dbg !12
+// CHECK:STDOUT:   call void @_CF.Main.d4b5665541d5d7a8(ptr %.loc47), !dbg !12
 // CHECK:STDOUT:   ret void, !dbg !13
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -76,10 +76,10 @@ fn M() {
 // CHECK:STDOUT:   ret void, !dbg !17
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CF.Main.66be507887ceee78(ptr %x) !dbg !18 {
+// CHECK:STDOUT: define linkonce_odr void @_CF.Main.d4b5665541d5d7a8(ptr %x) !dbg !18 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %A.call = call %type @_CA.Main.5754c7a55c7cbe4a(%type zeroinitializer), !dbg !19
-// CHECK:STDOUT:   call void @_CB.Main.66be507887ceee78(ptr %x), !dbg !20
+// CHECK:STDOUT:   call void @_CB.Main.d4b5665541d5d7a8(ptr %x), !dbg !20
 // CHECK:STDOUT:   ret void, !dbg !21
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -95,10 +95,10 @@ fn M() {
 // CHECK:STDOUT:   ret void, !dbg !27
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CB.Main.66be507887ceee78(ptr %x) !dbg !28 {
+// CHECK:STDOUT: define linkonce_odr void @_CB.Main.d4b5665541d5d7a8(ptr %x) !dbg !28 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %.loc34_5.2 = load double, ptr %x, align 8, !dbg !29
-// CHECK:STDOUT:   %D.call = call double @_CD.Main.66be507887ceee78(double %.loc34_5.2), !dbg !30
+// CHECK:STDOUT:   %D.call = call double @_CD.Main.d4b5665541d5d7a8(double %.loc34_5.2), !dbg !30
 // CHECK:STDOUT:   ret void, !dbg !31
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -107,7 +107,7 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %x, !dbg !33
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CD.Main.66be507887ceee78(double %x) !dbg !34 {
+// CHECK:STDOUT: define linkonce_odr double @_CD.Main.d4b5665541d5d7a8(double %x) !dbg !34 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   ret double %x, !dbg !35
 // CHECK:STDOUT: }
@@ -139,7 +139,7 @@ fn M() {
 // CHECK:STDOUT: !15 = !DILocation(line: 38, column: 3, scope: !14)
 // CHECK:STDOUT: !16 = !DILocation(line: 39, column: 3, scope: !14)
 // CHECK:STDOUT: !17 = !DILocation(line: 37, column: 1, scope: !14)
-// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.66be507887ceee78", scope: null, file: !3, line: 37, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 37, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !19 = !DILocation(line: 38, column: 3, scope: !18)
 // CHECK:STDOUT: !20 = !DILocation(line: 39, column: 3, scope: !18)
 // CHECK:STDOUT: !21 = !DILocation(line: 37, column: 1, scope: !18)
@@ -149,11 +149,11 @@ fn M() {
 // CHECK:STDOUT: !25 = !DILocation(line: 34, column: 5, scope: !24)
 // CHECK:STDOUT: !26 = !DILocation(line: 34, column: 3, scope: !24)
 // CHECK:STDOUT: !27 = !DILocation(line: 33, column: 1, scope: !24)
-// CHECK:STDOUT: !28 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.66be507887ceee78", scope: null, file: !3, line: 33, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !28 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 33, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !29 = !DILocation(line: 34, column: 5, scope: !28)
 // CHECK:STDOUT: !30 = !DILocation(line: 34, column: 3, scope: !28)
 // CHECK:STDOUT: !31 = !DILocation(line: 33, column: 1, scope: !28)
 // CHECK:STDOUT: !32 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.b88d1103f417c6d4", scope: null, file: !3, line: 29, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !33 = !DILocation(line: 30, column: 3, scope: !32)
-// CHECK:STDOUT: !34 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.66be507887ceee78", scope: null, file: !3, line: 29, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !34 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 29, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !35 = !DILocation(line: 30, column: 3, scope: !34)

+ 4 - 4
toolchain/lower/testdata/function/generic/call_recursive_basic.carbon

@@ -57,7 +57,7 @@ fn M() {
 // CHECK:STDOUT:   %.loc30_5 = load i32, ptr %n.var, align 4, !dbg !11
 // CHECK:STDOUT:   %F.call.loc30 = call i32 @_CF.Main.b88d1103f417c6d4(i32 %.loc30_5, i32 0), !dbg !12
 // CHECK:STDOUT:   %.loc31_5 = load double, ptr %m.var, align 8, !dbg !13
-// CHECK:STDOUT:   %F.call.loc31 = call double @_CF.Main.66be507887ceee78(double %.loc31_5, i32 0), !dbg !14
+// CHECK:STDOUT:   %F.call.loc31 = call double @_CF.Main.d4b5665541d5d7a8(double %.loc31_5, i32 0), !dbg !14
 // CHECK:STDOUT:   %.loc32_5 = load ptr, ptr %ptr_i32.var, align 8, !dbg !15
 // CHECK:STDOUT:   %F.call.loc32 = call ptr @_CF.Main.e8193710fd35b608(ptr %.loc32_5, i32 0), !dbg !16
 // CHECK:STDOUT:   %.loc33_5 = load ptr, ptr %ptr_f64.var, align 8, !dbg !17
@@ -82,7 +82,7 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %F.call, !dbg !26
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CF.Main.66be507887ceee78(double %x, i32 %count) !dbg !27 {
+// CHECK:STDOUT: define linkonce_odr double @_CF.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !27 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 0, !dbg !28
 // CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !29
@@ -92,7 +92,7 @@ fn M() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.else:                                          ; preds = %entry
 // CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !31
-// CHECK:STDOUT:   %F.call = call double @_CF.Main.66be507887ceee78(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !32
+// CHECK:STDOUT:   %F.call = call double @_CF.Main.d4b5665541d5d7a8(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !32
 // CHECK:STDOUT:   ret double %F.call, !dbg !33
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -146,7 +146,7 @@ fn M() {
 // CHECK:STDOUT: !24 = !DILocation(line: 21, column: 15, scope: !20)
 // CHECK:STDOUT: !25 = !DILocation(line: 21, column: 10, scope: !20)
 // CHECK:STDOUT: !26 = !DILocation(line: 21, column: 3, scope: !20)
-// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.66be507887ceee78", scope: null, file: !3, line: 17, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 17, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !28 = !DILocation(line: 18, column: 7, scope: !27)
 // CHECK:STDOUT: !29 = !DILocation(line: 18, column: 6, scope: !27)
 // CHECK:STDOUT: !30 = !DILocation(line: 19, column: 5, scope: !27)

+ 15 - 15
toolchain/lower/testdata/function/generic/call_recursive_diamond.carbon

@@ -76,7 +76,7 @@ fn M() {
 // CHECK:STDOUT:   %.loc53_5 = load i32, ptr %n.var, align 4, !dbg !11
 // CHECK:STDOUT:   %A.call.loc53 = call i32 @_CA.Main.b88d1103f417c6d4(i32 %.loc53_5, i32 0), !dbg !12
 // CHECK:STDOUT:   %.loc54_5 = load double, ptr %m.var, align 8, !dbg !13
-// CHECK:STDOUT:   %A.call.loc54 = call double @_CA.Main.66be507887ceee78(double %.loc54_5, i32 0), !dbg !14
+// CHECK:STDOUT:   %A.call.loc54 = call double @_CA.Main.d4b5665541d5d7a8(double %.loc54_5, i32 0), !dbg !14
 // CHECK:STDOUT:   %.loc55_5 = load ptr, ptr %ptr_i32.var, align 8, !dbg !15
 // CHECK:STDOUT:   %A.call.loc55 = call ptr @_CA.Main.e8193710fd35b608(ptr %.loc55_5, i32 0), !dbg !16
 // CHECK:STDOUT:   %.loc56_5 = load ptr, ptr %ptr_f64.var, align 8, !dbg !17
@@ -109,7 +109,7 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %C.call, !dbg !29
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CA.Main.66be507887ceee78(double %x, i32 %count) !dbg !30 {
+// CHECK:STDOUT: define linkonce_odr double @_CA.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !30 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 4, !dbg !31
 // CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then.loc22, label %if.else.loc22, !dbg !32
@@ -123,11 +123,11 @@ fn M() {
 // CHECK:STDOUT:   br i1 %Int.as.EqWith.impl.Equal.call, label %if.then.loc25, label %if.else.loc25, !dbg !35
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.then.loc25:                                    ; preds = %if.else.loc22
-// CHECK:STDOUT:   %B.call = call double @_CB.Main.66be507887ceee78(double %x, i32 %count), !dbg !36
+// CHECK:STDOUT:   %B.call = call double @_CB.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !36
 // CHECK:STDOUT:   ret double %B.call, !dbg !37
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.else.loc25:                                    ; preds = %if.else.loc22
-// CHECK:STDOUT:   %C.call = call double @_CC.Main.66be507887ceee78(double %x, i32 %count), !dbg !38
+// CHECK:STDOUT:   %C.call = call double @_CC.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !38
 // CHECK:STDOUT:   ret double %C.call, !dbg !39
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -167,17 +167,17 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %D.call, !dbg !57
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CB.Main.66be507887ceee78(double %x, i32 %count) !dbg !58 {
+// CHECK:STDOUT: define linkonce_odr double @_CB.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !58 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Print.call = call i32 (ptr, ...) @printf(ptr @printf.int.format, i32 1), !dbg !59
-// CHECK:STDOUT:   %D.call = call double @_CD.Main.66be507887ceee78(double %x, i32 %count), !dbg !60
+// CHECK:STDOUT:   %D.call = call double @_CD.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !60
 // CHECK:STDOUT:   ret double %D.call, !dbg !61
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CC.Main.66be507887ceee78(double %x, i32 %count) !dbg !62 {
+// CHECK:STDOUT: define linkonce_odr double @_CC.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !62 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Print.call = call i32 (ptr, ...) @printf(ptr @printf.int.format, i32 2), !dbg !63
-// CHECK:STDOUT:   %D.call = call double @_CD.Main.66be507887ceee78(double %x, i32 %count), !dbg !64
+// CHECK:STDOUT:   %D.call = call double @_CD.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !64
 // CHECK:STDOUT:   ret double %D.call, !dbg !65
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -204,10 +204,10 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %A.call, !dbg !77
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CD.Main.66be507887ceee78(double %x, i32 %count) !dbg !78 {
+// CHECK:STDOUT: define linkonce_odr double @_CD.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !78 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !79
-// CHECK:STDOUT:   %A.call = call double @_CA.Main.66be507887ceee78(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !80
+// CHECK:STDOUT:   %A.call = call double @_CA.Main.d4b5665541d5d7a8(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !80
 // CHECK:STDOUT:   ret double %A.call, !dbg !81
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -223,7 +223,7 @@ fn M() {
 // CHECK:STDOUT: uselistorder ptr @_CA.Main.e8193710fd35b608, { 1, 2, 0 }
 // CHECK:STDOUT: uselistorder ptr @printf, { 5, 4, 3, 2, 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @_CD.Main.b88d1103f417c6d4, { 1, 0 }
-// CHECK:STDOUT: uselistorder ptr @_CD.Main.66be507887ceee78, { 1, 0 }
+// CHECK:STDOUT: uselistorder ptr @_CD.Main.d4b5665541d5d7a8, { 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @_CD.Main.e8193710fd35b608, { 1, 0 }
 // CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
@@ -261,7 +261,7 @@ fn M() {
 // CHECK:STDOUT: !27 = !DILocation(line: 26, column: 5, scope: !20)
 // CHECK:STDOUT: !28 = !DILocation(line: 28, column: 12, scope: !20)
 // CHECK:STDOUT: !29 = !DILocation(line: 28, column: 5, scope: !20)
-// CHECK:STDOUT: !30 = distinct !DISubprogram(name: "A", linkageName: "_CA.Main.66be507887ceee78", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !30 = distinct !DISubprogram(name: "A", linkageName: "_CA.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !31 = !DILocation(line: 22, column: 7, scope: !30)
 // CHECK:STDOUT: !32 = !DILocation(line: 22, column: 6, scope: !30)
 // CHECK:STDOUT: !33 = !DILocation(line: 23, column: 5, scope: !30)
@@ -289,11 +289,11 @@ fn M() {
 // CHECK:STDOUT: !55 = !DILocation(line: 39, column: 3, scope: !54)
 // CHECK:STDOUT: !56 = !DILocation(line: 40, column: 10, scope: !54)
 // CHECK:STDOUT: !57 = !DILocation(line: 40, column: 3, scope: !54)
-// CHECK:STDOUT: !58 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.66be507887ceee78", scope: null, file: !3, line: 33, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !58 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 33, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !59 = !DILocation(line: 34, column: 3, scope: !58)
 // CHECK:STDOUT: !60 = !DILocation(line: 35, column: 10, scope: !58)
 // CHECK:STDOUT: !61 = !DILocation(line: 35, column: 3, scope: !58)
-// CHECK:STDOUT: !62 = distinct !DISubprogram(name: "C", linkageName: "_CC.Main.66be507887ceee78", scope: null, file: !3, line: 38, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !62 = distinct !DISubprogram(name: "C", linkageName: "_CC.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 38, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !63 = !DILocation(line: 39, column: 3, scope: !62)
 // CHECK:STDOUT: !64 = !DILocation(line: 40, column: 10, scope: !62)
 // CHECK:STDOUT: !65 = !DILocation(line: 40, column: 3, scope: !62)
@@ -309,7 +309,7 @@ fn M() {
 // CHECK:STDOUT: !75 = !DILocation(line: 44, column: 15, scope: !74)
 // CHECK:STDOUT: !76 = !DILocation(line: 44, column: 10, scope: !74)
 // CHECK:STDOUT: !77 = !DILocation(line: 44, column: 3, scope: !74)
-// CHECK:STDOUT: !78 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.66be507887ceee78", scope: null, file: !3, line: 43, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !78 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 43, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !79 = !DILocation(line: 44, column: 15, scope: !78)
 // CHECK:STDOUT: !80 = !DILocation(line: 44, column: 10, scope: !78)
 // CHECK:STDOUT: !81 = !DILocation(line: 44, column: 3, scope: !78)

+ 7 - 7
toolchain/lower/testdata/function/generic/call_recursive_mutual.carbon

@@ -59,7 +59,7 @@ fn M() {
 // CHECK:STDOUT:   %.loc38_5 = load i32, ptr %n.var, align 4, !dbg !11
 // CHECK:STDOUT:   %F.call.loc38 = call i32 @_CF.Main.b88d1103f417c6d4(i32 %.loc38_5, i32 0), !dbg !12
 // CHECK:STDOUT:   %.loc39_5 = load double, ptr %m.var, align 8, !dbg !13
-// CHECK:STDOUT:   %F.call.loc39 = call double @_CF.Main.66be507887ceee78(double %.loc39_5, i32 0), !dbg !14
+// CHECK:STDOUT:   %F.call.loc39 = call double @_CF.Main.d4b5665541d5d7a8(double %.loc39_5, i32 0), !dbg !14
 // CHECK:STDOUT:   %.loc40_5 = load ptr, ptr %ptr_i32.var, align 8, !dbg !15
 // CHECK:STDOUT:   %F.call.loc40 = call ptr @_CF.Main.e8193710fd35b608(ptr %.loc40_5, i32 0), !dbg !16
 // CHECK:STDOUT:   %.loc41_5 = load ptr, ptr %ptr_f64.var, align 8, !dbg !17
@@ -84,7 +84,7 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %G.call, !dbg !26
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CF.Main.66be507887ceee78(double %x, i32 %count) !dbg !27 {
+// CHECK:STDOUT: define linkonce_odr double @_CF.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !27 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 3, !dbg !28
 // CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !29
@@ -94,7 +94,7 @@ fn M() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.else:                                          ; preds = %entry
 // CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !31
-// CHECK:STDOUT:   %G.call = call double @_CG.Main.66be507887ceee78(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !32
+// CHECK:STDOUT:   %G.call = call double @_CG.Main.d4b5665541d5d7a8(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !32
 // CHECK:STDOUT:   ret double %G.call, !dbg !33
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -126,7 +126,7 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %F.call, !dbg !47
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CG.Main.66be507887ceee78(double %x, i32 %count) !dbg !48 {
+// CHECK:STDOUT: define linkonce_odr double @_CG.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !48 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 4, !dbg !49
 // CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !50
@@ -136,7 +136,7 @@ fn M() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.else:                                          ; preds = %entry
 // CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !52
-// CHECK:STDOUT:   %F.call = call double @_CF.Main.66be507887ceee78(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !53
+// CHECK:STDOUT:   %F.call = call double @_CF.Main.d4b5665541d5d7a8(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !53
 // CHECK:STDOUT:   ret double %F.call, !dbg !54
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -190,7 +190,7 @@ fn M() {
 // CHECK:STDOUT: !24 = !DILocation(line: 22, column: 15, scope: !20)
 // CHECK:STDOUT: !25 = !DILocation(line: 22, column: 10, scope: !20)
 // CHECK:STDOUT: !26 = !DILocation(line: 22, column: 3, scope: !20)
-// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.66be507887ceee78", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !28 = !DILocation(line: 19, column: 7, scope: !27)
 // CHECK:STDOUT: !29 = !DILocation(line: 19, column: 6, scope: !27)
 // CHECK:STDOUT: !30 = !DILocation(line: 20, column: 5, scope: !27)
@@ -211,7 +211,7 @@ fn M() {
 // CHECK:STDOUT: !45 = !DILocation(line: 29, column: 15, scope: !41)
 // CHECK:STDOUT: !46 = !DILocation(line: 29, column: 10, scope: !41)
 // CHECK:STDOUT: !47 = !DILocation(line: 29, column: 3, scope: !41)
-// CHECK:STDOUT: !48 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.66be507887ceee78", scope: null, file: !3, line: 25, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !48 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 25, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !49 = !DILocation(line: 26, column: 7, scope: !48)
 // CHECK:STDOUT: !50 = !DILocation(line: 26, column: 6, scope: !48)
 // CHECK:STDOUT: !51 = !DILocation(line: 27, column: 5, scope: !48)

+ 4 - 4
toolchain/lower/testdata/function/generic/call_recursive_reorder_more.carbon

@@ -94,7 +94,7 @@ fn M() {
 // CHECK:STDOUT:   %.loc42_5 = load double, ptr %val_f64.var, align 8, !dbg !32
 // CHECK:STDOUT:   %.loc42_14 = load ptr, ptr %ptr_bool.var, align 8, !dbg !33
 // CHECK:STDOUT:   %.loc42_24 = load ptr, ptr %ptr_bool.var, align 8, !dbg !34
-// CHECK:STDOUT:   %F.call.loc42 = call i32 @_CF.Main.f51a89281f4fb62e(double %.loc42_5, ptr %.loc42_14, ptr %.loc42_24, i32 0), !dbg !35
+// CHECK:STDOUT:   %F.call.loc42 = call i32 @_CF.Main.4dcab66ec095dfec(double %.loc42_5, ptr %.loc42_14, ptr %.loc42_24, i32 0), !dbg !35
 // CHECK:STDOUT:   %.loc46_5 = load ptr, ptr %ptr_bool.var, align 8, !dbg !36
 // CHECK:STDOUT:   %.loc46_15 = load ptr, ptr %ptr_i16.var, align 8, !dbg !37
 // CHECK:STDOUT:   %.loc46_24 = load ptr, ptr %ptr_i32.var, align 8, !dbg !38
@@ -185,7 +185,7 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %F.call, !dbg !92
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr i32 @_CF.Main.f51a89281f4fb62e(double %x, ptr %y, ptr %z, i32 %count) !dbg !93 {
+// CHECK:STDOUT: define linkonce_odr i32 @_CF.Main.4dcab66ec095dfec(double %x, ptr %y, ptr %z, i32 %count) !dbg !93 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 2, !dbg !94
 // CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !95
@@ -195,7 +195,7 @@ fn M() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.else:                                          ; preds = %entry
 // CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !97
-// CHECK:STDOUT:   %F.call = call i32 @_CF.Main.f51a89281f4fb62e(double %x, ptr %z, ptr %y, i32 %Int.as.AddWith.impl.Op.call), !dbg !98
+// CHECK:STDOUT:   %F.call = call i32 @_CF.Main.4dcab66ec095dfec(double %x, ptr %z, ptr %y, i32 %Int.as.AddWith.impl.Op.call), !dbg !98
 // CHECK:STDOUT:   ret i32 %F.call, !dbg !99
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -329,7 +329,7 @@ fn M() {
 // CHECK:STDOUT: !90 = !DILocation(line: 19, column: 21, scope: !86)
 // CHECK:STDOUT: !91 = !DILocation(line: 19, column: 10, scope: !86)
 // CHECK:STDOUT: !92 = !DILocation(line: 19, column: 3, scope: !86)
-// CHECK:STDOUT: !93 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.f51a89281f4fb62e", scope: null, file: !3, line: 15, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !93 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.4dcab66ec095dfec", scope: null, file: !3, line: 15, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !94 = !DILocation(line: 16, column: 7, scope: !93)
 // CHECK:STDOUT: !95 = !DILocation(line: 16, column: 6, scope: !93)
 // CHECK:STDOUT: !96 = !DILocation(line: 17, column: 5, scope: !93)

+ 25 - 25
toolchain/lower/testdata/function/generic/call_recursive_sccs_deep.carbon

@@ -103,7 +103,7 @@ fn M() {
 // CHECK:STDOUT:   %.loc79_5 = load i32, ptr %n.var, align 4, !dbg !11
 // CHECK:STDOUT:   %A.call.loc79 = call i32 @_CA.Main.b88d1103f417c6d4(i32 %.loc79_5, i32 0), !dbg !12
 // CHECK:STDOUT:   %.loc80_5 = load double, ptr %m.var, align 8, !dbg !13
-// CHECK:STDOUT:   %A.call.loc80 = call double @_CA.Main.66be507887ceee78(double %.loc80_5, i32 0), !dbg !14
+// CHECK:STDOUT:   %A.call.loc80 = call double @_CA.Main.d4b5665541d5d7a8(double %.loc80_5, i32 0), !dbg !14
 // CHECK:STDOUT:   %.loc81_5 = load ptr, ptr %ptr_i32.var, align 8, !dbg !15
 // CHECK:STDOUT:   %A.call.loc81 = call ptr @_CA.Main.e8193710fd35b608(ptr %.loc81_5, i32 0), !dbg !16
 // CHECK:STDOUT:   %.loc82_5 = load ptr, ptr %ptr_f64.var, align 8, !dbg !17
@@ -121,10 +121,10 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %D.call, !dbg !23
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CA.Main.66be507887ceee78(double %x, i32 %count) !dbg !24 {
+// CHECK:STDOUT: define linkonce_odr double @_CA.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !24 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   call void @_CB.Main.66be507887ceee78(double %x, i32 %count), !dbg !25
-// CHECK:STDOUT:   %D.call = call double @_CD.Main.66be507887ceee78(double %x, i32 %count), !dbg !26
+// CHECK:STDOUT:   call void @_CB.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !25
+// CHECK:STDOUT:   %D.call = call double @_CD.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !26
 // CHECK:STDOUT:   ret double %D.call, !dbg !27
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -163,13 +163,13 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %F.call, !dbg !44
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CB.Main.66be507887ceee78(double %x, i32 %count) !dbg !45 {
+// CHECK:STDOUT: define linkonce_odr void @_CB.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !45 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   call void @_CC.Main.66be507887ceee78(double %x, i32 %count), !dbg !46
+// CHECK:STDOUT:   call void @_CC.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !46
 // CHECK:STDOUT:   ret void, !dbg !47
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CD.Main.66be507887ceee78(double %x, i32 %count) !dbg !48 {
+// CHECK:STDOUT: define linkonce_odr double @_CD.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !48 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 4, !dbg !49
 // CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then.loc48, label %if.else.loc48, !dbg !50
@@ -183,11 +183,11 @@ fn M() {
 // CHECK:STDOUT:   br i1 %Int.as.EqWith.impl.Equal.call, label %if.then.loc51, label %if.else.loc51, !dbg !53
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.then.loc51:                                    ; preds = %if.else.loc48
-// CHECK:STDOUT:   %E.call = call double @_CE.Main.66be507887ceee78(double %x, i32 %count), !dbg !54
+// CHECK:STDOUT:   %E.call = call double @_CE.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !54
 // CHECK:STDOUT:   ret double %E.call, !dbg !55
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.else.loc51:                                    ; preds = %if.else.loc48
-// CHECK:STDOUT:   %F.call = call double @_CF.Main.66be507887ceee78(double %x, i32 %count), !dbg !56
+// CHECK:STDOUT:   %F.call = call double @_CF.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !56
 // CHECK:STDOUT:   ret double %F.call, !dbg !57
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -246,7 +246,7 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %G.call, !dbg !84
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CC.Main.66be507887ceee78(double %x, i32 %count) !dbg !85 {
+// CHECK:STDOUT: define linkonce_odr void @_CC.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !85 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.LessOrEquivalent.call = icmp sle i32 %count, 2, !dbg !86
 // CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.LessOrEquivalent.call, label %if.then, label %if.else, !dbg !87
@@ -254,22 +254,22 @@ fn M() {
 // CHECK:STDOUT: if.then:                                          ; preds = %entry
 // CHECK:STDOUT:   %Print.call = call i32 (ptr, ...) @printf(ptr @printf.int.format, i32 %count), !dbg !88
 // CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !89
-// CHECK:STDOUT:   call void @_CB.Main.66be507887ceee78(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !90
+// CHECK:STDOUT:   call void @_CB.Main.d4b5665541d5d7a8(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !90
 // CHECK:STDOUT:   br label %if.else, !dbg !91
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.else:                                          ; preds = %if.then, %entry
 // CHECK:STDOUT:   ret void, !dbg !92
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CE.Main.66be507887ceee78(double %x, i32 %count) !dbg !93 {
+// CHECK:STDOUT: define linkonce_odr double @_CE.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !93 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %G.call = call double @_CG.Main.66be507887ceee78(double %x, i32 %count), !dbg !94
+// CHECK:STDOUT:   %G.call = call double @_CG.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !94
 // CHECK:STDOUT:   ret double %G.call, !dbg !95
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CF.Main.66be507887ceee78(double %x, i32 %count) !dbg !96 {
+// CHECK:STDOUT: define linkonce_odr double @_CF.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !96 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %G.call = call double @_CG.Main.66be507887ceee78(double %x, i32 %count), !dbg !97
+// CHECK:STDOUT:   %G.call = call double @_CG.Main.d4b5665541d5d7a8(double %x, i32 %count), !dbg !97
 // CHECK:STDOUT:   ret double %G.call, !dbg !98
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -309,10 +309,10 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %D.call, !dbg !116
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CG.Main.66be507887ceee78(double %x, i32 %count) !dbg !117 {
+// CHECK:STDOUT: define linkonce_odr double @_CG.Main.d4b5665541d5d7a8(double %x, i32 %count) !dbg !117 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !118
-// CHECK:STDOUT:   %D.call = call double @_CD.Main.66be507887ceee78(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !119
+// CHECK:STDOUT:   %D.call = call double @_CD.Main.d4b5665541d5d7a8(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !119
 // CHECK:STDOUT:   ret double %D.call, !dbg !120
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -328,7 +328,7 @@ fn M() {
 // CHECK:STDOUT: uselistorder ptr @_CA.Main.e8193710fd35b608, { 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @printf, { 2, 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @_CG.Main.b88d1103f417c6d4, { 1, 0 }
-// CHECK:STDOUT: uselistorder ptr @_CG.Main.66be507887ceee78, { 1, 0 }
+// CHECK:STDOUT: uselistorder ptr @_CG.Main.d4b5665541d5d7a8, { 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @_CG.Main.e8193710fd35b608, { 1, 0 }
 // CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
@@ -360,7 +360,7 @@ fn M() {
 // CHECK:STDOUT: !21 = !DILocation(line: 32, column: 3, scope: !20)
 // CHECK:STDOUT: !22 = !DILocation(line: 33, column: 10, scope: !20)
 // CHECK:STDOUT: !23 = !DILocation(line: 33, column: 3, scope: !20)
-// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "A", linkageName: "_CA.Main.66be507887ceee78", scope: null, file: !3, line: 31, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "A", linkageName: "_CA.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 31, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !25 = !DILocation(line: 32, column: 3, scope: !24)
 // CHECK:STDOUT: !26 = !DILocation(line: 33, column: 10, scope: !24)
 // CHECK:STDOUT: !27 = !DILocation(line: 33, column: 3, scope: !24)
@@ -381,10 +381,10 @@ fn M() {
 // CHECK:STDOUT: !42 = !DILocation(line: 52, column: 5, scope: !35)
 // CHECK:STDOUT: !43 = !DILocation(line: 54, column: 12, scope: !35)
 // CHECK:STDOUT: !44 = !DILocation(line: 54, column: 5, scope: !35)
-// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.66be507887ceee78", scope: null, file: !3, line: 36, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 36, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !46 = !DILocation(line: 37, column: 3, scope: !45)
 // CHECK:STDOUT: !47 = !DILocation(line: 36, column: 1, scope: !45)
-// CHECK:STDOUT: !48 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.66be507887ceee78", scope: null, file: !3, line: 47, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !48 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 47, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !49 = !DILocation(line: 48, column: 7, scope: !48)
 // CHECK:STDOUT: !50 = !DILocation(line: 48, column: 6, scope: !48)
 // CHECK:STDOUT: !51 = !DILocation(line: 49, column: 5, scope: !48)
@@ -421,7 +421,7 @@ fn M() {
 // CHECK:STDOUT: !82 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.b88d1103f417c6d4", scope: null, file: !3, line: 64, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !83 = !DILocation(line: 65, column: 10, scope: !82)
 // CHECK:STDOUT: !84 = !DILocation(line: 65, column: 3, scope: !82)
-// CHECK:STDOUT: !85 = distinct !DISubprogram(name: "C", linkageName: "_CC.Main.66be507887ceee78", scope: null, file: !3, line: 40, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !85 = distinct !DISubprogram(name: "C", linkageName: "_CC.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 40, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !86 = !DILocation(line: 41, column: 7, scope: !85)
 // CHECK:STDOUT: !87 = !DILocation(line: 41, column: 6, scope: !85)
 // CHECK:STDOUT: !88 = !DILocation(line: 42, column: 5, scope: !85)
@@ -429,10 +429,10 @@ fn M() {
 // CHECK:STDOUT: !90 = !DILocation(line: 43, column: 5, scope: !85)
 // CHECK:STDOUT: !91 = !DILocation(line: 41, column: 3, scope: !85)
 // CHECK:STDOUT: !92 = !DILocation(line: 40, column: 1, scope: !85)
-// CHECK:STDOUT: !93 = distinct !DISubprogram(name: "E", linkageName: "_CE.Main.66be507887ceee78", scope: null, file: !3, line: 60, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !93 = distinct !DISubprogram(name: "E", linkageName: "_CE.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 60, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !94 = !DILocation(line: 61, column: 10, scope: !93)
 // CHECK:STDOUT: !95 = !DILocation(line: 61, column: 3, scope: !93)
-// CHECK:STDOUT: !96 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.66be507887ceee78", scope: null, file: !3, line: 64, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !96 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 64, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !97 = !DILocation(line: 65, column: 10, scope: !96)
 // CHECK:STDOUT: !98 = !DILocation(line: 65, column: 3, scope: !96)
 // CHECK:STDOUT: !99 = distinct !DISubprogram(name: "C", linkageName: "_CC.Main.e8193710fd35b608", scope: null, file: !3, line: 40, type: !5, spFlags: DISPFlagDefinition, unit: !2)
@@ -453,7 +453,7 @@ fn M() {
 // CHECK:STDOUT: !114 = !DILocation(line: 69, column: 15, scope: !113)
 // CHECK:STDOUT: !115 = !DILocation(line: 69, column: 10, scope: !113)
 // CHECK:STDOUT: !116 = !DILocation(line: 69, column: 3, scope: !113)
-// CHECK:STDOUT: !117 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.66be507887ceee78", scope: null, file: !3, line: 68, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !117 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 68, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !118 = !DILocation(line: 69, column: 15, scope: !117)
 // CHECK:STDOUT: !119 = !DILocation(line: 69, column: 10, scope: !117)
 // CHECK:STDOUT: !120 = !DILocation(line: 69, column: 3, scope: !117)

+ 9 - 9
toolchain/lower/testdata/function/generic/call_specific_in_class.carbon

@@ -73,7 +73,7 @@ fn M() {
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 8, ptr %var_f64.var), !dbg !11
 // CHECK:STDOUT:   store double 0.000000e+00, ptr %var_f64.var, align 8, !dbg !11
 // CHECK:STDOUT:   %.loc42 = load double, ptr %var_f64.var, align 8, !dbg !21
-// CHECK:STDOUT:   %F.call.loc42 = call double @_CF.Main.66be507887ceee78(double %.loc42), !dbg !22
+// CHECK:STDOUT:   %F.call.loc42 = call double @_CF.Main.d4b5665541d5d7a8(double %.loc42), !dbg !22
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 0, ptr %c.var), !dbg !12
 // CHECK:STDOUT:   %F.call.loc44 = call %type @_CF.Main.5754c7a55c7cbe4a(%type zeroinitializer), !dbg !23
 // CHECK:STDOUT:   ret void, !dbg !24
@@ -94,9 +94,9 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %G.call, !dbg !30
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CF.Main.66be507887ceee78(double %x) !dbg !31 {
+// CHECK:STDOUT: define linkonce_odr double @_CF.Main.d4b5665541d5d7a8(double %x) !dbg !31 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %G.call = call double @_CG.Main.66be507887ceee78(double %x), !dbg !32
+// CHECK:STDOUT:   %G.call = call double @_CG.Main.d4b5665541d5d7a8(double %x), !dbg !32
 // CHECK:STDOUT:   ret double %G.call, !dbg !33
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -122,11 +122,11 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %C.Cfn.call, !dbg !44
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CG.Main.66be507887ceee78(double %x) !dbg !45 {
+// CHECK:STDOUT: define linkonce_odr double @_CG.Main.d4b5665541d5d7a8(double %x) !dbg !45 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %c.var = alloca {}, align 8, !dbg !46
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 0, ptr %c.var), !dbg !46
-// CHECK:STDOUT:   %C.Cfn.call = call double @_CCfn.C.Main.66be507887ceee78(ptr %c.var, double %x), !dbg !47
+// CHECK:STDOUT:   %C.Cfn.call = call double @_CCfn.C.Main.d4b5665541d5d7a8(ptr %c.var, double %x), !dbg !47
 // CHECK:STDOUT:   ret double %C.Cfn.call, !dbg !48
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -148,7 +148,7 @@ fn M() {
 // CHECK:STDOUT:   ret i32 %x, !dbg !56
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CCfn.C.Main.66be507887ceee78(ptr %self, double %x) !dbg !57 {
+// CHECK:STDOUT: define linkonce_odr double @_CCfn.C.Main.d4b5665541d5d7a8(ptr %self, double %x) !dbg !57 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   ret double %x, !dbg !58
 // CHECK:STDOUT: }
@@ -198,7 +198,7 @@ fn M() {
 // CHECK:STDOUT: !28 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.b88d1103f417c6d4", scope: null, file: !3, line: 28, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !29 = !DILocation(line: 29, column: 10, scope: !28)
 // CHECK:STDOUT: !30 = !DILocation(line: 29, column: 3, scope: !28)
-// CHECK:STDOUT: !31 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.66be507887ceee78", scope: null, file: !3, line: 28, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !31 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 28, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !32 = !DILocation(line: 29, column: 10, scope: !31)
 // CHECK:STDOUT: !33 = !DILocation(line: 29, column: 3, scope: !31)
 // CHECK:STDOUT: !34 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.5754c7a55c7cbe4a", scope: null, file: !3, line: 28, type: !5, spFlags: DISPFlagDefinition, unit: !2)
@@ -212,7 +212,7 @@ fn M() {
 // CHECK:STDOUT: !42 = !DILocation(line: 24, column: 3, scope: !41)
 // CHECK:STDOUT: !43 = !DILocation(line: 25, column: 10, scope: !41)
 // CHECK:STDOUT: !44 = !DILocation(line: 25, column: 3, scope: !41)
-// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.66be507887ceee78", scope: null, file: !3, line: 23, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 23, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !46 = !DILocation(line: 24, column: 3, scope: !45)
 // CHECK:STDOUT: !47 = !DILocation(line: 25, column: 10, scope: !45)
 // CHECK:STDOUT: !48 = !DILocation(line: 25, column: 3, scope: !45)
@@ -224,7 +224,7 @@ fn M() {
 // CHECK:STDOUT: !54 = !DILocation(line: 19, column: 5, scope: !53)
 // CHECK:STDOUT: !55 = distinct !DISubprogram(name: "Cfn", linkageName: "_CCfn.C.Main.b88d1103f417c6d4", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !56 = !DILocation(line: 19, column: 5, scope: !55)
-// CHECK:STDOUT: !57 = distinct !DISubprogram(name: "Cfn", linkageName: "_CCfn.C.Main.66be507887ceee78", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !57 = distinct !DISubprogram(name: "Cfn", linkageName: "_CCfn.C.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !58 = !DILocation(line: 19, column: 5, scope: !57)
 // CHECK:STDOUT: !59 = distinct !DISubprogram(name: "Cfn", linkageName: "_CCfn.C.Main.5754c7a55c7cbe4a", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !60 = !DILocation(line: 19, column: 5, scope: !59)

+ 2 - 2
toolchain/lower/testdata/struct/member_access.carbon

@@ -28,8 +28,8 @@ fn Run() -> i32 {
 // CHECK:STDOUT:   %y.var = alloca i32, align 4, !dbg !8
 // CHECK:STDOUT:   %z.var = alloca i32, align 4, !dbg !9
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 16, ptr %x.var), !dbg !7
-// CHECK:STDOUT:   %.loc14_48.2.a = getelementptr inbounds nuw { double, i32 }, ptr %x.var, i32 0, i32 0, !dbg !10
-// CHECK:STDOUT:   %.loc14_48.5.b = getelementptr inbounds nuw { double, i32 }, ptr %x.var, i32 0, i32 1, !dbg !10
+// CHECK:STDOUT:   %.loc14_48.3.a = getelementptr inbounds nuw { double, i32 }, ptr %x.var, i32 0, i32 0, !dbg !10
+// CHECK:STDOUT:   %.loc14_48.6.b = getelementptr inbounds nuw { double, i32 }, ptr %x.var, i32 0, i32 1, !dbg !10
 // CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x.var, ptr align 8 @struct.loc14_3, i64 16, i1 false), !dbg !7
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 4, ptr %y.var), !dbg !8
 // CHECK:STDOUT:   %.loc15_17.1.b = getelementptr inbounds nuw { double, i32 }, ptr %x.var, i32 0, i32 1, !dbg !11

+ 49 - 7
toolchain/sem_ir/builtin_function_kind.cpp

@@ -123,7 +123,8 @@ struct AnySizedInt {
   }
 };
 
-// Constraint that requires the type to be an integer type.
+// Constraint that requires the type to be an integer type: either a sized
+// integer type or a literal.
 struct AnyInt {
   static auto Check(const File& sem_ir, ValidateState& state, TypeId type_id)
       -> bool {
@@ -133,15 +134,22 @@ struct AnyInt {
   }
 };
 
-// Constraint that requires the type to be a float type.
+// Constraint that requires the type to be a sized floating-point type.
+struct AnySizedFloat {
+  static auto Check(const File& sem_ir, ValidateState& /*state*/,
+                    TypeId type_id) -> bool {
+    return sem_ir.types().Is<FloatType>(type_id);
+  }
+};
+
+// Constraint that requires the type to be a float type: either a sized float
+// type or a literal.
 struct AnyFloat {
   static auto Check(const File& sem_ir, ValidateState& state, TypeId type_id)
       -> bool {
-    if (BuiltinType<LegacyFloatType::TypeInstId>::Check(sem_ir, state,
-                                                        type_id)) {
-      return true;
-    }
-    return sem_ir.types().Is<FloatType>(type_id);
+    return AnySizedFloat::Check(sem_ir, state, type_id) ||
+           BuiltinType<LegacyFloatType::TypeInstId>::Check(sem_ir, state,
+                                                           type_id);
   }
 };
 
@@ -251,6 +259,10 @@ using SizedIntU = TypeParam<1, AnySizedInt>;
 // generic type parameter that is constrained to be an float type.
 using FloatT = TypeParam<0, AnyFloat>;
 
+// Convenience name used in the builtin type signatures below for a second
+// generic type parameter that is constrained to be an float type.
+using FloatU = TypeParam<1, AnyFloat>;
+
 // Not a builtin function.
 constexpr BuiltinInfo None = {"", nullptr};
 
@@ -276,6 +288,10 @@ constexpr BuiltinInfo CharLiteralMakeType = {"char_literal.make_type",
 constexpr BuiltinInfo IntLiteralMakeType = {"int_literal.make_type",
                                             ValidateSignature<auto()->Type>};
 
+// Returns the `Core.FloatLiteral` type.
+constexpr BuiltinInfo FloatLiteralMakeType = {"float_literal.make_type",
+                                              ValidateSignature<auto()->Type>};
+
 // Returns the `iN` type.
 // TODO: Should we use a more specific type as the type of the bit width?
 constexpr BuiltinInfo IntMakeTypeSigned = {
@@ -497,6 +513,31 @@ constexpr BuiltinInfo FloatMul = {
 constexpr BuiltinInfo FloatDiv = {
     "float.div", ValidateSignature<auto(FloatT, FloatT)->FloatT>};
 
+// "float.add_assign": float in-place addition.
+constexpr BuiltinInfo FloatAddAssign = {
+    "float.add_assign",
+    ValidateSignature<auto(PointerTo<FloatT>, FloatT)->NoReturn>};
+
+// "float.sub_assign": float in-place subtraction.
+constexpr BuiltinInfo FloatSubAssign = {
+    "float.sub_assign",
+    ValidateSignature<auto(PointerTo<FloatT>, FloatT)->NoReturn>};
+
+// "float.mul_assign": float in-place multiplication.
+constexpr BuiltinInfo FloatMulAssign = {
+    "float.mul_assign",
+    ValidateSignature<auto(PointerTo<FloatT>, FloatT)->NoReturn>};
+
+// "float.div_assign": float in-place division.
+constexpr BuiltinInfo FloatDivAssign = {
+    "float.div_assign",
+    ValidateSignature<auto(PointerTo<FloatT>, FloatT)->NoReturn>};
+
+// Converts between floating-point types, with a diagnostic if the value doesn't
+// fit.
+constexpr BuiltinInfo FloatConvertChecked = {
+    "float.convert_checked", ValidateSignature<auto(FloatT)->FloatU>};
+
 // "float.eq": float equality comparison.
 constexpr BuiltinInfo FloatEq = {"float.eq",
                                  ValidateSignature<auto(FloatT, FloatT)->Bool>};
@@ -608,6 +649,7 @@ auto BuiltinFunctionKind::IsCompTimeOnly(const File& sem_ir,
                                          TypeId return_type_id) const -> bool {
   switch (*this) {
     case CharConvertChecked:
+    case FloatConvertChecked:
     case IntConvertChecked:
       // Checked conversions are compile-time only.
       return true;

+ 10 - 0
toolchain/sem_ir/builtin_function_kind.def

@@ -30,6 +30,7 @@ CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(ReadChar)
 // Type factories.
 CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(CharLiteralMakeType)
 CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntLiteralMakeType)
+CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatLiteralMakeType)
 CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntMakeTypeSigned)
 CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntMakeTypeUnsigned)
 CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatMakeType)
@@ -96,6 +97,15 @@ CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatSub)
 CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatMul)
 CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatDiv)
 
+// Float compound assignment.
+CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatAddAssign)
+CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatSubAssign)
+CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatMulAssign)
+CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatDivAssign)
+
+// Float conversion.
+CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatConvertChecked)
+
 // Float comparison.
 CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatEq)
 CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(FloatNeq)

+ 2 - 1
toolchain/sem_ir/stringify.cpp

@@ -369,7 +369,8 @@ class Stringifier {
   }
 
   auto StringifyInst(InstId /*inst_id*/, FloatType inst) -> void {
-    // TODO: Is this okay?
+    *out_ << "<builtin ";
+    step_stack_->PushString(">");
     if (auto width_value =
             sem_ir_->insts().TryGetAs<IntValue>(inst.bit_width_id)) {
       *out_ << "f";

+ 15 - 15
toolchain/sem_ir/typed_insts.h

@@ -691,17 +691,6 @@ struct FieldDecl {
   ElementIndex index;
 };
 
-// A floating point value.
-struct FloatValue {
-  static constexpr auto Kind =
-      InstKind::FloatValue.Define<Parse::RealLiteralId>(
-          {.ir_name = "float_value",
-           .constant_kind = InstConstantKind::Always});
-
-  TypeId type_id;
-  FloatId float_id;
-};
-
 // A floating point type.
 struct FloatType {
   static constexpr auto Kind = InstKind::FloatType.Define<Parse::NoneNodeId>(
@@ -717,6 +706,17 @@ struct FloatType {
   InstId bit_width_id;
 };
 
+// A floating point value.
+struct FloatValue {
+  static constexpr auto Kind =
+      InstKind::FloatValue.Define<Parse::RealLiteralId>(
+          {.ir_name = "float_value",
+           .constant_kind = InstConstantKind::Always});
+
+  TypeId type_id;
+  FloatId float_id;
+};
+
 // A function declaration.
 struct FunctionDecl {
   static constexpr auto Kind =
@@ -1085,13 +1085,13 @@ struct IntValue {
   IntId int_id;
 };
 
-// The legacy float type. This is currently used for real literals, and is
-// treated as f64. It's separate from `FloatType`, and should change to mirror
-// integers, likely replacing this with a `FloatLiteralType`.
+// The float literal type. This is currently represented as f64.
+// TODO: Rename this to FloatLiteralType.
+// TODO: Replace this with a rational number type, following the design.
 struct LegacyFloatType {
   static constexpr auto Kind =
       InstKind::LegacyFloatType.Define<Parse::NoneNodeId>(
-          {.ir_name = "f64",
+          {.ir_name = "Core.FloatLiteral",
            .is_type = InstIsType::Always,
            .constant_kind = InstConstantKind::Always});
   // This is a singleton instruction. However, it may still evolve into a more

+ 18 - 1
toolchain/testing/testdata/min_prelude/parts/float.carbon

@@ -2,12 +2,29 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/as.carbon
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/float_literal.carbon
 // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/parts/int_literal.carbon
 
 // --- min_prelude/parts/float.carbon
 
 package Core library "prelude/parts/float";
 
+export import library "prelude/parts/as";
+export import library "prelude/parts/float_literal";
 export import library "prelude/parts/int_literal";
 
-fn Float(size: IntLiteral()) -> type = "float.make_type";
+private fn MakeFloat(size: IntLiteral()) -> type = "float.make_type";
+
+class Float(N:! IntLiteral()) {
+  adapt MakeFloat(N);
+}
+
+impl forall [To:! IntLiteral()] FloatLiteral() as ImplicitAs(Float(To)) {
+  fn Convert[self: Self]() -> Float(To) = "float.convert_checked";
+}
+
+// TODO: Remove this once ImplicitAs extends As.
+impl forall [To:! IntLiteral()] FloatLiteral() as As(Float(To)) {
+  fn Convert[self: Self]() -> Float(To) = "float.convert_checked";
+}

+ 9 - 0
toolchain/testing/testdata/min_prelude/parts/float_literal.carbon

@@ -0,0 +1,9 @@
+// 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
+
+// --- min_prelude/parts/float_literal.carbon
+
+package Core library "prelude/parts/float_literal";
+
+fn FloatLiteral() -> type = "float_literal.make_type";