Skip to content

Commit 1d4054c

Browse files
committed
Optimizer: add simplification for checked_cast_addr_br instructions
1 parent d34dec8 commit 1d4054c

File tree

4 files changed

+201
-0
lines changed

4 files changed

+201
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ swift_compiler_sources(Optimizer
1212
SimplifyBeginCOWMutation.swift
1313
SimplifyBranch.swift
1414
SimplifyBuiltin.swift
15+
SimplifyCheckedCast.swift
1516
SimplifyCondBranch.swift
1617
SimplifyCondFail.swift
1718
SimplifyConvertEscapeToNoEscape.swift
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===--- SimplifyCheckedCast.swift ----------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SIL
14+
15+
extension CheckedCastAddrBranchInst : OnoneSimplifyable {
16+
func simplify(_ context: SimplifyContext) {
17+
guard let castWillSucceed = self.dynamicCastResult else {
18+
return
19+
}
20+
if castWillSucceed {
21+
replaceSuccess(context)
22+
} else {
23+
replaceFailure(context)
24+
}
25+
}
26+
}
27+
28+
private extension CheckedCastAddrBranchInst {
29+
func replaceSuccess(_ context: SimplifyContext) {
30+
let builder = Builder(before: self, context)
31+
switch consumptionKind {
32+
case .TakeAlways, .TakeOnSuccess:
33+
builder.createCopyAddr(from: source, to: destination, takeSource: true, initializeDest: true)
34+
case .CopyOnSuccess:
35+
builder.createCopyAddr(from: source, to: destination, takeSource: false, initializeDest: true)
36+
}
37+
builder.createBranch(to: successBlock)
38+
context.erase(instruction: self)
39+
}
40+
41+
func replaceFailure(_ context: SimplifyContext) {
42+
let builder = Builder(before: self, context)
43+
switch consumptionKind {
44+
case .TakeAlways:
45+
builder.createDestroyAddr(address: source)
46+
case .CopyOnSuccess, .TakeOnSuccess:
47+
break
48+
}
49+
builder.createBranch(to: failureBlock)
50+
context.erase(instruction: self)
51+
}
52+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -onone-simplification -simplify-instruction=checked_cast_addr_br | %FileCheck %s
2+
3+
4+
// REQUIRES: swift_in_compiler
5+
6+
import Swift
7+
import Builtin
8+
9+
class X {}
10+
class D: X {}
11+
12+
struct S {
13+
var x: X
14+
}
15+
16+
// CHECK-LABEL: sil @same_type_take_always
17+
// CHECK: copy_addr [take] %1 to [init] %0 : $*X
18+
// CHECK-NEXT: br bb1
19+
// CHECK: bb1:
20+
// CHECK-NEXT: tuple
21+
// CHECK-NEXT: return
22+
// CHECK-NOT: bb2:
23+
// CHECK: } // end sil function 'same_type_take_always'
24+
sil @same_type_take_always : $@convention(thin) (@in X) -> @out X {
25+
bb0(%0 : $*X, %1 : $*X):
26+
checked_cast_addr_br take_always X in %1 : $*X to X in %0 : $*X, bb1, bb2
27+
bb1:
28+
%r = tuple()
29+
return %r : $()
30+
bb2:
31+
unreachable
32+
}
33+
34+
// CHECK-LABEL: sil @same_type_take_on_success
35+
// CHECK: copy_addr [take] %1 to [init] %0 : $*X
36+
// CHECK-NEXT: br bb1
37+
// CHECK: bb1:
38+
// CHECK-NEXT: tuple
39+
// CHECK-NEXT: return
40+
// CHECK-NOT: bb2:
41+
// CHECK: } // end sil function 'same_type_take_on_success'
42+
sil @same_type_take_on_success : $@convention(thin) (@in X) -> @out X {
43+
bb0(%0 : $*X, %1 : $*X):
44+
checked_cast_addr_br take_on_success X in %1 : $*X to X in %0 : $*X, bb1, bb2
45+
bb1:
46+
%r = tuple()
47+
return %r : $()
48+
bb2:
49+
unreachable
50+
}
51+
52+
// CHECK-LABEL: sil @same_type_copy_on_success
53+
// CHECK: copy_addr %1 to [init] %0 : $*X
54+
// CHECK-NEXT: br bb1
55+
// CHECK: bb1:
56+
// CHECK-NEXT: tuple
57+
// CHECK-NEXT: return
58+
// CHECK-NOT: bb2:
59+
// CHECK: } // end sil function 'same_type_copy_on_success'
60+
sil @same_type_copy_on_success : $@convention(thin) (@in X) -> @out X {
61+
bb0(%0 : $*X, %1 : $*X):
62+
checked_cast_addr_br copy_on_success X in %1 : $*X to X in %0 : $*X, bb1, bb2
63+
bb1:
64+
%r = tuple()
65+
return %r : $()
66+
bb2:
67+
unreachable
68+
}
69+
70+
// CHECK-LABEL: sil @fail_with_take_always
71+
// CHECK: bb0(%0 : $*S, %1 : $*String):
72+
// CHECK-NEXT: destroy_addr %1 : $*String
73+
// CHECK-NEXT: br bb1
74+
// CHECK: bb1:
75+
// CHECK-NEXT: unreachable
76+
// CHECK: } // end sil function 'fail_with_take_always'
77+
sil @fail_with_take_always : $@convention(thin) (@in String) -> @out S {
78+
bb0(%0 : $*S, %1 : $*String):
79+
checked_cast_addr_br take_always String in %1 : $*String to S in %0 : $*S, bb1, bb2
80+
bb1:
81+
%r = tuple()
82+
return %r : $()
83+
bb2:
84+
unreachable
85+
}
86+
87+
// CHECK-LABEL: sil @fail_with_take_on_success
88+
// CHECK: bb0(%0 : $*S, %1 : $*String):
89+
// CHECK-NEXT: br bb1
90+
// CHECK: bb1:
91+
// CHECK-NEXT: unreachable
92+
// CHECK: } // end sil function 'fail_with_take_on_success'
93+
sil @fail_with_take_on_success : $@convention(thin) (@in String) -> @out S {
94+
bb0(%0 : $*S, %1 : $*String):
95+
checked_cast_addr_br take_on_success String in %1 : $*String to S in %0 : $*S, bb1, bb2
96+
bb1:
97+
%r = tuple()
98+
return %r : $()
99+
bb2:
100+
unreachable
101+
}
102+
103+
// CHECK-LABEL: sil @fail_with_copy_on_success
104+
// CHECK: bb0(%0 : $*S, %1 : $*String):
105+
// CHECK-NEXT: br bb1
106+
// CHECK: bb1:
107+
// CHECK-NEXT: unreachable
108+
// CHECK: } // end sil function 'fail_with_copy_on_success'
109+
sil @fail_with_copy_on_success : $@convention(thin) (@in String) -> @out S {
110+
bb0(%0 : $*S, %1 : $*String):
111+
checked_cast_addr_br copy_on_success String in %1 : $*String to S in %0 : $*S, bb1, bb2
112+
bb1:
113+
%r = tuple()
114+
return %r : $()
115+
bb2:
116+
unreachable
117+
}
118+
119+
// CHECK-LABEL: sil @unknown_result
120+
// CHECK: checked_cast_addr_br
121+
// CHECK: } // end sil function 'unknown_result'
122+
sil @unknown_result : $@convention(thin) (@in X) -> @out D {
123+
bb0(%0 : $*D, %1 : $*X):
124+
checked_cast_addr_br copy_on_success X in %1 : $*X to D in %0 : $*D, bb1, bb2
125+
bb1:
126+
%r = tuple()
127+
return %r : $()
128+
bb2:
129+
unreachable
130+
}
131+

test/embedded/arrays.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ func print(_ array: [Int]) {
4343
print("]")
4444
}
4545
46+
func isArray<S: Sequence>(_ s: S) -> Bool where S.Element == Int {
47+
return s is [Int]
48+
}
49+
50+
public func testIsArray() -> Bool {
51+
return isArray(Array<Int>())
52+
}
53+
54+
public func testIsNotArray() -> Bool {
55+
return isArray(Array<Int>().lazy)
56+
}
57+
4658
func test() {
4759
var a = [1, 2, 3]
4860
a.append(8)
@@ -51,6 +63,11 @@ func test() {
5163
var c = b
5264
c = c.reversed().filter { $0 % 2 == 0 }
5365
print(c) // CHECK: [8, 4, 2]
66+
67+
// CHECK: yes
68+
print(testIsArray() ? "yes" : "no")
69+
// CHECK: no
70+
print(testIsNotArray() ? "yes" : "no")
5471
}
5572

5673
test()

0 commit comments

Comments
 (0)