Compute and cache the value representation of a type when it becomes complete. (#3271)

Using the computed value representation, fix lowering of struct and
tuple values to use the value representation rather than the object
representation. Fixes an issue found in the review of #3257.

This currently causes us to compute value representations of all types
as they are created, which generates substantially more SemIR to
represent types. We can get some of that back by deferring computation
of the value representation until the type is required to be complete,
but some of the additional cost here will persist with this approach.

I also considered making the computation of the value representation
type be something that lives entirely within the lowering phase, but I
think that's not the right approach in the longer term, because the
value representation will be semantically visible and relevant once we
start allowing it to be customized.

We should consider moving the nodes that exist to compute canonical
non-local types, including value representations, out into a separate
global block. That will clean up the SemIR representation substantially,
and make the SemIR produced for a function not depend on which types we
happen to have encountered beforehand. But that's not being done in this
PR.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
This commit is contained in:
Richard Smith
2023-10-13 22:27:02 +00:00
committed by GitHub
co-authored by Chandler Carruth
parent 1ae5fe0cd5
commit e4caf7d604
61 changed files with 837 additions and 508 deletions
+7 -4
View File
@@ -21,7 +21,8 @@ fn G() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc10_25: (type, type, type) = tuple_literal (i32, i32, i32)
// CHECK:STDOUT: %.loc10_28: i32 = int_literal 2
// CHECK:STDOUT: %.loc10_29: type = array_type %.loc10_28, (i32, i32, i32)
// CHECK:STDOUT: %.loc10_29.1: type = array_type %.loc10_28, (i32, i32, i32)
// CHECK:STDOUT: %.loc10_29.2: type = ptr_type [(i32, i32, i32); 2]
// CHECK:STDOUT: %v: ref [(i32, i32, i32); 2] = var "v"
// CHECK:STDOUT: %F.ref.loc10_34: <function> = name_reference "F", package.%F
// CHECK:STDOUT: %.loc10_42.3: ref (i32, i32, i32) = splice_block %.loc10_42.2 {
@@ -36,8 +37,10 @@ fn G() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc10_40: init (i32, i32, i32) = call %F.ref.loc10_39() to %.loc10_42.6
// CHECK:STDOUT: %.loc10_42.7: type = tuple_type ((i32, i32, i32), (i32, i32, i32))
// CHECK:STDOUT: %.loc10_42.8: ((i32, i32, i32), (i32, i32, i32)) = tuple_literal (%.loc10_35, %.loc10_40)
// CHECK:STDOUT: %.loc10_42.9: init [(i32, i32, i32); 2] = array_init %.loc10_42.8, (%.loc10_35, %.loc10_40) to %v
// CHECK:STDOUT: assign %v, %.loc10_42.9
// CHECK:STDOUT: %.loc10_42.8: type = tuple_type ((i32, i32, i32)*, (i32, i32, i32)*)
// CHECK:STDOUT: %.loc10_42.9: type = ptr_type ((i32, i32, i32)*, (i32, i32, i32)*)
// CHECK:STDOUT: %.loc10_42.10: ((i32, i32, i32), (i32, i32, i32)) = tuple_literal (%.loc10_35, %.loc10_40)
// CHECK:STDOUT: %.loc10_42.11: init [(i32, i32, i32); 2] = array_init %.loc10_42.10, (%.loc10_35, %.loc10_40) to %v
// CHECK:STDOUT: assign %v, %.loc10_42.11
// CHECK:STDOUT: return
// CHECK:STDOUT: }
+2 -1
View File
@@ -26,7 +26,8 @@ fn Run() {
// CHECK:STDOUT: fn @Run() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc10_16: i32 = int_literal 1
// CHECK:STDOUT: %.loc10_17: type = array_type %.loc10_16, i32
// CHECK:STDOUT: %.loc10_17.1: type = array_type %.loc10_16, i32
// CHECK:STDOUT: %.loc10_17.2: type = ptr_type [i32; 1]
// CHECK:STDOUT: %t: ref [i32; 1] = var "t"
// CHECK:STDOUT: %F.ref: <function> = name_reference "F", package.%F
// CHECK:STDOUT: %.loc10_22.1: init (i32,) = call %F.ref()
+6 -3
View File
@@ -9,8 +9,10 @@ var b: [i32; 3] = a;
// CHECK:STDOUT: file "assign_var.carbon" {
// CHECK:STDOUT: %.loc7_22.1: type = tuple_type (type, type, type)
// CHECK:STDOUT: %.loc7_22.2: (type, type, type) = tuple_literal (i32, i32, i32)
// CHECK:STDOUT: %.loc7_22.3: type = tuple_type (i32, i32, i32)
// CHECK:STDOUT: %.loc7_22.2: type = ptr_type (type, type, type)
// CHECK:STDOUT: %.loc7_22.3: (type, type, type) = tuple_literal (i32, i32, i32)
// CHECK:STDOUT: %.loc7_22.4: type = tuple_type (i32, i32, i32)
// CHECK:STDOUT: %.loc7_22.5: type = ptr_type (i32, i32, i32)
// CHECK:STDOUT: %a: ref (i32, i32, i32) = var "a"
// CHECK:STDOUT: %.loc7_27: i32 = int_literal 1
// CHECK:STDOUT: %.loc7_30: i32 = int_literal 2
@@ -25,7 +27,8 @@ var b: [i32; 3] = a;
// CHECK:STDOUT: %.loc7_34.8: init (i32, i32, i32) = tuple_init %.loc7_34.1, (%.loc7_34.3, %.loc7_34.5, %.loc7_34.7)
// CHECK:STDOUT: assign %a, %.loc7_34.8
// CHECK:STDOUT: %.loc8_14: i32 = int_literal 3
// CHECK:STDOUT: %.loc8_15: type = array_type %.loc8_14, i32
// CHECK:STDOUT: %.loc8_15.1: type = array_type %.loc8_14, i32
// CHECK:STDOUT: %.loc8_15.2: type = ptr_type [i32; 3]
// CHECK:STDOUT: %b: ref [i32; 3] = var "b"
// CHECK:STDOUT: %a.ref: ref (i32, i32, i32) = name_reference "a", %a
// CHECK:STDOUT: %.loc8_19.1: ref i32 = tuple_access %a.ref, member0
+20 -15
View File
@@ -10,7 +10,8 @@ var c: [(); 5] = ((), (), (), (), (),);
// CHECK:STDOUT: file "base.carbon" {
// CHECK:STDOUT: %.loc7_14: i32 = int_literal 1
// CHECK:STDOUT: %.loc7_15: type = array_type %.loc7_14, i32
// CHECK:STDOUT: %.loc7_15.1: type = array_type %.loc7_14, i32
// CHECK:STDOUT: %.loc7_15.2: type = ptr_type [i32; 1]
// CHECK:STDOUT: %a: ref [i32; 1] = var "a"
// CHECK:STDOUT: %.loc7_20: i32 = int_literal 1
// CHECK:STDOUT: %.loc7_22.1: type = tuple_type (i32)
@@ -21,24 +22,27 @@ var c: [(); 5] = ((), (), (), (), (),);
// CHECK:STDOUT: %.loc7_22.6: init [i32; 1] = array_init %.loc7_22.2, (%.loc7_22.5) to %a
// CHECK:STDOUT: assign %a, %.loc7_22.6
// CHECK:STDOUT: %.loc8_14: i32 = int_literal 2
// CHECK:STDOUT: %.loc8_15: type = array_type %.loc8_14, f64
// CHECK:STDOUT: %.loc8_15.1: type = array_type %.loc8_14, f64
// CHECK:STDOUT: %.loc8_15.2: type = ptr_type [f64; 2]
// CHECK:STDOUT: %b: ref [f64; 2] = var "b"
// CHECK:STDOUT: %.loc8_20: f64 = real_literal 111e-1
// CHECK:STDOUT: %.loc8_26: f64 = real_literal 22e-1
// CHECK:STDOUT: %.loc8_30.1: type = tuple_type (f64, f64)
// CHECK:STDOUT: %.loc8_30.2: (f64, f64) = tuple_literal (%.loc8_20, %.loc8_26)
// CHECK:STDOUT: %.loc8_30.3: i32 = int_literal 0
// CHECK:STDOUT: %.loc8_30.4: ref f64 = array_index %b, %.loc8_30.3
// CHECK:STDOUT: %.loc8_30.5: init f64 = initialize_from %.loc8_20 to %.loc8_30.4
// CHECK:STDOUT: %.loc8_30.6: i32 = int_literal 1
// CHECK:STDOUT: %.loc8_30.7: ref f64 = array_index %b, %.loc8_30.6
// CHECK:STDOUT: %.loc8_30.8: init f64 = initialize_from %.loc8_26 to %.loc8_30.7
// CHECK:STDOUT: %.loc8_30.9: init [f64; 2] = array_init %.loc8_30.2, (%.loc8_30.5, %.loc8_30.8) to %b
// CHECK:STDOUT: assign %b, %.loc8_30.9
// CHECK:STDOUT: %.loc8_30.2: type = ptr_type (f64, f64)
// CHECK:STDOUT: %.loc8_30.3: (f64, f64) = tuple_literal (%.loc8_20, %.loc8_26)
// CHECK:STDOUT: %.loc8_30.4: i32 = int_literal 0
// CHECK:STDOUT: %.loc8_30.5: ref f64 = array_index %b, %.loc8_30.4
// CHECK:STDOUT: %.loc8_30.6: init f64 = initialize_from %.loc8_20 to %.loc8_30.5
// CHECK:STDOUT: %.loc8_30.7: i32 = int_literal 1
// CHECK:STDOUT: %.loc8_30.8: ref f64 = array_index %b, %.loc8_30.7
// CHECK:STDOUT: %.loc8_30.9: init f64 = initialize_from %.loc8_26 to %.loc8_30.8
// CHECK:STDOUT: %.loc8_30.10: init [f64; 2] = array_init %.loc8_30.3, (%.loc8_30.6, %.loc8_30.9) to %b
// CHECK:STDOUT: assign %b, %.loc8_30.10
// CHECK:STDOUT: %.loc9_10.1: type = tuple_type ()
// CHECK:STDOUT: %.loc9_10.2: () = tuple_literal ()
// CHECK:STDOUT: %.loc9_13: i32 = int_literal 5
// CHECK:STDOUT: %.loc9_14: type = array_type %.loc9_13, ()
// CHECK:STDOUT: %.loc9_14.1: type = array_type %.loc9_13, ()
// CHECK:STDOUT: %.loc9_14.2: type = ptr_type [(); 5]
// CHECK:STDOUT: %c: ref [(); 5] = var "c"
// CHECK:STDOUT: %.loc9_20.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc9_24.1: () = tuple_literal ()
@@ -46,12 +50,13 @@ var c: [(); 5] = ((), (), (), (), (),);
// CHECK:STDOUT: %.loc9_32.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc9_36.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc9_38.1: type = tuple_type ((), (), (), (), ())
// CHECK:STDOUT: %.loc9_38.2: ((), (), (), (), ()) = tuple_literal (%.loc9_20.1, %.loc9_24.1, %.loc9_28.1, %.loc9_32.1, %.loc9_36.1)
// CHECK:STDOUT: %.loc9_38.2: type = ptr_type ((), (), (), (), ())
// CHECK:STDOUT: %.loc9_38.3: ((), (), (), (), ()) = tuple_literal (%.loc9_20.1, %.loc9_24.1, %.loc9_28.1, %.loc9_32.1, %.loc9_36.1)
// CHECK:STDOUT: %.loc9_20.2: init () = tuple_init %.loc9_20.1, ()
// CHECK:STDOUT: %.loc9_24.2: init () = tuple_init %.loc9_24.1, ()
// CHECK:STDOUT: %.loc9_28.2: init () = tuple_init %.loc9_28.1, ()
// CHECK:STDOUT: %.loc9_32.2: init () = tuple_init %.loc9_32.1, ()
// CHECK:STDOUT: %.loc9_36.2: init () = tuple_init %.loc9_36.1, ()
// CHECK:STDOUT: %.loc9_38.3: init [(); 5] = array_init %.loc9_38.2, (%.loc9_20.2, %.loc9_24.2, %.loc9_28.2, %.loc9_32.2, %.loc9_36.2) to %c
// CHECK:STDOUT: assign %c, %.loc9_38.3
// CHECK:STDOUT: %.loc9_38.4: init [(); 5] = array_init %.loc9_38.3, (%.loc9_20.2, %.loc9_24.2, %.loc9_28.2, %.loc9_32.2, %.loc9_36.2) to %c
// CHECK:STDOUT: assign %c, %.loc9_38.4
// CHECK:STDOUT: }
+2 -1
View File
@@ -12,6 +12,7 @@ var a: [1; 1];
// CHECK:STDOUT: file "fail_invalid_type.carbon" {
// CHECK:STDOUT: %.loc10_9: i32 = int_literal 1
// CHECK:STDOUT: %.loc10_12: i32 = int_literal 1
// CHECK:STDOUT: %.loc10_13: type = array_type %.loc10_12, <error>
// CHECK:STDOUT: %.loc10_13.1: type = array_type %.loc10_12, <error>
// CHECK:STDOUT: %.loc10_13.2: type = ptr_type [<error>; 1]
// CHECK:STDOUT: %a: ref [<error>; 1] = var "a"
// CHECK:STDOUT: }
+4 -2
View File
@@ -11,12 +11,14 @@ var a: [i32; 1] = (1, 2, 3);
// CHECK:STDOUT: file "fail_out_of_bound.carbon" {
// CHECK:STDOUT: %.loc10_14: i32 = int_literal 1
// CHECK:STDOUT: %.loc10_15: type = array_type %.loc10_14, i32
// CHECK:STDOUT: %.loc10_15.1: type = array_type %.loc10_14, i32
// CHECK:STDOUT: %.loc10_15.2: type = ptr_type [i32; 1]
// CHECK:STDOUT: %a: ref [i32; 1] = var "a"
// CHECK:STDOUT: %.loc10_20: i32 = int_literal 1
// CHECK:STDOUT: %.loc10_23: i32 = int_literal 2
// CHECK:STDOUT: %.loc10_26: i32 = int_literal 3
// CHECK:STDOUT: %.loc10_27.1: type = tuple_type (i32, i32, i32)
// CHECK:STDOUT: %.loc10_27.2: (i32, i32, i32) = tuple_literal (%.loc10_20, %.loc10_23, %.loc10_26)
// CHECK:STDOUT: %.loc10_27.2: type = ptr_type (i32, i32, i32)
// CHECK:STDOUT: %.loc10_27.3: (i32, i32, i32) = tuple_literal (%.loc10_20, %.loc10_23, %.loc10_26)
// CHECK:STDOUT: assign %a, <error>
// CHECK:STDOUT: }
+15 -8
View File
@@ -28,19 +28,24 @@ var d: [i32; 3] = t2;
// CHECK:STDOUT: file "fail_type_mismatch.carbon" {
// CHECK:STDOUT: %.loc10_14: i32 = int_literal 3
// CHECK:STDOUT: %.loc10_15: type = array_type %.loc10_14, i32
// CHECK:STDOUT: %.loc10_15.1: type = array_type %.loc10_14, i32
// CHECK:STDOUT: %.loc10_15.2: type = ptr_type [i32; 3]
// CHECK:STDOUT: %a: ref [i32; 3] = var "a"
// CHECK:STDOUT: %.loc10_20: i32 = int_literal 1
// CHECK:STDOUT: %.1: type = ptr_type String
// CHECK:STDOUT: %.loc10_23: String = string_literal "Hello"
// CHECK:STDOUT: %.loc10_32: String = string_literal "World"
// CHECK:STDOUT: %.loc10_39.1: type = tuple_type (i32, String, String)
// CHECK:STDOUT: %.loc10_39.2: (i32, String, String) = tuple_literal (%.loc10_20, %.loc10_23, %.loc10_32)
// CHECK:STDOUT: %.loc10_39.3: i32 = int_literal 0
// CHECK:STDOUT: %.loc10_39.4: ref i32 = array_index %a, %.loc10_39.3
// CHECK:STDOUT: %.loc10_39.5: init i32 = initialize_from %.loc10_20 to %.loc10_39.4
// CHECK:STDOUT: %.loc10_39.2: type = tuple_type (i32, String*, String*)
// CHECK:STDOUT: %.loc10_39.3: type = ptr_type (i32, String*, String*)
// CHECK:STDOUT: %.loc10_39.4: (i32, String, String) = tuple_literal (%.loc10_20, %.loc10_23, %.loc10_32)
// CHECK:STDOUT: %.loc10_39.5: i32 = int_literal 0
// CHECK:STDOUT: %.loc10_39.6: ref i32 = array_index %a, %.loc10_39.5
// CHECK:STDOUT: %.loc10_39.7: init i32 = initialize_from %.loc10_20 to %.loc10_39.6
// CHECK:STDOUT: assign %a, <error>
// CHECK:STDOUT: %.loc12_29.1: type = tuple_type (type, type, type)
// CHECK:STDOUT: %.loc12_29.2: (type, type, type) = tuple_literal (i32, String, String)
// CHECK:STDOUT: %.loc12_29.2: type = ptr_type (type, type, type)
// CHECK:STDOUT: %.loc12_29.3: (type, type, type) = tuple_literal (i32, String, String)
// CHECK:STDOUT: %t1: ref (i32, String, String) = var "t1"
// CHECK:STDOUT: %.loc16_14: i32 = int_literal 3
// CHECK:STDOUT: %.loc16_15: type = array_type %.loc16_14, i32
@@ -59,10 +64,12 @@ var d: [i32; 3] = t2;
// CHECK:STDOUT: %.loc21_20: i32 = int_literal 1
// CHECK:STDOUT: %.loc21_23: i32 = int_literal 2
// CHECK:STDOUT: %.loc21_24.1: type = tuple_type (i32, i32)
// CHECK:STDOUT: %.loc21_24.2: (i32, i32) = tuple_literal (%.loc21_20, %.loc21_23)
// CHECK:STDOUT: %.loc21_24.2: type = ptr_type (i32, i32)
// CHECK:STDOUT: %.loc21_24.3: (i32, i32) = tuple_literal (%.loc21_20, %.loc21_23)
// CHECK:STDOUT: assign %c, <error>
// CHECK:STDOUT: %.loc23_18.1: type = tuple_type (type, type)
// CHECK:STDOUT: %.loc23_18.2: (type, type) = tuple_literal (i32, i32)
// CHECK:STDOUT: %.loc23_18.2: type = ptr_type (type, type)
// CHECK:STDOUT: %.loc23_18.3: (type, type) = tuple_literal (i32, i32)
// CHECK:STDOUT: %t2: ref (i32, i32) = var "t2"
// CHECK:STDOUT: %.loc27_14: i32 = int_literal 3
// CHECK:STDOUT: %.loc27_15: type = array_type %.loc27_14, i32
+16 -15
View File
@@ -34,22 +34,23 @@ fn G() -> i32 {
// CHECK:STDOUT: %.loc12_16: i32 = int_literal 2
// CHECK:STDOUT: %.loc12_19: i32 = int_literal 3
// CHECK:STDOUT: %.loc12_20.1: type = tuple_type (i32, i32, i32)
// CHECK:STDOUT: %.loc12_20.2: (i32, i32, i32) = tuple_literal (%.loc12_13, %.loc12_16, %.loc12_19)
// CHECK:STDOUT: %.loc12_20.2: type = ptr_type (i32, i32, i32)
// CHECK:STDOUT: %.loc12_20.3: (i32, i32, i32) = tuple_literal (%.loc12_13, %.loc12_16, %.loc12_19)
// CHECK:STDOUT: %.loc12_23: i32 = int_literal 1
// CHECK:STDOUT: %.loc12_20.3: ref [i32; 3] = temporary_storage
// CHECK:STDOUT: %.loc12_20.4: i32 = int_literal 0
// CHECK:STDOUT: %.loc12_20.5: ref i32 = array_index %.loc12_20.3, %.loc12_20.4
// CHECK:STDOUT: %.loc12_20.6: init i32 = initialize_from %.loc12_13 to %.loc12_20.5
// CHECK:STDOUT: %.loc12_20.7: i32 = int_literal 1
// CHECK:STDOUT: %.loc12_20.8: ref i32 = array_index %.loc12_20.3, %.loc12_20.7
// CHECK:STDOUT: %.loc12_20.9: init i32 = initialize_from %.loc12_16 to %.loc12_20.8
// CHECK:STDOUT: %.loc12_20.10: i32 = int_literal 2
// CHECK:STDOUT: %.loc12_20.11: ref i32 = array_index %.loc12_20.3, %.loc12_20.10
// CHECK:STDOUT: %.loc12_20.12: init i32 = initialize_from %.loc12_19 to %.loc12_20.11
// CHECK:STDOUT: %.loc12_20.13: init [i32; 3] = array_init %.loc12_20.2, (%.loc12_20.6, %.loc12_20.9, %.loc12_20.12) to %.loc12_20.3
// CHECK:STDOUT: %.loc12_20.14: ref [i32; 3] = temporary %.loc12_20.3, %.loc12_20.13
// CHECK:STDOUT: %.loc12_20.15: [i32; 3] = bind_value %.loc12_20.14
// CHECK:STDOUT: %.loc12_11.1: init i32 = call %F.ref(%.loc12_20.15, %.loc12_23)
// CHECK:STDOUT: %.loc12_20.4: ref [i32; 3] = temporary_storage
// CHECK:STDOUT: %.loc12_20.5: i32 = int_literal 0
// CHECK:STDOUT: %.loc12_20.6: ref i32 = array_index %.loc12_20.4, %.loc12_20.5
// CHECK:STDOUT: %.loc12_20.7: init i32 = initialize_from %.loc12_13 to %.loc12_20.6
// CHECK:STDOUT: %.loc12_20.8: i32 = int_literal 1
// CHECK:STDOUT: %.loc12_20.9: ref i32 = array_index %.loc12_20.4, %.loc12_20.8
// CHECK:STDOUT: %.loc12_20.10: init i32 = initialize_from %.loc12_16 to %.loc12_20.9
// CHECK:STDOUT: %.loc12_20.11: i32 = int_literal 2
// CHECK:STDOUT: %.loc12_20.12: ref i32 = array_index %.loc12_20.4, %.loc12_20.11
// CHECK:STDOUT: %.loc12_20.13: init i32 = initialize_from %.loc12_19 to %.loc12_20.12
// CHECK:STDOUT: %.loc12_20.14: init [i32; 3] = array_init %.loc12_20.3, (%.loc12_20.7, %.loc12_20.10, %.loc12_20.13) to %.loc12_20.4
// CHECK:STDOUT: %.loc12_20.15: ref [i32; 3] = temporary %.loc12_20.4, %.loc12_20.14
// CHECK:STDOUT: %.loc12_20.16: [i32; 3] = bind_value %.loc12_20.15
// CHECK:STDOUT: %.loc12_11.1: init i32 = call %F.ref(%.loc12_20.16, %.loc12_23)
// CHECK:STDOUT: %.loc12_11.2: ref i32 = temporary_storage
// CHECK:STDOUT: %.loc12_11.3: ref i32 = temporary %.loc12_11.2, %.loc12_11.1
// CHECK:STDOUT: %.loc12_11.4: i32 = bind_value %.loc12_11.3
+33 -31
View File
@@ -8,7 +8,8 @@ var a: [i32; 9] = (1, 2, 3, 4, 5, 6, 7, 8, 9);
// CHECK:STDOUT: file "nine_elements.carbon" {
// CHECK:STDOUT: %.loc7_14: i32 = int_literal 9
// CHECK:STDOUT: %.loc7_15: type = array_type %.loc7_14, i32
// CHECK:STDOUT: %.loc7_15.1: type = array_type %.loc7_14, i32
// CHECK:STDOUT: %.loc7_15.2: type = ptr_type [i32; 9]
// CHECK:STDOUT: %a: ref [i32; 9] = var "a"
// CHECK:STDOUT: %.loc7_20: i32 = int_literal 1
// CHECK:STDOUT: %.loc7_23: i32 = int_literal 2
@@ -20,34 +21,35 @@ var a: [i32; 9] = (1, 2, 3, 4, 5, 6, 7, 8, 9);
// CHECK:STDOUT: %.loc7_41: i32 = int_literal 8
// CHECK:STDOUT: %.loc7_44: i32 = int_literal 9
// CHECK:STDOUT: %.loc7_45.1: type = tuple_type (i32, i32, i32, i32, i32, i32, i32, i32, i32)
// CHECK:STDOUT: %.loc7_45.2: (i32, i32, i32, i32, i32, i32, i32, i32, i32) = tuple_literal (%.loc7_20, %.loc7_23, %.loc7_26, %.loc7_29, %.loc7_32, %.loc7_35, %.loc7_38, %.loc7_41, %.loc7_44)
// CHECK:STDOUT: %.loc7_45.3: i32 = int_literal 0
// CHECK:STDOUT: %.loc7_45.4: ref i32 = array_index %a, %.loc7_45.3
// CHECK:STDOUT: %.loc7_45.5: init i32 = initialize_from %.loc7_20 to %.loc7_45.4
// CHECK:STDOUT: %.loc7_45.6: i32 = int_literal 1
// CHECK:STDOUT: %.loc7_45.7: ref i32 = array_index %a, %.loc7_45.6
// CHECK:STDOUT: %.loc7_45.8: init i32 = initialize_from %.loc7_23 to %.loc7_45.7
// CHECK:STDOUT: %.loc7_45.9: i32 = int_literal 2
// CHECK:STDOUT: %.loc7_45.10: ref i32 = array_index %a, %.loc7_45.9
// CHECK:STDOUT: %.loc7_45.11: init i32 = initialize_from %.loc7_26 to %.loc7_45.10
// CHECK:STDOUT: %.loc7_45.12: i32 = int_literal 3
// CHECK:STDOUT: %.loc7_45.13: ref i32 = array_index %a, %.loc7_45.12
// CHECK:STDOUT: %.loc7_45.14: init i32 = initialize_from %.loc7_29 to %.loc7_45.13
// CHECK:STDOUT: %.loc7_45.15: i32 = int_literal 4
// CHECK:STDOUT: %.loc7_45.16: ref i32 = array_index %a, %.loc7_45.15
// CHECK:STDOUT: %.loc7_45.17: init i32 = initialize_from %.loc7_32 to %.loc7_45.16
// CHECK:STDOUT: %.loc7_45.18: i32 = int_literal 5
// CHECK:STDOUT: %.loc7_45.19: ref i32 = array_index %a, %.loc7_45.18
// CHECK:STDOUT: %.loc7_45.20: init i32 = initialize_from %.loc7_35 to %.loc7_45.19
// CHECK:STDOUT: %.loc7_45.21: i32 = int_literal 6
// CHECK:STDOUT: %.loc7_45.22: ref i32 = array_index %a, %.loc7_45.21
// CHECK:STDOUT: %.loc7_45.23: init i32 = initialize_from %.loc7_38 to %.loc7_45.22
// CHECK:STDOUT: %.loc7_45.24: i32 = int_literal 7
// CHECK:STDOUT: %.loc7_45.25: ref i32 = array_index %a, %.loc7_45.24
// CHECK:STDOUT: %.loc7_45.26: init i32 = initialize_from %.loc7_41 to %.loc7_45.25
// CHECK:STDOUT: %.loc7_45.27: i32 = int_literal 8
// CHECK:STDOUT: %.loc7_45.28: ref i32 = array_index %a, %.loc7_45.27
// CHECK:STDOUT: %.loc7_45.29: init i32 = initialize_from %.loc7_44 to %.loc7_45.28
// CHECK:STDOUT: %.loc7_45.30: init [i32; 9] = array_init %.loc7_45.2, (%.loc7_45.5, %.loc7_45.8, %.loc7_45.11, %.loc7_45.14, %.loc7_45.17, %.loc7_45.20, %.loc7_45.23, %.loc7_45.26, %.loc7_45.29) to %a
// CHECK:STDOUT: assign %a, %.loc7_45.30
// CHECK:STDOUT: %.loc7_45.2: type = ptr_type (i32, i32, i32, i32, i32, i32, i32, i32, i32)
// CHECK:STDOUT: %.loc7_45.3: (i32, i32, i32, i32, i32, i32, i32, i32, i32) = tuple_literal (%.loc7_20, %.loc7_23, %.loc7_26, %.loc7_29, %.loc7_32, %.loc7_35, %.loc7_38, %.loc7_41, %.loc7_44)
// CHECK:STDOUT: %.loc7_45.4: i32 = int_literal 0
// CHECK:STDOUT: %.loc7_45.5: ref i32 = array_index %a, %.loc7_45.4
// CHECK:STDOUT: %.loc7_45.6: init i32 = initialize_from %.loc7_20 to %.loc7_45.5
// CHECK:STDOUT: %.loc7_45.7: i32 = int_literal 1
// CHECK:STDOUT: %.loc7_45.8: ref i32 = array_index %a, %.loc7_45.7
// CHECK:STDOUT: %.loc7_45.9: init i32 = initialize_from %.loc7_23 to %.loc7_45.8
// CHECK:STDOUT: %.loc7_45.10: i32 = int_literal 2
// CHECK:STDOUT: %.loc7_45.11: ref i32 = array_index %a, %.loc7_45.10
// CHECK:STDOUT: %.loc7_45.12: init i32 = initialize_from %.loc7_26 to %.loc7_45.11
// CHECK:STDOUT: %.loc7_45.13: i32 = int_literal 3
// CHECK:STDOUT: %.loc7_45.14: ref i32 = array_index %a, %.loc7_45.13
// CHECK:STDOUT: %.loc7_45.15: init i32 = initialize_from %.loc7_29 to %.loc7_45.14
// CHECK:STDOUT: %.loc7_45.16: i32 = int_literal 4
// CHECK:STDOUT: %.loc7_45.17: ref i32 = array_index %a, %.loc7_45.16
// CHECK:STDOUT: %.loc7_45.18: init i32 = initialize_from %.loc7_32 to %.loc7_45.17
// CHECK:STDOUT: %.loc7_45.19: i32 = int_literal 5
// CHECK:STDOUT: %.loc7_45.20: ref i32 = array_index %a, %.loc7_45.19
// CHECK:STDOUT: %.loc7_45.21: init i32 = initialize_from %.loc7_35 to %.loc7_45.20
// CHECK:STDOUT: %.loc7_45.22: i32 = int_literal 6
// CHECK:STDOUT: %.loc7_45.23: ref i32 = array_index %a, %.loc7_45.22
// CHECK:STDOUT: %.loc7_45.24: init i32 = initialize_from %.loc7_38 to %.loc7_45.23
// CHECK:STDOUT: %.loc7_45.25: i32 = int_literal 7
// CHECK:STDOUT: %.loc7_45.26: ref i32 = array_index %a, %.loc7_45.25
// CHECK:STDOUT: %.loc7_45.27: init i32 = initialize_from %.loc7_41 to %.loc7_45.26
// CHECK:STDOUT: %.loc7_45.28: i32 = int_literal 8
// CHECK:STDOUT: %.loc7_45.29: ref i32 = array_index %a, %.loc7_45.28
// CHECK:STDOUT: %.loc7_45.30: init i32 = initialize_from %.loc7_44 to %.loc7_45.29
// CHECK:STDOUT: %.loc7_45.31: init [i32; 9] = array_init %.loc7_45.3, (%.loc7_45.6, %.loc7_45.9, %.loc7_45.12, %.loc7_45.15, %.loc7_45.18, %.loc7_45.21, %.loc7_45.24, %.loc7_45.27, %.loc7_45.30) to %a
// CHECK:STDOUT: assign %a, %.loc7_45.31
// CHECK:STDOUT: }