| // RUN: %target-sil-opt -enable-sil-verify-all -sroa %s | %FileCheck %s |
| |
| sil_stage canonical |
| |
| import Builtin |
| import Swift |
| |
| /////////////////////////////// |
| // Struct with Scalar Fields // |
| /////////////////////////////// |
| |
| struct S1 { |
| var x : Builtin.Int1 |
| var y : Builtin.Int32 |
| var z : Builtin.Int64 |
| } |
| |
| sil [ossa] @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| |
| // CHECK-LABEL: sil [ossa] @struct_with_scalar_fields : $@convention(thin) (S1) -> () |
| // CHECK: bb0([[VAR_0:%[0-9]+]] : $S1): |
| |
| // CHECK-NEXT: [[VAR_1:%[0-9]+]] = alloc_stack $Builtin.Int1 |
| // CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int32 |
| // CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int64 |
| // CHECK-NEXT: ([[VAR_4:%[0-9]+]], [[VAR_6:%[0-9]+]], [[VAR_8:%[0-9]+]]) = destructure_struct [[VAR_0]] |
| // CHECK-NEXT: store [[VAR_4]] to [trivial] [[VAR_1]] : $*Builtin.Int1 |
| // CHECK-NEXT: store [[VAR_6]] to [trivial] [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: store [[VAR_8]] to [trivial] [[VAR_3]] : $*Builtin.Int64 |
| |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_10:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_11:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_12:%[0-9]+]] = apply [[VAR_10]]([[VAR_11]]) : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_13:%[0-9]+]] = load [trivial] [[VAR_1]] : $*Builtin.Int1 |
| // CHECK-NEXT: [[VAR_14:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_15:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_16:%[0-9]+]] = struct $S1 ([[VAR_13]] : $Builtin.Int1, [[VAR_14]] : $Builtin.Int32, [[VAR_15]] : $Builtin.Int64) |
| |
| // CHECK: dealloc_stack [[VAR_3]] : $*Builtin.Int64 |
| // CHECK: dealloc_stack [[VAR_2]] : $*Builtin.Int32 |
| // CHECK: dealloc_stack [[VAR_1]] : $*Builtin.Int1 |
| |
| // CHECK: [[VAR_20:%[0-9]+]] = tuple () |
| // CHECK: return [[VAR_20]] : $() |
| sil [ossa] @struct_with_scalar_fields : $@convention(thin) (S1) -> () { |
| bb0(%0 : $S1): |
| %1 = alloc_stack $S1 |
| debug_value %1 : $*S1 // should not prevent the optimization |
| debug_value %1 : $*S1 // should not prevent the optimization |
| store %0 to [trivial] %1 : $*S1 |
| %2 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| %3 = struct_element_addr %1 : $*S1, #S1.y |
| %4 = load [trivial] %3 : $*Builtin.Int32 |
| apply %2(%4) : $@convention(thin) (Builtin.Int32) -> () |
| %5 = load [trivial] %1 : $*S1 |
| dealloc_stack %1 : $*S1 |
| %6 = tuple () |
| return %6 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @dont_sroa_without_benefit : $@convention(thin) (S1) -> S1 |
| // CHECK: bb0 |
| // CHECK-NEXT: alloc_stack $S1 |
| // CHECK-NEXT: store %0 to [trivial] %1 : $*S1 |
| // CHECK-NEXT: load [trivial] %1 : $*S1 |
| // CHECK-NEXT: dealloc_stack %1 : $*S1 |
| // CHECK-NEXT: return |
| sil [ossa] @dont_sroa_without_benefit : $@convention(thin) (S1) -> S1 { |
| bb0(%0 : $S1): |
| %1 = alloc_stack $S1 |
| store %0 to [trivial] %1 : $*S1 |
| %3 = load [trivial] %1 : $*S1 |
| dealloc_stack %1 : $*S1 |
| return %3 : $S1 |
| } |
| |
| |
| /////////////////////////////// |
| // Struct With Struct Fields // |
| /////////////////////////////// |
| |
| sil [ossa] @use_s1 : $@convention(thin) (S1) -> () |
| |
| struct S2 { |
| var alpha : Builtin.FPIEEE32 |
| var beta : S1 |
| } |
| |
| // CHECK-LABEL: sil [ossa] @struct_with_struct_fields : $@convention(thin) (S2, Builtin.Int64) -> () |
| // CHECK: bb0([[VAR_0:%[0-9]+]] : $S2, [[VAR_1:%[0-9]+]] : $Builtin.Int64): |
| |
| // CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.FPIEEE32 |
| // CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int1 |
| // CHECK-NEXT: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int32 |
| // CHECK-NEXT: [[VAR_5:%[0-9]+]] = alloc_stack $Builtin.Int64 |
| |
| // CHECK-NEXT: ([[VAR_6:%[0-9]+]], [[VAR_8:%[0-9]+]]) = destructure_struct [[VAR_0]] |
| // CHECK-NEXT: store [[VAR_6]] to [trivial] [[VAR_2]] : $*Builtin.FPIEEE32 |
| |
| // CHECK-NEXT: ([[VAR_9:%[0-9]+]], [[VAR_11:%[0-9]+]], [[VAR_13:%[0-9]+]]) = destructure_struct [[VAR_8]] |
| // CHECK-NEXT: store [[VAR_9]] to [trivial] [[VAR_3]] : $*Builtin.Int1 |
| // CHECK-NEXT: store [[VAR_11]] to [trivial] [[VAR_4]] : $*Builtin.Int32 |
| // CHECK-NEXT: store [[VAR_13]] to [trivial] [[VAR_5]] : $*Builtin.Int64 |
| |
| // CHECK-NEXT: [[VAR_15:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int1 |
| // CHECK-NEXT: [[VAR_16:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_17:%[0-9]+]] = load [trivial] [[VAR_5]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_18:%[0-9]+]] = struct $S1 ([[VAR_15]] : $Builtin.Int1, [[VAR_16]] : $Builtin.Int32, [[VAR_17]] : $Builtin.Int64) |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_19:%[0-9]+]] = function_ref @use_s1 : $@convention(thin) (S1) -> () |
| // CHECK-NEXT: [[VAR_20:%[0-9]+]] = apply [[VAR_19]]([[VAR_18]]) : $@convention(thin) (S1) -> () |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_21:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_22:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_23:%[0-9]+]] = apply [[VAR_21]]([[VAR_22]]) : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_24:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.FPIEEE32 |
| // CHECK-NEXT: [[VAR_25:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int1 |
| // CHECK-NEXT: [[VAR_26:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_27:%[0-9]+]] = load [trivial] [[VAR_5]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_28:%[0-9]+]] = struct $S1 ([[VAR_25]] : $Builtin.Int1, [[VAR_26]] : $Builtin.Int32, [[VAR_27]] : $Builtin.Int64) |
| // CHECK-NEXT: [[VAR_29:%[0-9]+]] = struct $S2 ([[VAR_24]] : $Builtin.FPIEEE32, [[VAR_28]] : $S1) |
| // CHECK-NEXT: store [[VAR_1]] to [trivial] [[VAR_5]] : $*Builtin.Int64 |
| // CHECK-NEXT: dealloc_stack [[VAR_5]] : $*Builtin.Int64 |
| // CHECK-NEXT: dealloc_stack [[VAR_4]] : $*Builtin.Int32 |
| // CHECK-NEXT: dealloc_stack [[VAR_3]] : $*Builtin.Int1 |
| // CHECK-NEXT: dealloc_stack [[VAR_2]] : $*Builtin.FPIEEE32 |
| // CHECK-NEXT: [[VAR_35:%[0-9]+]] = tuple () |
| // CHECK-NEXT: return [[VAR_35]] : $() |
| sil [ossa] @struct_with_struct_fields : $@convention(thin) (S2, Builtin.Int64) -> () { |
| bb0(%0 : $S2, %1 : $Builtin.Int64): |
| %2 = alloc_stack $S2 |
| store %0 to [trivial] %2 : $*S2 |
| %3 = struct_element_addr %2 : $*S2, #S2.beta |
| %4 = load [trivial] %3 : $*S1 |
| %5 = function_ref @use_s1 : $@convention(thin) (S1) -> () |
| apply %5(%4) : $@convention(thin) (S1) -> () |
| %6 = struct_element_addr %3 : $*S1, #S1.y |
| %7 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| %8 = load [trivial] %6 : $*Builtin.Int32 |
| apply %7(%8) : $@convention(thin) (Builtin.Int32) -> () |
| %9 = load [trivial] %2 : $*S2 |
| %10 = struct_element_addr %3 : $*S1, #S1.z |
| store %1 to [trivial] %10 : $*Builtin.Int64 |
| dealloc_stack %2 : $*S2 |
| %11 = tuple() |
| return %11 : $() |
| } |
| |
| ////////////////////////////// |
| // Struct with Tuple Fields // |
| ////////////////////////////// |
| |
| sil [ossa] @use_tup : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () |
| |
| struct S3 { |
| var gamma : (Builtin.Int32, Builtin.Int64, Builtin.Int16) |
| var delta : Builtin.FPIEEE32 |
| } |
| |
| // CHECK-LABEL: sil [ossa] @struct_with_tuple_fields : $@convention(thin) (S3, Builtin.Int64) -> () |
| // CHECK: bb0([[VAR_0:%[0-9]+]] : $S3, [[VAR_1:%[0-9]+]] : $Builtin.Int64): |
| // CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int32 |
| // CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int64 |
| // CHECK-NEXT: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int16 |
| // CHECK-NEXT: [[VAR_5:%[0-9]+]] = alloc_stack $Builtin.FPIEEE32 |
| // CHECK-NEXT: ([[VAR_6:%[0-9]+]], [[VAR_13:%[0-9]+]]) = destructure_struct [[VAR_0]] |
| // CHECK-NEXT: ([[VAR_7:%[0-9]+]], [[VAR_9:%[0-9]+]], [[VAR_11:%[0-9]+]]) = destructure_tuple [[VAR_6]] |
| // CHECK-NEXT: store [[VAR_7]] to [trivial] [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: store [[VAR_9]] to [trivial] [[VAR_3]] : $*Builtin.Int64 |
| // CHECK-NEXT: store [[VAR_11]] to [trivial] [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: store [[VAR_13]] to [trivial] [[VAR_5]] : $*Builtin.FPIEEE32 |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_15:%[0-9]+]] = function_ref @use_tup : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () |
| // CHECK-NEXT: [[VAR_16:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_17:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_18:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: [[VAR_19:%[0-9]+]] = tuple ([[VAR_16]] : $Builtin.Int32, [[VAR_17]] : $Builtin.Int64, [[VAR_18]] : $Builtin.Int16) |
| // CHECK-NEXT: [[VAR_20:%[0-9]+]] = apply [[VAR_15]]([[VAR_19]]) : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () |
| // CHECK-NEXT: [[VAR_21:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_22:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_23:%[0-9]+]] = apply [[VAR_22]]([[VAR_21]]) : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_24:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_25:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_26:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: [[VAR_27:%[0-9]+]] = tuple ([[VAR_24]] : $Builtin.Int32, [[VAR_25]] : $Builtin.Int64, [[VAR_26]] : $Builtin.Int16) |
| // CHECK-NEXT: [[VAR_28:%[0-9]+]] = load [trivial] [[VAR_5]] : $*Builtin.FPIEEE32 |
| // CHECK-NEXT: [[VAR_29:%[0-9]+]] = struct $S3 ([[VAR_27]] : $(Builtin.Int32, Builtin.Int64, Builtin.Int16), [[VAR_28]] : $Builtin.FPIEEE32) |
| // CHECK-NEXT: store [[VAR_1]] to [trivial] [[VAR_3]] : $*Builtin.Int64 |
| // CHECK-NEXT: dealloc_stack [[VAR_5]] : $*Builtin.FPIEEE32 |
| // CHECK-NEXT: dealloc_stack [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: dealloc_stack [[VAR_3]] : $*Builtin.Int64 |
| // CHECK-NEXT: dealloc_stack [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_35:%[0-9]+]] = tuple () |
| // CHECK-NEXT: return [[VAR_35]] : $() |
| sil [ossa] @struct_with_tuple_fields : $@convention(thin) (S3, Builtin.Int64) -> () { |
| bb0(%0 : $S3, %1 : $Builtin.Int64): |
| %2 = alloc_stack $S3 |
| store %0 to [trivial] %2 : $*S3 |
| %3 = function_ref @use_tup : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () |
| %4 = struct_element_addr %2 : $*S3, #S3.gamma |
| %5 = load [trivial] %4 : $*(Builtin.Int32, Builtin.Int64, Builtin.Int16) |
| apply %3(%5) : $@convention(thin) ((Builtin.Int32, Builtin.Int64, Builtin.Int16)) -> () |
| %6 = tuple_element_addr %4 : $*(Builtin.Int32, Builtin.Int64, Builtin.Int16), 0 |
| %7 = load [trivial] %6 : $*Builtin.Int32 |
| %8 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| apply %8(%7) : $@convention(thin) (Builtin.Int32) -> () |
| %9 = load [trivial] %2 : $*S3 |
| %10 = tuple_element_addr %4 : $*(Builtin.Int32, Builtin.Int64, Builtin.Int16), 1 |
| store %1 to [trivial] %10 : $*Builtin.Int64 |
| dealloc_stack %2 : $*S3 |
| %11 = tuple () |
| return %11 : $() |
| } |
| |
| ////////////////////////////// |
| // Tuple with Scalar Fields // |
| ////////////////////////////// |
| |
| // CHECK-LABEL: sil [ossa] @tuple_with_scalar_fields : $@convention(thin) ((Builtin.Int1, Builtin.Int32, Builtin.Int64)) -> () |
| // CHECK: bb0([[VAR_0:%[0-9]+]] : $(Builtin.Int1, Builtin.Int32, Builtin.Int64)): |
| // CHECK-NEXT: [[VAR_1:%[0-9]+]] = alloc_stack $Builtin.Int1 |
| // CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int32 |
| // CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int64 |
| // CHECK-NEXT: ([[VAR_4:%[0-9]+]], [[VAR_6:%[0-9]+]], [[VAR_8:%[0-9]+]]) = destructure_tuple [[VAR_0]] |
| // CHECK-NEXT: store [[VAR_4]] to [trivial] [[VAR_1]] : $*Builtin.Int1 |
| // CHECK-NEXT: store [[VAR_6]] to [trivial] [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: store [[VAR_8]] to [trivial] [[VAR_3]] : $*Builtin.Int64 |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_10:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_11:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_12:%[0-9]+]] = apply [[VAR_10]]([[VAR_11]]) : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_13:%[0-9]+]] = load [trivial] [[VAR_1]] : $*Builtin.Int1 |
| // CHECK-NEXT: [[VAR_14:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_15:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_16:%[0-9]+]] = tuple ([[VAR_13]] : $Builtin.Int1, [[VAR_14]] : $Builtin.Int32, [[VAR_15]] : $Builtin.Int64) |
| // CHECK-NEXT: dealloc_stack [[VAR_3]] : $*Builtin.Int64 |
| // CHECK-NEXT: dealloc_stack [[VAR_2]] : $*Builtin.Int32 |
| // CHECK-NEXT: dealloc_stack [[VAR_1]] : $*Builtin.Int1 |
| // CHECK-NEXT: [[VAR_20:%[0-9]+]] = tuple () |
| // CHECK-NEXT: return [[VAR_20]] : $() |
| sil [ossa] @tuple_with_scalar_fields : $@convention(thin) ((Builtin.Int1, Builtin.Int32, Builtin.Int64)) -> () { |
| bb0(%0 : $(Builtin.Int1, Builtin.Int32, Builtin.Int64)): |
| %1 = alloc_stack $(Builtin.Int1, Builtin.Int32, Builtin.Int64) |
| store %0 to [trivial] %1 : $*(Builtin.Int1, Builtin.Int32, Builtin.Int64) |
| %2 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| %3 = tuple_element_addr %1 : $*(Builtin.Int1, Builtin.Int32, Builtin.Int64), 1 |
| %4 = load [trivial] %3 : $*Builtin.Int32 |
| apply %2(%4) : $@convention(thin) (Builtin.Int32) -> () |
| %5 = load [trivial] %1 : $*(Builtin.Int1, Builtin.Int32, Builtin.Int64) |
| dealloc_stack %1 : $*(Builtin.Int1, Builtin.Int32, Builtin.Int64) |
| %6 = tuple() |
| return %6 : $() |
| } |
| |
| ////////////////////////////// |
| // Tuple With Struct Fields // |
| ////////////////////////////// |
| |
| struct S4 { |
| var aleph : Builtin.Int64 |
| var bet : Builtin.Int32 |
| } |
| |
| sil [ossa] @use_str4 : $@convention(thin) (S4) -> () |
| |
| // CHECK-LABEL: sil [ossa] @tuple_with_struct_fields : $@convention(thin) ((S4, Builtin.Int16), Builtin.Int16) -> () |
| // CHECK: bb0([[VAR_0:%[0-9]+]] : $(S4, Builtin.Int16), [[VAR_1:%[0-9]+]] : $Builtin.Int16): |
| // CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int64 |
| // CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int32 |
| // CHECK-NEXT: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int16 |
| // CHECK-NEXT: ([[VAR_5:%[0-9]+]], [[VAR_10:%[0-9]+]]) = destructure_tuple [[VAR_0]] |
| // CHECK-NEXT: ([[VAR_6:%[0-9]+]], [[VAR_8:%[0-9]+]]) = destructure_struct [[VAR_5]] |
| // CHECK-NEXT: store [[VAR_6]] to [trivial] [[VAR_2]] : $*Builtin.Int64 |
| // CHECK-NEXT: store [[VAR_8]] to [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: store [[VAR_10]] to [trivial] [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_12:%[0-9]+]] = function_ref @use_str4 : $@convention(thin) (S4) -> () |
| // CHECK-NEXT: [[VAR_13:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_14:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_15:%[0-9]+]] = struct $S4 ([[VAR_13]] : $Builtin.Int64, [[VAR_14]] : $Builtin.Int32) |
| // CHECK-NEXT: [[VAR_16:%[0-9]+]] = apply [[VAR_12]]([[VAR_15]]) : $@convention(thin) (S4) -> () |
| // CHECK-NEXT: [[VAR_17:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_18:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_19:%[0-9]+]] = apply [[VAR_18]]([[VAR_17]]) : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_20:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_21:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_22:%[0-9]+]] = struct $S4 ([[VAR_20]] : $Builtin.Int64, [[VAR_21]] : $Builtin.Int32) |
| // CHECK-NEXT: [[VAR_23:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: [[VAR_24:%[0-9]+]] = tuple ([[VAR_22]] : $S4, [[VAR_23]] : $Builtin.Int16) |
| // CHECK-NEXT: store [[VAR_1]] to [trivial] [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: dealloc_stack [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: dealloc_stack [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: dealloc_stack [[VAR_2]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_29:%[0-9]+]] = tuple () |
| // CHECK-NEXT: return [[VAR_29]] : $() |
| sil [ossa] @tuple_with_struct_fields : $@convention(thin) ((S4, Builtin.Int16), Builtin.Int16) -> () { |
| bb0(%0 : $(S4, Builtin.Int16), %1 : $Builtin.Int16): |
| %2 = alloc_stack $(S4, Builtin.Int16) |
| store %0 to [trivial] %2 : $*(S4, Builtin.Int16) |
| %3 = function_ref @use_str4 : $@convention(thin) (S4) -> () |
| %4 = tuple_element_addr %2 : $*(S4, Builtin.Int16), 0 |
| %5 = load [trivial] %4 : $*S4 |
| apply %3(%5) : $@convention(thin) (S4) -> () |
| %6 = struct_element_addr %4 : $*S4, #S4.bet |
| %7 = load [trivial] %6 : $*Builtin.Int32 |
| %8 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| apply %8(%7) : $@convention(thin) (Builtin.Int32) -> () |
| %9 = load [trivial] %2 : $*(S4, Builtin.Int16) |
| %10 = tuple_element_addr %2 : $*(S4, Builtin.Int16), 1 |
| store %1 to [trivial] %10 : $*Builtin.Int16 |
| dealloc_stack %2 : $*(S4, Builtin.Int16) |
| %11 = tuple() |
| return %11 : $() |
| } |
| |
| ///////////////////////////////// |
| // Tuple with Tuple Field Test // |
| ///////////////////////////////// |
| |
| sil [ossa] @use_tup2 : $@convention(thin) ((Builtin.Int64, Builtin.Int32)) -> () |
| sil [ossa] @use_int16 : $@convention(thin) (Builtin.Int16) -> () |
| |
| // CHECK-LABEL: sil [ossa] @tuple_with_tuple_fields : $@convention(thin) (((Builtin.Int64, Builtin.Int32), Builtin.Int16), Builtin.Int16) -> () |
| // CHECK: bb0([[VAR_0:%[0-9]+]] : $((Builtin.Int64, Builtin.Int32), Builtin.Int16), [[VAR_1:%[0-9]+]] : $Builtin.Int16): |
| // CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Builtin.Int64 |
| // CHECK-NEXT: [[VAR_3:%[0-9]+]] = alloc_stack $Builtin.Int32 |
| // CHECK-NEXT: [[VAR_4:%[0-9]+]] = alloc_stack $Builtin.Int16 |
| // CHECK-NEXT: ([[VAR_5:%[0-9]+]], [[VAR_10:%[0-9]+]]) = destructure_tuple [[VAR_0]] |
| // CHECK-NEXT: ([[VAR_6:%[0-9]+]], [[VAR_8:%[0-9]+]]) = destructure_tuple [[VAR_5]] |
| // CHECK-NEXT: store [[VAR_6]] to [trivial] [[VAR_2]] : $*Builtin.Int64 |
| // CHECK-NEXT: store [[VAR_8]] to [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: store [[VAR_10]] to [trivial] [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: [[VAR_12:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_13:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_14:%[0-9]+]] = tuple ([[VAR_12]] : $Builtin.Int64, [[VAR_13]] : $Builtin.Int32) |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_15:%[0-9]+]] = function_ref @use_tup2 : $@convention(thin) ((Builtin.Int64, Builtin.Int32)) -> () |
| // CHECK-NEXT: [[VAR_16:%[0-9]+]] = apply [[VAR_15]]([[VAR_14]]) : $@convention(thin) ((Builtin.Int64, Builtin.Int32)) -> () |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_17:%[0-9]+]] = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_18:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_19:%[0-9]+]] = apply [[VAR_17]]([[VAR_18]]) : $@convention(thin) (Builtin.Int32) -> () |
| // CHECK-NEXT: [[VAR_20:%[0-9]+]] = load [trivial] [[VAR_2]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_21:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: [[VAR_22:%[0-9]+]] = tuple ([[VAR_20]] : $Builtin.Int64, [[VAR_21]] : $Builtin.Int32) |
| // CHECK-NEXT: [[VAR_23:%[0-9]+]] = load [trivial] [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: [[VAR_24:%[0-9]+]] = tuple ([[VAR_22]] : $(Builtin.Int64, Builtin.Int32), [[VAR_23]] : $Builtin.Int16) |
| // CHECK-NEXT: store [[VAR_1]] to [trivial] [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: dealloc_stack [[VAR_4]] : $*Builtin.Int16 |
| // CHECK-NEXT: dealloc_stack [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: dealloc_stack [[VAR_2]] : $*Builtin.Int64 |
| // CHECK-NEXT: [[VAR_29:%[0-9]+]] = tuple () |
| // CHECK-NEXT: return [[VAR_29]] : $() |
| sil [ossa] @tuple_with_tuple_fields : $@convention(thin) (((Builtin.Int64, Builtin.Int32), Builtin.Int16), Builtin.Int16) -> () { |
| bb0(%0 : $((Builtin.Int64, Builtin.Int32), Builtin.Int16), %1 : $Builtin.Int16): |
| %2 = alloc_stack $((Builtin.Int64, Builtin.Int32), Builtin.Int16) |
| store %0 to [trivial] %2 : $*((Builtin.Int64, Builtin.Int32), Builtin.Int16) |
| %3 = tuple_element_addr %2 : $*((Builtin.Int64, Builtin.Int32), Builtin.Int16), 0 |
| %4 = load [trivial] %3 : $*(Builtin.Int64, Builtin.Int32) |
| %5 = function_ref @use_tup2 : $@convention(thin) ((Builtin.Int64, Builtin.Int32)) -> () |
| apply %5(%4) : $@convention(thin) ((Builtin.Int64, Builtin.Int32)) -> () |
| %6 = tuple_element_addr %3 : $*(Builtin.Int64, Builtin.Int32), 1 |
| %7 = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> () |
| %8 = load [trivial] %6 : $*Builtin.Int32 |
| apply %7(%8) : $@convention(thin) (Builtin.Int32) -> () |
| %9 = load [trivial] %2 : $*((Builtin.Int64, Builtin.Int32), Builtin.Int16) |
| %10 = tuple_element_addr %2 : $*((Builtin.Int64, Builtin.Int32), Builtin.Int16), 1 |
| store %1 to [trivial] %10 : $*Builtin.Int16 |
| dealloc_stack %2 : $*((Builtin.Int64, Builtin.Int32), Builtin.Int16) |
| %11 = tuple() |
| return %11 : $() |
| } |
| |
| ///////////////////////// |
| // Capture Struct Test // |
| ///////////////////////// |
| |
| struct CapturedS { |
| var x : Builtin.Int32 |
| } |
| |
| sil [ossa] @use_capturedstruct : $@convention(thin) (@inout CapturedS) -> () |
| |
| // CHECK-LABEL: sil [ossa] @captured_struct : $@convention(thin) (CapturedS) -> () |
| // CHECK: bb0([[VAR_0:%[0-9]+]] : $CapturedS): |
| // CHECK-NEXT: [[VAR_1:%[0-9]+]] = alloc_stack $CapturedS |
| // CHECK-NEXT: store [[VAR_0]] to [trivial] [[VAR_1]] : $*CapturedS |
| // CHECK-NEXT: [[VAR_3:%[0-9]+]] = struct_element_addr [[VAR_1]] : $*CapturedS, #CapturedS.x |
| // CHECK-NEXT: [[VAR_4:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_5:%[0-9]+]] = function_ref @use_capturedstruct : $@convention(thin) (@inout CapturedS) -> () |
| // CHECK-NEXT: [[VAR_6:%[0-9]+]] = apply [[VAR_5]]([[VAR_1]]) : $@convention(thin) (@inout CapturedS) -> () |
| // CHECK-NEXT: [[VAR_7:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: dealloc_stack [[VAR_1]] : $*CapturedS |
| // CHECK-NEXT: [[VAR_9:%[0-9]+]] = tuple () |
| // CHECK-NEXT: return [[VAR_9]] : $() |
| sil [ossa] @captured_struct : $@convention(thin) (CapturedS) -> () { |
| bb0(%0 : $CapturedS): |
| %1 = alloc_stack $CapturedS |
| store %0 to [trivial] %1 : $*CapturedS |
| %3 = struct_element_addr %1 : $*CapturedS, #CapturedS.x |
| %4 = load [trivial] %3 : $*Builtin.Int32 |
| %5 = function_ref @use_capturedstruct : $@convention(thin) (@inout CapturedS) -> () |
| %6 = apply %5(%1) : $@convention(thin) (@inout CapturedS) -> () |
| %7 = load [trivial] %3 : $*Builtin.Int32 |
| dealloc_stack %1 : $*CapturedS |
| %9 = tuple () |
| return %9 : $() |
| } |
| |
| ///////////////////////// |
| // Captured Tuple Test // |
| ///////////////////////// |
| |
| sil [ossa] @use_capturedtuple : $@convention(thin) (@inout (Builtin.Int32, Builtin.Int64)) -> () |
| |
| // CHECK-LABEL: sil [ossa] @captured_tuple : $@convention(thin) ((Builtin.Int32, Builtin.Int64)) -> () |
| // CHECK: bb0([[VAR_0:%[0-9]+]] : $(Builtin.Int32, Builtin.Int64)): |
| // CHECK-NEXT: [[VAR_1:%[0-9]+]] = alloc_stack $(Builtin.Int32, Builtin.Int64) |
| // CHECK-NEXT: store [[VAR_0]] to [trivial] [[VAR_1]] : $*(Builtin.Int32, Builtin.Int64) |
| // CHECK-NEXT: [[VAR_3:%[0-9]+]] = tuple_element_addr [[VAR_1]] : $*(Builtin.Int32, Builtin.Int64), 0 |
| // CHECK-NEXT: [[VAR_4:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_5:%[0-9]+]] = function_ref @use_capturedtuple : $@convention(thin) (@inout (Builtin.Int32, Builtin.Int64)) -> () |
| // CHECK-NEXT: [[VAR_6:%[0-9]+]] = apply [[VAR_5]]([[VAR_1]]) : $@convention(thin) (@inout (Builtin.Int32, Builtin.Int64)) -> () |
| // CHECK-NEXT: [[VAR_7:%[0-9]+]] = load [trivial] [[VAR_3]] : $*Builtin.Int32 |
| // CHECK-NEXT: dealloc_stack [[VAR_1]] : $*(Builtin.Int32, Builtin.Int64) |
| // CHECK-NEXT: [[VAR_9:%[0-9]+]] = tuple () |
| // CHECK-NEXT: return [[VAR_9]] : $() |
| sil [ossa] @captured_tuple : $@convention(thin) ((Builtin.Int32, Builtin.Int64)) -> () { |
| bb0(%0 : $(Builtin.Int32, Builtin.Int64)): |
| %1 = alloc_stack $(Builtin.Int32, Builtin.Int64) |
| store %0 to [trivial] %1 : $*(Builtin.Int32, Builtin.Int64) |
| %3 = tuple_element_addr %1 : $*(Builtin.Int32, Builtin.Int64), 0 |
| %4 = load [trivial] %3 : $*Builtin.Int32 |
| %5 = function_ref @use_capturedtuple : $@convention(thin) (@inout (Builtin.Int32, Builtin.Int64)) -> () |
| %6 = apply %5(%1) : $@convention(thin) (@inout (Builtin.Int32, Builtin.Int64)) -> () |
| %7 = load [trivial] %3 : $*Builtin.Int32 |
| dealloc_stack %1 : $*(Builtin.Int32, Builtin.Int64) |
| %9 = tuple () |
| return %9 : $() |
| } |
| |
| /////////////////////// |
| // Non-trivial Tests // |
| /////////////////////// |
| |
| class Obj { } |
| |
| struct NotTrivial { |
| var x : Obj |
| var y : Obj |
| } |
| |
| sil [ossa] @use_obj : $@convention(thin) (@owned Obj) -> () |
| |
| // CHECK-LABEL: sil [ossa] @struct_with_obj_fields : $@convention(thin) (@owned NotTrivial) -> () |
| // CHECK: bb0([[VAR_0:%[0-9]+]] : @owned $NotTrivial): |
| |
| // CHECK-NEXT: [[VAR_1:%[0-9]+]] = alloc_stack $Obj |
| // CHECK-NEXT: [[VAR_2:%[0-9]+]] = alloc_stack $Obj |
| // CHECK-NEXT: ([[VAR_4:%[0-9]+]], [[VAR_6:%[0-9]+]]) = destructure_struct [[VAR_0]] |
| // CHECK-NEXT: store [[VAR_4]] to [init] [[VAR_1]] : $*Obj |
| // CHECK-NEXT: store [[VAR_6]] to [init] [[VAR_2]] : $*Obj |
| |
| // CHECK-NEXT: function_ref |
| // CHECK-NEXT: [[VAR_10:%[0-9]+]] = function_ref @use_obj : $@convention(thin) (@owned Obj) -> () |
| // Make sure we use [copy] here ▼▼▼▼▼▼ |
| // CHECK-NEXT: [[VAR_11:%[0-9]+]] = load [copy] [[VAR_2]] : $*Obj |
| // CHECK-NEXT: [[VAR_12:%[0-9]+]] = apply [[VAR_10]]([[VAR_11]]) : $@convention(thin) (@owned Obj) -> () |
| // CHECK-NEXT: [[VAR_13:%[0-9]+]] = load [take] [[VAR_1]] : $*Obj |
| // CHECK-NEXT: [[VAR_14:%[0-9]+]] = load [take] [[VAR_2]] : $*Obj |
| // CHECK-NEXT: [[VAR_16:%[0-9]+]] = struct $NotTrivial ([[VAR_13]] : $Obj, [[VAR_14]] : $Obj) |
| |
| // CHECK: dealloc_stack [[VAR_2]] : $*Obj |
| // CHECK: dealloc_stack [[VAR_1]] : $*Obj |
| |
| // CHECK: [[VAR_20:%[0-9]+]] = tuple () |
| // CHECK: return [[VAR_20]] : $() |
| sil [ossa] @struct_with_obj_fields : $@convention(thin) (@owned NotTrivial) -> () { |
| bb0(%0 : @owned $NotTrivial): |
| %1 = alloc_stack $NotTrivial |
| debug_value %1 : $*NotTrivial // should not prevent the optimization |
| store %0 to [init] %1 : $*NotTrivial |
| %2 = function_ref @use_obj : $@convention(thin) (@owned Obj) -> () |
| %3 = struct_element_addr %1 : $*NotTrivial, #NotTrivial.y |
| // Make sure that SROA respects the [copy] qual. |
| %4 = load [copy] %3 : $*Obj |
| apply %2(%4) : $@convention(thin) (@owned Obj) -> () |
| %5 = load [take] %1 : $*NotTrivial |
| destroy_value %5 : $NotTrivial |
| dealloc_stack %1 : $*NotTrivial |
| %6 = tuple () |
| return %6 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @struct_with_obj_fields_multiple_stores : |
| // CHECK: bb0([[ARG_0:%[0-9]+]] : @owned $NotTrivial, [[ARG_1:%[0-9]+]] : @owned $NotTrivial): |
| // CHECK: [[VAR_1:%[0-9]+]] = alloc_stack $Obj |
| // CHECK: [[VAR_2:%[0-9]+]] = alloc_stack $Obj |
| // CHECK: ([[VAR_4:%[0-9]+]], [[VAR_6:%[0-9]+]]) = destructure_struct [[ARG_0]] |
| // CHECK: store [[VAR_4]] to [init] [[VAR_1]] : $*Obj |
| // CHECK: store [[VAR_6]] to [init] [[VAR_2]] : $*Obj |
| // CHECK: ([[VAR_4a:%[0-9]+]], [[VAR_6a:%[0-9]+]]) = destructure_struct [[ARG_1]] |
| // Make sure we use [assign] here |
| // CHECK: store [[VAR_4a]] to [assign] [[VAR_1]] : $*Obj |
| // CHECK: store [[VAR_6a]] to [assign] [[VAR_2]] : $*Obj |
| // CHECK-LABEL: } // end sil function 'struct_with_obj_fields_multiple_stores' |
| sil [ossa] @struct_with_obj_fields_multiple_stores : $@convention(thin) (@owned NotTrivial, @owned NotTrivial) -> () { |
| bb0(%0 : @owned $NotTrivial, %1 : @owned $NotTrivial): |
| %stk = alloc_stack $NotTrivial |
| store %0 to [init] %stk : $*NotTrivial |
| %3 = struct_element_addr %stk : $*NotTrivial, #NotTrivial.y |
| %4 = load [copy] %3 : $*Obj |
| %2 = function_ref @use_obj : $@convention(thin) (@owned Obj) -> () |
| apply %2(%4) : $@convention(thin) (@owned Obj) -> () |
| store %1 to [assign] %stk : $*NotTrivial |
| %4a = load [copy] %3 : $*Obj |
| apply %2(%4a) : $@convention(thin) (@owned Obj) -> () |
| %5 = load [take] %stk : $*NotTrivial |
| destroy_value %5 : $NotTrivial |
| dealloc_stack %stk : $*NotTrivial |
| %6 = tuple () |
| return %6 : $() |
| } |