Skip to content

Commit 546b5af

Browse files
committed
Copies over original closure-spec tests as XFAIL (when needed)
1 parent fd60984 commit 546b5af

10 files changed

+2325
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-swift-frontend -parse-as-library -O -module-name=test -experimental-swift-based-closure-specialization %s -emit-sil | %FileCheck %s
2+
// XFAIL: *
3+
4+
func closure(_ a: Int, b: Int) -> Bool {
5+
return a < b
6+
}
7+
8+
// Check that closure() is inlined into call_closure after call_closure is
9+
// specialized for it.
10+
11+
// CHECK-LABEL: sil shared [noinline] @$s4test12call_closureySbSi_SiSbSi_SitXEtF27$s4test7closure_1bSbSi_SitFTf1nnc_n
12+
// CHECK-NOT: apply
13+
// CHECK: builtin "cmp_slt_Int
14+
// CHECK-NOT: apply
15+
// CHECK: return
16+
@inline(never)
17+
func call_closure(_ a: Int, _ b: Int, _ f: (Int , Int) -> Bool) -> Bool {
18+
return f(a, b)
19+
}
20+
21+
public func testit() -> Bool {
22+
return call_closure(0, 1, closure)
23+
}
24+

test/SILOptimizer/experimental-swift-based-closure-specialization/closure_specialize.sil

