blob: d8bfb45b93570a446ebdcf27f96f0892197c903b [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all -enable-expand-all -sil-lower-agg-instrs-expand-all -lower-aggregate-instrs %s | %FileCheck %s
// This file makes sure that the mechanics of expanding aggregate instructions
// work. With that in mind, we expand all structs here ignoring code-size
// trade-offs.
sil_stage canonical
import Swift
import Builtin
class C1 {
var data : Builtin.Int64
init()
}
class C2 {
var data : Builtin.FPIEEE32
init()
}
class C3 {
var data : Builtin.FPIEEE64
init()
}
struct S2 {
var cls1 : C1
var cls2 : C2
var trivial : Builtin.FPIEEE32
}
struct S {
var trivial : Builtin.Int64
var cls : C3
var inner_struct : S2
}
enum E {
case NoElement(Void)
case TrivialElement(Builtin.Int64)
case ReferenceElement(C1)
case StructNonTrivialElt(S)
case TupleNonTrivialElt((Builtin.Int64, S, C3))
}
// A struct for testing that aggregate rebuilding works.
struct S3 {
var trivial1 : Builtin.Int64
var cls : S
var trivial2 : Builtin.Int64
var e : E
var trivial3 : Builtin.Int64
}
//////////////////
// Destroy Addr //
//////////////////
// CHECK-LABEL: sil [ossa] @expand_destroy_addr_trivial
// CHECK: bb0
// CHECK: tuple ()
// CHECK: return
sil [ossa] @expand_destroy_addr_trivial : $@convention(thin) (@in Builtin.Int64) -> () {
bb0(%0 : $*Builtin.Int64):
destroy_addr %0 : $*Builtin.Int64
%1 = tuple()
return %1 : $()
}
// CHECK-LABEL: sil [ossa] @expand_destroy_addr_aggstructnontrivial :
// CHECK: bb0([[INPTR:%[0-9]+]] : $*S):
// CHECK: [[IN:%[0-9]+]] = load [take] [[INPTR]] : $*S
// CHECK: ({{%.*}}, [[cls:%.*]], [[innerstruct:%.*]]) = destructure_struct [[IN]]
// CHECK: destroy_value [[cls]] : $C3
// CHECK: ([[innerstruct_cls1:%.*]], [[innerstruct_cls2:%.*]], {{%.*}}) = destructure_struct [[innerstruct]]
// CHECK: destroy_value [[innerstruct_cls1]] : $C1
// CHECK: destroy_value [[innerstruct_cls2]] : $C2
// CHECK: } // end sil function 'expand_destroy_addr_aggstructnontrivial'
sil [ossa] @expand_destroy_addr_aggstructnontrivial : $@convention(thin) (@in S) -> () {
bb0(%0 : $*S):
destroy_addr %0 : $*S
%1 = tuple()
return %1 : $()
}
// CHECK-LABEL: sil [ossa] @expand_destroy_addr_aggtuplenontrivial :
// CHECK: bb0([[INPTR:%[0-9]+]] : $*(S, S2, C1)):
// CHECK: [[IN:%[0-9]+]] = load [take] [[INPTR]] : $*(S, S2, C1)
// CHECK: ([[ELT0:%.*]], [[ELT1:%.*]], [[ELT2:%.*]]) = destructure_tuple [[IN]]
// CHECK: ({{%[0-9]+}}, [[ELT0cls:%[0-9]+]], [[ELT0innerstruct:%[0-9]+]]) = destructure_struct [[ELT0]]
// CHECK: destroy_value [[ELT0cls]]
// CHECK: ([[ELT0innerstructcls1:%[0-9]+]], [[ELT0innerstructcls2:%[0-9]+]], {{%[0-9]+}}) = destructure_struct [[ELT0innerstruct]]
// CHECK: destroy_value [[ELT0innerstructcls1]]
// CHECK: destroy_value [[ELT0innerstructcls2]]
// CHECK: ([[ELT1cls1:%[0-9]+]], [[ELT1cls2:%[0-9]+]], {{%.*}}) = destructure_struct [[ELT1]]
// CHECK: destroy_value [[ELT1cls1]] : $C1
// CHECK: destroy_value [[ELT1cls2]] : $C2
// CHECK: destroy_value [[ELT2]]
// CHECK: } // end sil function 'expand_destroy_addr_aggtuplenontrivial'
sil [ossa] @expand_destroy_addr_aggtuplenontrivial : $@convention(thin) (@in (S, S2, C1)) -> () {
bb0(%0 : $*(S, S2, C1)):
destroy_addr %0 : $*(S, S2, C1)
%1 = tuple()
return %1 : $()
}
// Do not do anything.
sil [ossa] @expand_destroy_addr_addressonly : $@convention(thin) <T> (@in T) -> () {
bb0(%0 : $*T):
destroy_addr %0 : $*T
%1 = tuple()
return %1 : $()
}
// CHECK-LABEL: sil [ossa] @expand_destroy_addr_reference :
// CHECK: bb0
// CHECK: load
// CHECK: destroy_value
// CHECK: tuple
// CHECK: } // end sil function 'expand_destroy_addr_reference'
sil [ossa] @expand_destroy_addr_reference : $@convention(thin) (@in C1) -> () {
bb0(%0 : $*C1):
destroy_addr %0 : $*C1
%1 = tuple()
return %1 : $()
}
// CHECK-LABEL: sil [ossa] @expand_destroy_addr_enum :
// CHECK: bb0
// CHECK: load
// CHECK: destroy_value
// CHECK: } // end sil function 'expand_destroy_addr_enum'
sil [ossa] @expand_destroy_addr_enum : $@convention(thin) (@in E) -> () {
bb0(%0 : $*E):
destroy_addr %0 : $*E
%1 = tuple()
return %1 : $()
}
///////////////
// Copy Addr //
///////////////
// CHECK-LABEL: sil [ossa] @expand_copy_addr_takeinit :
// CHECK: bb0([[OUT:%[0-9]+]] : $*S, [[IN:%[0-9]+]] : $*S):
// CHECK: [[LOAD:%[0-9]+]] = load [take] [[IN]]
// CHECK: store [[LOAD]] to [init] [[OUT]]
// CHECK: } // end sil function 'expand_copy_addr_takeinit'
sil [ossa] @expand_copy_addr_takeinit : $@convention(thin) (@in S) -> @out S {
bb0(%0 : $*S, %1 : $*S):
copy_addr [take] %1 to [initialization] %0 : $*S
%2 = tuple()
return %2 : $()
}
// CHECK-LABEL: sil [ossa] @expand_copy_addr_init :
// CHECK: bb0([[OUT:%[0-9]+]] : $*S, [[IN:%[0-9]+]] : $*S):
// CHECK: [[LOADED_IN:%[0-9]+]] = load [copy] [[IN]] : $*S
// CHECK: store [[LOADED_IN]] to [init] [[OUT]]
// CHECK: } // end sil function 'expand_copy_addr_init'
sil [ossa] @expand_copy_addr_init : $@convention(thin) (@in_guaranteed S) -> @out S {
bb0(%0 : $*S, %1 : $*S):
copy_addr %1 to [initialization] %0 : $*S
%2 = tuple()
return %2 : $()
}
// CHECK-LABEL: sil [ossa] @expand_copy_addr_take :
// CHECK: bb0([[IN_ARG:%[0-9]+]] : $*S, [[INOUT_ARG:%[0-9]+]] : $*S):
// CHECK: [[LOADED_IN_ARG:%[0-9]+]] = load [take] [[IN_ARG]]
// CHECK: store [[LOADED_IN_ARG]] to [assign] [[INOUT_ARG]]
// CHECK: } // end sil function 'expand_copy_addr_take'
sil [ossa] @expand_copy_addr_take : $@convention(thin) (@in S, @inout S) -> () {
bb0(%0 : $*S, %1 : $*S):
copy_addr [take] %0 to %1 : $*S
%2 = tuple()
return %2 : $()
}
// Test expansions for various types (these will become more
// interesting when I introduce the actual chopping work).
// CHECK-LABEL: sil [ossa] @expand_copy_addr_trivial :
// CHECK: bb0
// CHECK: load [trivial]
// CHECK: store
// CHECK: } // end sil function 'expand_copy_addr_trivial'
sil [ossa] @expand_copy_addr_trivial : $@convention(thin) (@inout Builtin.Int64, @inout Builtin.Int64) -> () {
bb0(%0 : $*Builtin.Int64, %1 : $*Builtin.Int64):
copy_addr %0 to %1 : $*Builtin.Int64
%2 = tuple()
return %2 : $()
}
// CHECK-LABEL: sil [ossa] @expand_copy_addr_aggstructnontrivial :
// CHECK: bb0([[INOUT_ARG1:%[0-9]+]] : $*S, [[INOUT_ARG2:%[0-9]+]] : $*S):
// CHECK: [[INOUT_ARG1_LOADED:%[0-9]+]] = load [copy] [[INOUT_ARG1]]
// CHECK: store [[INOUT_ARG1_LOADED]] to [assign] [[INOUT_ARG2]]
// CHECK: } // end sil function 'expand_copy_addr_aggstructnontrivial'
sil [ossa] @expand_copy_addr_aggstructnontrivial : $@convention(thin) (@inout S, @inout S) -> () {
bb0(%0 : $*S, %1 : $*S):
copy_addr %0 to %1 : $*S
%2 = tuple()
return %2 : $()
}
// CHECK-LABEL: sil [ossa] @expand_copy_addr_aggtuplenontrivial :
// CHECK: bb0([[INOUT_1:%[0-9]+]] : $*(S, S2, C1, E), [[INOUT_2:%[0-9]+]] : $*(S, S2, C1, E)):
// CHECK: [[INOUT_1_LOADED:%[0-9]+]] = load [copy] [[INOUT_1]] : $*(S, S2, C1, E)
// CHECK: store [[INOUT_1_LOADED]] to [assign] [[INOUT_2]] : $*(S, S2, C1, E)
// CHECK: tuple ()
// CHECK: return
sil [ossa] @expand_copy_addr_aggtuplenontrivial : $@convention(thin) (@inout (S, S2, C1, E), @inout (S, S2, C1, E)) -> () {
bb0(%0 : $*(S, S2, C1, E), %1 : $*(S, S2, C1, E)):
copy_addr %0 to %1 : $*(S, S2, C1, E)
%2 = tuple()
return %2 : $()
}
// Do not do anything.
//
// CHECK-LABEL: sil [ossa] @expand_copy_addr_addressonly : $@convention(thin) <T> (@in T, @inout T) -> () {
// CHECK: copy_addr
// CHECK: } // end sil function 'expand_copy_addr_addressonly'
sil [ossa] @expand_copy_addr_addressonly : $@convention(thin) <T> (@in T, @inout T) -> () {
bb0(%0 : $*T, %1 : $*T):
copy_addr [take] %0 to %1 : $*T
%9999 = tuple()
return %9999 : $()
}
// Just turn into a load + destroy_value.
// CHECK-LABEL: sil [ossa] @expand_copy_addr_reference :
// CHECK: bb0([[INOUT_1:%[0-9]+]] : $*C1, [[INOUT_2:%[0-9]+]] : $*C1):
// CHECK: [[LOAD1:%[0-9]+]] = load [copy] [[INOUT_1]] : $*C1
// CHECK: store [[LOAD1]] to [assign] [[INOUT_2]]
// CHECK: } // end sil function 'expand_copy_addr_reference'
sil [ossa] @expand_copy_addr_reference : $@convention(thin) (@inout C1, @inout C1) -> () {
bb0(%0 : $*C1, %1 : $*C1):
copy_addr %0 to %1 : $*C1
%2 = tuple()
return %2 : $()
}
// CHECK-LABEL: sil [ossa] @expand_copy_addr_enum :
// CHECK: bb0([[IN1:%[0-9]+]] : $*E, [[IN2:%[0-9]+]] : $*E):
// CHECK: [[LOAD1:%[0-9]+]] = load [copy] [[IN1]] : $*E
// CHECK: store [[LOAD1]] to [assign] [[IN2]]
// CHECK: } // end sil function 'expand_copy_addr_enum'
sil [ossa] @expand_copy_addr_enum : $@convention(thin) (@inout E, @inout E) -> () {
bb0(%0 : $*E, %1 : $*E):
copy_addr %0 to %1 : $*E
%2 = tuple()
return %2 : $()
}
///////////////////
// Destroy Value //
///////////////////
// CHECK-LABEL: sil [ossa] @expand_destroy_value_aggstructnontrivial :
// CHECK: bb0([[IN:%[0-9]+]] : @owned $S):
// CHECK: destroy_value [[IN]]
// CHECK: } // end sil function 'expand_destroy_value_aggstructnontrivial'
sil [ossa] @expand_destroy_value_aggstructnontrivial : $@convention(thin) (@owned S) -> () {
bb0(%0 : @owned $S):
destroy_value %0 : $S
%1 = tuple()
return %1 : $()
}
// CHECK-LABEL: sil [ossa] @expand_destroy_value_aggtuplenontrivial :
// CHECK: bb0([[IN:%[0-9]+]] : @owned $(S, S2, C1, E)):
// CHECK: destroy_value [[IN]]
// CHECK: } // end sil function 'expand_destroy_value_aggtuplenontrivial'
sil [ossa] @expand_destroy_value_aggtuplenontrivial : $@convention(thin) (@owned (S, S2, C1, E)) -> () {
bb0(%0 : @owned $(S, S2, C1, E)):
destroy_value %0 : $(S, S2, C1, E)
%1 = tuple()
return %1 : $()
}
// CHECK-LABEL: sil [ossa] @expand_destroy_value_reference :
// CHECK: bb0([[IN:%[0-9]+]] : @owned $C1):
// CHECK: destroy_value [[IN]]
// CHECK: } // end sil function 'expand_destroy_value_reference'
sil [ossa] @expand_destroy_value_reference : $@convention(thin) (@owned C1) -> () {
bb0(%0 : @owned $C1):
destroy_value %0 : $C1
%1 = tuple()
return %1 : $()
}
// CHECK-LABEL: sil [ossa] @expand_destroy_value_enum :
// CHECK: bb0([[IN1:%[0-9]+]] : @owned $E):
// CHECK: destroy_value
// CHECK: } // end sil function 'expand_destroy_value_enum'
sil [ossa] @expand_destroy_value_enum : $@convention(thin) (@owned E) -> () {
bb0(%0 : @owned $E):
destroy_value %0 : $E
%1 = tuple()
return %1 : $()
}
////////////////
// Copy Value //
////////////////
// CHECK-LABEL: sil [ossa] @expand_copy_value_aggstructnontrivial :
// CHECK: bb0([[IN:%[0-9]+]] : @guaranteed $S3):
// CHECK: [[COPY:%.*]] = copy_value [[IN]]
// CHECK: return [[COPY]] : $S3
// CHECK: } // end sil function 'expand_copy_value_aggstructnontrivial'
sil [ossa] @expand_copy_value_aggstructnontrivial : $@convention(thin) (@guaranteed S3) -> @owned S3 {
bb0(%0 : @guaranteed $S3):
%1 = copy_value %0 : $S3
return %1 : $S3
}
// CHECK-LABEL: sil [ossa] @expand_copy_value_aggtuplenontrivial :
// CHECK: bb0([[IN:%[0-9]+]] : @guaranteed $(S, Builtin.Int64, S2, C1, Builtin.Int64, E)):
// CHECK: [[OUT:%.*]] = copy_value [[IN]]
// CHECK: return [[OUT]]
// CHECK: } // end sil function 'expand_copy_value_aggtuplenontrivial'
sil [ossa] @expand_copy_value_aggtuplenontrivial : $@convention(thin) (@guaranteed (S, Builtin.Int64, S2, C1, Builtin.Int64, E)) -> @owned (S, Builtin.Int64, S2, C1, Builtin.Int64, E) {
bb0(%0 : @guaranteed $(S, Builtin.Int64, S2, C1, Builtin.Int64, E)):
%1 = copy_value %0 : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E)
return %1 : $(S, Builtin.Int64, S2, C1, Builtin.Int64, E)
}
// CHECK-LABEL: sil [ossa] @expand_copy_value_reference :
// CHECK: bb0([[IN:%[0-9]+]] : @guaranteed $C1):
// CHECK: [[OUT:%.*]] = copy_value [[IN]]
// CHECK: return [[OUT]]
// CHECK: } // end sil function 'expand_copy_value_reference'
sil [ossa] @expand_copy_value_reference : $@convention(thin) (@guaranteed C1) -> @owned C1 {
bb0(%0 : @guaranteed $C1):
%1 = copy_value %0 : $C1
return %1 : $C1
}
// CHECK-LABEL: sil [ossa] @expand_copy_value_enum :
// CHECK: bb0([[IN:%[0-9]+]] : @guaranteed $E):
// CHECK: [[OUT:%.*]] = copy_value [[IN]]
// CHECk: return [[OUT]]
// CHECK: } // end sil function 'expand_copy_value_enum'
sil [ossa] @expand_copy_value_enum : $@convention(thin) (@guaranteed E) -> @owned E {
bb0(%0 : @guaranteed $E):
%1 = copy_value %0 : $E
return %1 : $E
}