Files
swift-mirror/test/SILOptimizer/loweraggregateinstrs.sil
Michael Gottesman ba46bc44d2 [lower-agg-instrs] Update for ossa.
For now I am trying out /not/ expanding when ownership is enabled. I still fixed
the problems in it though. I also put in a force expand everything pass to make
sure that in ossa we can still successfully go down this code path if we want
to.

The reason why I think this is the right thing to do is that the original reason
why lower aggregate instrs was written was to help the low level arc optimizer
(which only runs on non-ossa code). To the high level arc optimizer this is just
noise and will keep the IR simpler.

Another thing to note is that I updated the code so it should work in both ossa
and non-ossa. In order to not perturb the code too much, I had to add a small
optimization to TypeLowering where when ownership is disabled, we do not reform
aggregates when copying. Instead, we just return the passed in value. This makes
the pass the same when optimizing in both modes.
2020-08-03 10:42:34 -07:00

128 lines
4.3 KiB
Plaintext

// RUN: %target-sil-opt -enable-sil-verify-all %s -lower-aggregate-instrs | %FileCheck %s
// This file makes sure that given the current code-size metric we properly
// expand operations for small structs and not for large structs in a consistent
// way for all operations we expand.
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
case TrivialElement(Builtin.Int64)
case ReferenceElement(C1)
case StructNonTrivialElt(S)
case TupleNonTrivialElt((Builtin.Int64, S, C3))
}
// This struct is larger than our current code-size limit (> 6 leaf nodes).
struct LargeStruct {
var trivial1 : Builtin.Int64
var cls : S
var trivial2 : Builtin.Int64
var trivial3 : Builtin.Int64
}
///////////
// Tests //
///////////
// This test makes sure that we /do not/ expand retain_value, release_value and
// promote copy_addr/destroy_value to non-expanded retain_value, release_value.
// CHECK-LABEL: sil @large_struct_test : $@convention(thin) (@owned LargeStruct, @in LargeStruct) -> () {
// CHECK: bb0([[ARG0:%.*]] : $LargeStruct, [[ARG1:%.*]] : $*LargeStruct):
// CHECK: retain_value [[ARG0]]
// CHECK: release_value [[ARG0]]
// CHECK: [[ALLOC_STACK:%.*]] = alloc_stack $LargeStruct
// CHECK: [[LOADED_ARG1:%.*]] = load [[ARG1]]
// CHECK: retain_value [[LOADED_ARG1]]
// CHECK: [[LOADED_OLD_VAL:%.*]] = load [[ALLOC_STACK]]
// CHECK: release_value [[LOADED_OLD_VAL]]
// CHECK: store [[LOADED_ARG1]] to [[ALLOC_STACK]]
// CHECK: [[LOADED_ARG1:%.*]] = load [[ARG1]]
// CHECK: release_value [[LOADED_ARG1]]
// CHECK: dealloc_stack [[ALLOC_STACK]]
// CHECK: } // end sil function 'large_struct_test'
sil @large_struct_test : $@convention(thin) (@owned LargeStruct, @in LargeStruct) -> () {
bb0(%0 : $LargeStruct, %1 : $*LargeStruct):
retain_value %0 : $LargeStruct
release_value %0 : $LargeStruct
%2 = alloc_stack $LargeStruct
copy_addr %1 to %2 : $*LargeStruct
destroy_addr %1 : $*LargeStruct
dealloc_stack %2 : $*LargeStruct
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @small_struct_test : $@convention(thin) (@owned S2, @in S2) -> () {
// CHECK: bb0([[ARG0:%.*]] : $S2, [[ARG1:%.*]] : $*S2):
// CHECK: [[ARG0cls1:%.*]] = struct_extract [[ARG0]] : $S2, #S2.cls1
// CHECK: strong_retain [[ARG0cls1]] : $C1
// CHECK: [[ARG0cls2:%.*]] = struct_extract [[ARG0]] : $S2, #S2.cls2
// CHECK: strong_retain [[ARG0cls2]] : $C2
// CHECK: [[ARG0cls1:%.*]] = struct_extract [[ARG0]] : $S2, #S2.cls1
// CHECK: strong_release [[ARG0cls1]] : $C1
// CHECK: [[ARG0cls2:%.*]] = struct_extract [[ARG0]] : $S2, #S2.cls2
// CHECK: strong_release [[ARG0cls2]] : $C2
//
// CHECK: [[ALLOC_STACK:%.*]] = alloc_stack $S2
// CHECK: [[LOADED_ARG1:%.*]] = load [[ARG1]]
// CHECK: [[LOADED_ARG1cls1:%.*]] = struct_extract [[LOADED_ARG1]] : $S2, #S2.cls1
// CHECK: strong_retain [[LOADED_ARG1cls1]] : $C1
// CHECK: [[LOADED_ARG1cls2:%.*]] = struct_extract [[LOADED_ARG1]] : $S2, #S2.cls2
// CHECK: strong_retain [[LOADED_ARG1cls2]] : $C2
// CHECK: [[LOADED_OLDVALUE:%.*]] = load [[ALLOC_STACK]]
// CHECK: [[LOADED_OLDVALUEcls1:%.*]] = struct_extract [[LOADED_OLDVALUE]] : $S2, #S2.cls1
// CHECK: strong_release [[LOADED_OLDVALUEcls1]] : $C1
// CHECK: [[LOADED_OLDVALUEcls2:%.*]] = struct_extract [[LOADED_OLDVALUE]] : $S2, #S2.cls2
// CHECK: strong_release [[LOADED_OLDVALUEcls2]] : $C2
//
// CHECK: [[LOADED_ARG1:%.*]] = load [[ARG1]]
// CHECK: [[LOADED_ARG1cls1:%.*]] = struct_extract [[LOADED_ARG1]] : $S2, #S2.cls1
// CHECK: strong_release [[LOADED_ARG1cls1]] : $C1
// CHECK: [[LOADED_ARG1cls2:%.*]] = struct_extract [[LOADED_ARG1]] : $S2, #S2.cls2
// CHECK: strong_release [[LOADED_ARG1cls2]] : $C2
// CHECK: } // end sil function 'small_struct_test'
sil @small_struct_test : $@convention(thin) (@owned S2, @in S2) -> () {
bb0(%0 : $S2, %1 : $*S2):
retain_value %0 : $S2
release_value %0 : $S2
%2 = alloc_stack $S2
copy_addr %1 to %2 : $*S2
destroy_addr %1 : $*S2
dealloc_stack %2 : $*S2
%9999 = tuple()
return %9999 : $()
}