Lines changed: 941 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %target-sil-opt -sil-verify-without-invalidation -enable-sil-verify-all -simplify-cfg -experimental-swift-based-closure-specialization %s
2+
3+
// Test if the ClosureSpecializer correctly invalidates the dominator tree
4+
// even if there are no functions specialized.
5+
// The test just checks if the compiler does not crash.
6+
// First running SimplifyCFG creates the dominator tree, which should then be
7+
// invalidated by the ClosureSpecializer.
8+
// If this is not done correctly the verification will complain that the
9+
// dominator tree is not up to date.
10+
11+
import Builtin
12+
import Swift
13+
14+
sil @closure : $@convention(thin) () -> ()
15+
16+
sil @use_closure : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
17+
18+
sil hidden [noinline] @use_closure2 : $@convention(thin) (@owned @callee_owned () -> (), @owned @callee_owned () -> ()) -> () {
19+
bb0(%0 : $@callee_owned () -> (), %1 : $@callee_owned () -> ()):
20+
%2 = apply %0() : $@callee_owned () -> ()
21+
%3 = apply %1() : $@callee_owned () -> ()
22+
%4 = tuple ()
23+
return %3 : $()
24+
}
25+
26+
sil @insert_release_in_liferange_exit_block : $@convention(thin) () -> () {
27+
bb0:
28+
%2 = function_ref @closure : $@convention(thin) () -> ()
29+
%3 = partial_apply %2() : $@convention(thin) () -> ()
30+
%8 = function_ref @use_closure : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
31+
%5 = partial_apply %8(%3) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
32+
33+
// There is a critical edge from bb0 to bb2 which is broken by ValueLifetimeAnalysis.
34+
cond_br undef, bb2, bb1
35+
36+
bb1:
37+
strong_retain %3 : $@callee_owned () -> ()
38+
strong_retain %3 : $@callee_owned () -> ()
39+
%10 = function_ref @use_closure2 : $@convention(thin) (@owned @callee_owned () -> (), @owned @callee_owned () -> ()) -> ()
40+
41+
// Passing two closures actually prevents closure specialization.
42+
%17 = apply %10(%3, %3) : $@convention(thin) (@owned @callee_owned () -> (), @owned @callee_owned () -> ()) -> ()
43+
br bb2
44+
45+
bb2:
46+
strong_release %5 : $@callee_owned () -> ()
47+
%11 = tuple ()
48+
return %11 : $()
49+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all -experimental-swift-based-closure-specialization %s | %FileCheck %s
2+
// XFAIL: *
3+
4+
import Builtin
5+
6+
class C {}
7+
8+
sil [ossa] @getC : $@convention(thin) () -> @owned C
9+
10+
class Storage {}
11+
12+
struct Val {}
13+
14+
// Verify that the argument to the specialized take_closure is still @_eagerMove.
15+
16+
// CHECK-LABEL: sil {{.*}}@$s12take_closure0B04main1CCTf1nc_n : {{.*}}{
17+
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove @owned $C, {{%[^,]+}} :
18+
// CHECK-LABEL: } // end sil function '$s12take_closure0B04main1CCTf1nc_n'
19+
20+
sil [ossa] [noinline] @take_closure : $@convention(thin) (@owned C, @guaranteed @noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()) -> () {
21+
bb0(%c : @_eagerMove @owned $C, %0 : @guaranteed $@noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()):
22+
%getC = function_ref @getC : $@convention(thin) () -> @owned C
23+
%c1 = apply %getC() : $@convention(thin) () -> @owned C
24+
%c2 = apply %getC() : $@convention(thin) () -> @owned C
25+
%3 = apply %0(%c1, %c2) : $@noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()
26+
destroy_value %c2 : $C
27+
destroy_value %c1 : $C
28+
destroy_value %c : $C
29+
%retval = tuple()
30+
return %retval : $()
31+
}
32+
33+
sil shared [ossa] @closure : $@convention(thin) (@guaranteed C, @guaranteed C, @guaranteed C) -> () {
34+
bb0(%0 : @guaranteed $C, %1 : @guaranteed $C, %2 : @guaranteed $C):
35+
%15 = tuple ()
36+
return %15 : $()
37+
}
38+
39+
sil @caller : $@convention(thin) (@owned C) -> () {
40+
bb0(%0 : $C):
41+
%3 = function_ref @closure : $@convention(thin) (@guaranteed C, @guaranteed C, @guaranteed C) -> ()
42+
%4 = partial_apply [callee_guaranteed] [on_stack] %3(%0) : $@convention(thin) (@guaranteed C, @guaranteed C, @guaranteed C) -> ()
43+
%take_closure = function_ref @take_closure : $@convention(thin) (@owned C, @guaranteed @noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()) -> ()
44+
strong_retain %0 : $C
45+
%5 = apply %take_closure(%0, %4) : $@convention(thin) (@owned C, @guaranteed @noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()) -> ()
46+
strong_release %0 : $C
47+
dealloc_stack %4 : $@noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()
48+
%retval = tuple()
49+
return %retval : $()
50+
}
51+
52+
// =============================================================================
53+
// rdar://105887096: do not insert a retain inside a read-only function.
54+
// For now, the specialization is disabled.
55+
//
56+
// TODO: A @noescape closure should never be converted to an @owned argument
57+
// regardless of the function attribute.
58+
59+
// This should not be specialized until we support guaranteed arguments.
60+
// CHECK-NOT: @$s20takesReadOnlyClosure
61+
sil private [readonly] @takesReadOnlyClosure : $@convention(thin) (@noescape @callee_guaranteed (Val) -> Val) -> Val {
62+
bb0(%2 : $@noescape @callee_guaranteed (Val) -> Val):
63+
%46 = struct $Val ()
64+
%261 = apply %2(%46) : $@noescape @callee_guaranteed (Val) -> Val
65+
return %261 : $Val
66+
}
67+
68+
sil private @readOnlyClosure : $@convention(thin) (Val, @guaranteed Storage) -> Val {
69+
bb0(%0 : $Val, %1 : @closureCapture $Storage):
70+
%46 = struct $Val ()
71+
return %46 : $Val
72+
}
73+
74+
// CHECK-LABEL: sil @testPassReadOnlyClosure : $@convention(method) (@guaranteed Storage) -> Val {
75+
// CHECK-NOT: @owned Storage
76+
// CHECK: apply %{{.*}} : $@convention(thin) (@noescape @callee_guaranteed (Val) -> Val) -> Val
77+
// CHECK-LABEL: } // end sil function 'testPassReadOnlyClosure'
78+
sil @testPassReadOnlyClosure : $@convention(method) (@guaranteed Storage) -> Val {
79+
bb0(%0 : $Storage):
80+
%176 = function_ref @readOnlyClosure : $@convention(thin) (Val, @guaranteed Storage) -> Val
81+
%177 = partial_apply [callee_guaranteed] [on_stack] %176(%0) : $@convention(thin) (Val, @guaranteed Storage) -> Val
82+
%178 = mark_dependence %177 : $@noescape @callee_guaranteed (Val) -> Val on %0 : $Storage
83+
%188 = function_ref @takesReadOnlyClosure : $@convention(thin) (@noescape @callee_guaranteed (Val) -> Val) -> Val
84+
%189 = apply %188(%178) : $@convention(thin) (@noescape @callee_guaranteed (Val) -> Val) -> Val
85+
dealloc_stack %177 : $@noescape @callee_guaranteed (Val) -> Val
86+
return %189 : $Val
87+
}

0 commit comments

Comments
 (0)