1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
// RUN: %target-swift-frontend -primary-file %s -O -sil-verify-all -module-name=test -emit-sil | %FileCheck %s
// Also do an end-to-end test to check if the generated code is correct.
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -O -module-name=test %s -o %t/a.out
// RUN: %target-codesign %t/a.out
// RUN: %target-run %t/a.out | %FileCheck %s -check-prefix=CHECK-OUTPUT
// REQUIRES: executable_test
var g = 0
final class Myclass {
lazy var lvar: Int = {
print("lvar init")
return g
}()
}
struct Mystruct {
lazy var lvar: Int = {
print("lvar init")
return g
}()
}
// CHECK-LABEL: sil {{.*}} @$s4test0A7_simpleySiAA7MyclassCF
// CHECK: [[GETTER:%[0-9]+]] = function_ref @$s4test7MyclassC4lvarSivg
// CHECK: [[V1:%[0-9]+]] = apply [[GETTER]](%0)
// CHECK: [[V2OPT:%[0-9]+]] = load
// CHECK: [[V2:%[0-9]+]] = unchecked_enum_data [[V2OPT]]
// CHECK: [[V1VAL:%[0-9]+]] = struct_extract [[V1]]
// CHECK: [[V2VAL:%[0-9]+]] = struct_extract [[V2]]
// CHECK: builtin "sadd{{.*}}"([[V1VAL]] {{.*}}, [[V2VAL]]
// CHECK: } // end sil function '$s4test0A7_simpleySiAA7MyclassCF'
@inline(never)
func test_simple(_ c: Myclass) -> Int {
g = 27
let v1 = c.lvar
let v2 = c.lvar
return v1 &+ v2
}
// CHECK-LABEL: sil {{.*}} @$s4test0A4_cfgySiAA7MyclassC_SbtF
// CHECK: [[GETTER:%[0-9]+]] = function_ref @$s4test7MyclassC4lvarSivg
// CHECK: [[V1:%[0-9]+]] = apply [[GETTER]](%0)
// CHECK: bb1:
// CHECK: [[V2OPT:%[0-9]+]] = load
// CHECK: [[V2:%[0-9]+]] = unchecked_enum_data [[V2OPT]]
// CHECK: [[V2VAL:%[0-9]+]] = struct_extract [[V2]]
// CHECK: br bb3([[V2VAL]]
// CHECK: bb2:
// CHECK: bb3([[V2PHI:%[0-9]+]] {{.*}}):
// CHECK: [[V1VAL:%[0-9]+]] = struct_extract [[V1]]
// CHECK: builtin "sadd{{.*}}"([[V1VAL]] {{.*}}, [[V2PHI]]
// CHECK: } // end sil function '$s4test0A4_cfgySiAA7MyclassC_SbtF'
@inline(never)
func test_cfg(_ c: Myclass, _ b: Bool) -> Int {
g = 10
let v1 = c.lvar
var v2: Int
if b {
v2 = c.lvar
} else {
v2 = 0
}
return v1 &+ v2
}
// CHECK-LABEL: sil {{.*}} @$s4test0A12_no_hoistingySiAA7MyclassC_SbtF
// CHECK: bb1:
// CHECK: [[GETTER1:%[0-9]+]] = function_ref @$s4test7MyclassC4lvarSivg
// CHECK: = apply [[GETTER1]](%0)
// CHECK: bb2:
// CHECK: [[GETTER2:%[0-9]+]] = function_ref @$s4test7MyclassC4lvarSivg
// CHECK: = apply [[GETTER2]](%0)
// CHECK: bb3({{.*}}):
// CHECK: } // end sil function '$s4test0A12_no_hoistingySiAA7MyclassC_SbtF'
@inline(never)
func test_no_hoisting(_ c: Myclass, _ b: Bool) -> Int {
var v: Int
if b {
g = 20
v = c.lvar + 2
} else {
g = 30
v = c.lvar + 3
}
return v
}
// This test is disabled, because for structs, it does not work yet.
// CSE is too conservative to handle indirect getter arguments currently.
// CHECK-LABEL: sil {{.*}} @$s4test0A7_structySiAA8MystructVF
// CHECK-DISABLED: [[GETTER:%[0-9]+]] = function_ref @$s4test8MystructV4lvarSivg
// CHECK-DISABLED: [[V1:%[0-9]+]] = apply [[GETTER]]({{.*}})
// CHECK-DISABLED: [[V2OPT:%[0-9]+]] = load
// CHECK-DISABLED: [[V2:%[0-9]+]] = unchecked_enum_data [[V2OPT]]
// CHECK-DISABLED: [[V1VAL:%[0-9]+]] = struct_extract [[V1]]
// CHECK-DISABLED: [[V2VAL:%[0-9]+]] = struct_extract [[V2]]
// CHECK-DISABLED: builtin "sadd{{.*}}"([[V1VAL]] {{.*}}, [[V2VAL]]
// CHECK-DISABLED: } // end sil function '$s4test0A7_structySiAA8MystructVF'
@inline(never)
func test_struct(_ s: Mystruct) -> Int {
var sm = s
g = 42
let v1 = sm.lvar
let v2 = sm.lvar
return v1 &+ v2
}
// CHECK-LABEL: sil {{.*}} @$s4test0A19_overwritten_structySiAA8MystructVF
// CHECK: [[GETTER:%[0-9]+]] = function_ref @$s4test8MystructV4lvarSivg
// CHECK: [[V1:%[0-9]+]] = apply [[GETTER]]({{.*}})
// CHECK: [[V2:%[0-9]+]] = apply [[GETTER]]({{.*}})
// CHECK: [[V1VAL:%[0-9]+]] = struct_extract [[V1]]
// CHECK: [[V2VAL:%[0-9]+]] = struct_extract [[V2]]
// CHECK: builtin "sadd{{.*}}"([[V1VAL]] {{.*}}, [[V2VAL]]
// CHECK: } // end sil function '$s4test0A19_overwritten_structySiAA8MystructVF'
@inline(never)
func test_overwritten_struct(_ s: Mystruct) -> Int {
var sm = s
g = 42
let v1 = sm.lvar
sm = s
g = 43
let v2 = sm.lvar
return v1 &+ v2
}
func calltests() {
// CHECK-OUTPUT-LABEL: test_simple
print("test_simple")
// CHECK-OUTPUT-NEXT: lvar init
// CHECK-OUTPUT-NEXT: 54
print(test_simple(Myclass()))
// CHECK-OUTPUT-LABEL: test_cfg
print("test_cfg")
// CHECK-OUTPUT-NEXT: lvar init
// CHECK-OUTPUT-NEXT: 20
print(test_cfg(Myclass(), true))
// CHECK-OUTPUT-LABEL: test_no_hoisting
print("test_no_hoisting")
// CHECK-OUTPUT-NEXT: lvar init
// CHECK-OUTPUT-NEXT: 22
print(test_no_hoisting(Myclass(), true))
// CHECK-OUTPUT-NEXT: lvar init
// CHECK-OUTPUT-NEXT: 33
print(test_no_hoisting(Myclass(), false))
// CHECK-OUTPUT-LABEL: test_struct
print("test_struct")
// CHECK-OUTPUT-NEXT: lvar init
// CHECK-OUTPUT-NEXT: 84
print(test_struct(Mystruct()))
// CHECK-OUTPUT-LABEL: test_overwritten_struct
print("test_overwritten_struct")
// CHECK-OUTPUT-NEXT: lvar init
// CHECK-OUTPUT-NEXT: lvar init
// CHECK-OUTPUT-NEXT: 85
print(test_overwritten_struct(Mystruct()))
}
calltests()
|