Skip to content

Commit 6569c98

Browse files
committed
SIL optimizer: add an additional stack promotion pass to the late pipeline
Sometimes stack promotion can catch cases only at a late stage of the pipeline, after FunctionSignatureOpts. https://bugs.swift.org/browse/SR-12773 rdar://problem/63068408
1 parent 5013a02 commit 6569c98

File tree

3 files changed

+83
-2
lines changed

3 files changed

+83
-2
lines changed

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,10 @@ static void addLateLoopOptPassPipeline(SILPassPipelinePlan &P) {
606606
P.addAccessEnforcementReleaseSinking();
607607
P.addAccessEnforcementOpts();
608608

609+
// Sometimes stack promotion can catch cases only at this late stage of the
610+
// pipeline, after FunctionSignatureOpts.
611+
P.addStackPromotion();
612+
609613
// Optimize overflow checks.
610614
P.addRedundantOverflowCheckRemoval();
611615
P.addMergeCondFails();

test/SILOptimizer/devirt_speculative_init.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ public func make(type: Cat.Type, cats: Int) {
2727
// CHECK: bb1:
2828
// CHECK: return
2929
// CHECK: bb2({{%.*}} : $@thick Cat.Type):
30-
// CHECK: alloc_ref $Cat
30+
// CHECK: alloc_ref [stack] $Cat
3131
// CHECK: br bb1
3232
// CHECK: bb3:
33-
// CHECK: alloc_ref $BigCat
33+
// CHECK: alloc_ref [stack] $BigCat
3434
// CHECK: br bb1
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -parse-as-library -emit-module -emit-module-path=%t/Module.swiftmodule -module-name=Module -DMODULE %s -O -emit-sil -o %t/module.sil
3+
// RUN: %target-swift-frontend -module-name=main -DMAIN %s -I%t -O -emit-sil | %FileCheck %s
4+
5+
// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib
6+
7+
#if MODULE
8+
9+
public struct Foo: Equatable {
10+
@usableFromInline var optionA: Bool
11+
@usableFromInline var optionB: Optional<Int>
12+
13+
public typealias ArrayLiteralElement = FooElement
14+
15+
public struct FooElement: Equatable {
16+
@usableFromInline enum Backing: Equatable {
17+
case a
18+
case b(Int)
19+
}
20+
21+
@usableFromInline var backing: Backing
22+
23+
@inlinable internal init(backing: Backing) {
24+
self.backing = backing
25+
}
26+
27+
public static let optionA = FooElement(backing: .a)
28+
29+
@inlinable
30+
public static func getOptionA() -> FooElement {
31+
return FooElement(backing: .a)
32+
}
33+
@inlinable
34+
public static func optionB(_ x: Int) -> FooElement {
35+
return FooElement(backing: .b(x))
36+
}
37+
}
38+
}
39+
40+
extension Foo: ExpressibleByArrayLiteral {
41+
@inlinable
42+
@inline(never)
43+
public init(arrayLiteral things: FooElement...) {
44+
self.optionA = false
45+
self.optionB = nil
46+
for thing in things {
47+
switch thing.backing {
48+
case .a:
49+
self.optionA = true
50+
case .b(let x):
51+
self.optionB = x
52+
}
53+
}
54+
}
55+
}
56+
57+
#endif
58+
59+
60+
#if MAIN
61+
62+
import Module
63+
64+
// Check if the array literal can be stack promoted.
65+
66+
// CHECK-LABEL: sil @$s4main6testit6Module3FooVyF
67+
// CHECK: alloc_ref [stack] [tail_elems $Foo.FooElement
68+
// CHECK: } // end sil function '$s4main6testit6Module3FooVyF'
69+
70+
public func testit() -> Foo {
71+
return [.optionA, .optionB(0xbeef), .optionA]
72+
}
73+
74+
75+
#endif
76+
77+

0 commit comments

Comments
 (0)