Skip to content

Commit 741c6c3

Browse files
committed
Swift Optimizer: add the ComputeSideEffects pass.
Computes the side effects for a function, which consists of argument- and global effects. This is similar to the ComputeEscapeEffects pass, just for side-effects.
1 parent dd0f360 commit 741c6c3

File tree

11 files changed

+1582
-19
lines changed

11 files changed

+1582
-19
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
swift_compiler_sources(Optimizer
1010
AssumeSingleThreaded.swift
1111
ComputeEscapeEffects.swift
12+
ComputeSideEffects.swift
1213
ObjCBridgingOptimization.swift
1314
MergeCondFails.swift
1415
ReleaseDevirtualizer.swift

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ComputeSideEffects.swift

Lines changed: 468 additions & 0 deletions
Large diffs are not rendered by default.

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ private func registerSwiftPasses() {
5252
// Function passes
5353
registerPass(mergeCondFailsPass, { mergeCondFailsPass.run($0) })
5454
registerPass(computeEscapeEffects, { computeEscapeEffects.run($0) })
55+
registerPass(computeSideEffects, { computeSideEffects.run($0) })
5556
registerPass(objCBridgingOptimization, { objCBridgingOptimization.run($0) })
5657
registerPass(stackPromotion, { stackPromotion.run($0) })
5758
registerPass(functionStackProtection, { functionStackProtection.run($0) })

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ SWIFT_FUNCTION_PASS(AccessDumper, "dump-access",
245245
"Dump access information")
246246
SWIFT_FUNCTION_PASS(ComputeEscapeEffects, "compute-escape-effects",
247247
"Computes function escape effects")
248+
SWIFT_FUNCTION_PASS(ComputeSideEffects, "compute-side-effects",
249+
"Computes function side effects")
248250
PASS(FlowIsolation, "flow-isolation",
249251
"Enforces flow-sensitive actor isolation rules")
250252
PASS(FunctionOrderPrinter, "function-order-printer",

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ static void addHighLevelFunctionPipeline(SILPassPipelinePlan &P) {
639639

640640
P.addStringOptimization();
641641
P.addComputeEscapeEffects();
642+
P.addComputeSideEffects();
642643
}
643644

644645
// After "high-level" function passes have processed the entire call tree, run
@@ -654,6 +655,7 @@ static void addHighLevelModulePipeline(SILPassPipelinePlan &P) {
654655
//
655656
// FIXME: why does StackPromotion need to run in the module pipeline?
656657
P.addComputeEscapeEffects();
658+
P.addComputeSideEffects();
657659
P.addStackPromotion();
658660

659661
P.addGlobalOpt();
@@ -695,6 +697,7 @@ static void addClosureSpecializePassPipeline(SILPassPipelinePlan &P) {
695697
// ComputeEffects should be done at the end of a function-pipeline. The next
696698
// pass (GlobalOpt) is a module pass, so this is the end of a function-pipeline.
697699
P.addComputeEscapeEffects();
700+
P.addComputeSideEffects();
698701

699702
// Hoist globals out of loops.
700703
// Global-init functions should not be inlined GlobalOpt is done.
@@ -726,6 +729,7 @@ static void addClosureSpecializePassPipeline(SILPassPipelinePlan &P) {
726729
addSimplifyCFGSILCombinePasses(P);
727730

728731
P.addComputeEscapeEffects();
732+
P.addComputeSideEffects();
729733

730734
// We do this late since it is a pass like the inline caches that we only want
731735
// to run once very late. Make sure to run at least one round of the ARC
@@ -747,6 +751,7 @@ static void addLowLevelPassPipeline(SILPassPipelinePlan &P) {
747751
// We've done a lot of optimizations on this function, attempt to FSO.
748752
P.addFunctionSignatureOpts();
749753
P.addComputeEscapeEffects();
754+
P.addComputeSideEffects();
750755
}
751756

752757
static void addLateLoopOptPassPipeline(SILPassPipelinePlan &P) {
@@ -776,6 +781,7 @@ static void addLateLoopOptPassPipeline(SILPassPipelinePlan &P) {
776781
// Sometimes stack promotion can catch cases only at this late stage of the
777782
// pipeline, after FunctionSignatureOpts.
778783
P.addComputeEscapeEffects();
784+
P.addComputeSideEffects();
779785
P.addStackPromotion();
780786

781787
// Optimize overflow checks.

test/SILOptimizer/cross-module-effects.swift

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,17 @@ public final class X {
2525
}
2626

2727
// CHECK-FR-MODULE-LABEL: sil [canonical] @$s6Module17noInlineNoEffectsySiAA1XCF :
28-
// CHECK-FR-MODULE-NEXT: [%0: noescape **]
28+
// CHECK-FR-MODULE-NEXT: [%0: noescape **, read c0.v**]
29+
// CHECK-FR-MODULE-NEXT: [global: ]
2930
// CHECK-FR-MODULE-NEXT: {{^[^[]}}
3031
// CHECK-LE-MODULE-NOT: @$s6Module17noInlineNoEffectsySiAA1XCF
3132
public func noInlineNoEffects(_ x: X) -> Int {
3233
return x.i
3334
}
3435

3536
// CHECK-FR-MODULE-LABEL: sil [serialized] [noinline] [canonical] @$s6Module15inlineNoEffectsySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int {
36-
// CHECK-FR-MODULE-NEXT: [%0: noescape **]
37+
// CHECK-FR-MODULE-NEXT: [%0: noescape **, read c0.v**]
38+
// CHECK-FR-MODULE-NEXT: [global: ]
3739
// CHECK-FR-MODULE-NEXT: {{^[^[]}}
3840
// CHECK-LE-MODULE-LABEL: sil [serialized] [noinline] [canonical] @$s6Module15inlineNoEffectsySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int {
3941
// CHECK-LE-MODULE-NEXT: {{^[^[]}}
@@ -44,7 +46,8 @@ public func inlineNoEffects(_ x: X) -> Int {
4446
}
4547

4648
// CHECK-FR-MODULE-LABEL: sil [canonical] @$s6Module14internalCalleeySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int {
47-
// CHECK-FR-MODULE-NEXT: [%0: noescape **]
49+
// CHECK-FR-MODULE-NEXT: [%0: noescape **, read c0.v**]
50+
// CHECK-FR-MODULE-NEXT: [global: ]
4851
// CHECK-FR-MODULE-NEXT: {{^[^[]}}
4952
// CHECK-LE-MODULE-LABEL: sil [canonical] @$s6Module14internalCalleeySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int{{$}}
5053
@usableFromInline
@@ -53,7 +56,8 @@ func internalCallee(_ x: X) -> Int {
5356
}
5457

5558
// CHECK-FR-MODULE-LABEL: sil [canonical] @$s6Module19noInlineWithEffectsySiAA1XCF :
56-
// CHECK-FR-MODULE-NEXT: [%0: noescape! **]
59+
// CHECK-FR-MODULE-NEXT: [%0: noescape! **, read c0.v**]
60+
// CHECK-FR-MODULE-NEXT: [global: ]
5761
// CHECK-FR-MODULE-NEXT: {{^[^[]}}
5862
// CHECK-LE-MODULE-NOT: @$s6Module19noInlineWithEffectsySiAA1XCF
5963
@_effects(notEscaping x.**)
@@ -62,7 +66,8 @@ public func noInlineWithEffects(_ x: X) -> Int {
6266
}
6367

6468
// CHECK-FR-MODULE-LABEL: sil [serialized] [noinline] [canonical] @$s6Module17inlineWithEffectsySiAA1XCF :
65-
// CHECK-FR-MODULE-NEXT: [%0: noescape! **]
69+
// CHECK-FR-MODULE-NEXT: [%0: noescape! **, read c0.v**]
70+
// CHECK-FR-MODULE-NEXT: [global: ]
6671
// CHECK-FR-MODULE-NEXT: {{^[^[]}}
6772
// CHECK-LE-MODULE-LABEL: sil [serialized] [noinline] [canonical] @$s6Module17inlineWithEffectsySiAA1XCF :
6873
// CHECK-LE-MODULE-NEXT: [%0: noescape! **]
@@ -75,7 +80,8 @@ public func inlineWithEffects(_ x: X) -> Int {
7580
}
7681

7782
// CHECK-FR-MODULE-LABEL: sil [serialized] [noinline] [canonical] @$s6Module12simpleInlineySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int {
78-
// CHECK-FR-MODULE-NEXT: [%0: noescape **]
83+
// CHECK-FR-MODULE-NEXT: [%0: noescape **, read c0.v**]
84+
// CHECK-FR-MODULE-NEXT: [global: ]
7985
// CHECK-FR-MODULE-NEXT: {{^[^[]}}
8086
// CHECK-LE-MODULE-LABEL: sil [serialized] [noinline] [canonical] @$s6Module12simpleInlineySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int {
8187
// CHECK-LE-MODULE-NEXT: {{^[^[]}}
@@ -100,7 +106,8 @@ public func callit1() -> Int {
100106
}
101107

102108
// CHECK-FR-MAIN-LABEL: sil @$s6Module17noInlineNoEffectsySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int
103-
// CHECK-FR-MAIN-NEXT: [%0: noescape **]
109+
// CHECK-FR-MAIN-NEXT: [%0: noescape **, read c0.v**]
110+
// CHECK-FR-MAIN-NEXT: [global: ]
104111
// CHECK-FR-MAIN-NEXT: {{^[^[]}}
105112
// CHECK-LE-MAIN-LABEL: sil @$s6Module17noInlineNoEffectsySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int{{$}}
106113

@@ -115,7 +122,8 @@ public func callit2() -> Int {
115122
}
116123

117124
// CHECK-FR-MAIN-LABEL: sil public_external [noinline] @$s6Module15inlineNoEffectsySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int {
118-
// CHECK-FR-MAIN-NEXT: [%0: noescape **]
125+
// CHECK-FR-MAIN-NEXT: [%0: noescape **, read c0.v**]
126+
// CHECK-FR-MAIN-NEXT: [global: ]
119127
// CHECK-FR-MAIN-NEXT: {{^[^[]}}
120128
// CHECK-LE-MAIN-LABEL: sil public_external [noinline] @$s6Module15inlineNoEffectsySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int {
121129
// CHECK-LE-MAIN-NEXT: {{^[^[]}}
@@ -162,13 +170,15 @@ public func callit5() -> Int {
162170
}
163171

164172
// CHECK-FR-MAIN-LABEL: sil public_external [noinline] @$s6Module12simpleInlineySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int {
165-
// CHECK-FR-MAIN-NEXT: [%0: noescape **]
173+
// CHECK-FR-MAIN-NEXT: [%0: noescape **, read c0.v**]
174+
// CHECK-FR-MAIN-NEXT: [global: ]
166175
// CHECK-FR-MAIN-NEXT: {{^[^[]}}
167176
// CHECK-LE-MAIN-LABEL: sil public_external [noinline] @$s6Module12simpleInlineySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int {
168177
// CHECK-LE-MAIN-NEXT: {{^[^[]}}
169178

170179
// CHECK-FR-MAIN-LABEL: sil @$s6Module14internalCalleeySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int {
171-
// CHECK-FR-MAIN-NEXT: [%0: noescape **]
180+
// CHECK-FR-MAIN-NEXT: [%0: noescape **, read c0.v**]
181+
// CHECK-FR-MAIN-NEXT: [global: ]
172182
// CHECK-FR-MAIN-NEXT: {{^[^[]}}
173183
// CHECK-LE-MAIN-LABEL: sil @$s6Module14internalCalleeySiAA1XCF : $@convention(thin) (@guaranteed X) -> Int{{$}}
174184

test/SILOptimizer/existential_metatype.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ protocol SomeP {}
44
public enum SpecialEnum : SomeP {}
55

66
// CHECK-LABEL: sil shared [noinline] @$s20existential_metatype17checkProtocolType0aE0Sbxm_tAA5SomePRzlFAA11SpecialEnumO_Tg5Tf4d_n : $@convention(thin) () -> Bool {
7-
// CHECK-NEXT: bb0:
7+
// CHECK: bb0:
88
// CHECK-NEXT: %0 = integer_literal $Builtin.Int1, -1
99
// CHECK-NEXT: %1 = struct $Bool (%0 : $Builtin.Int1)
1010
// CHECK-NEXT: return %1 : $Bool

test/SILOptimizer/existential_specializer_indirect_class.sil

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ bb0(%0 : $*ClassProtocol):
2121

2222
// Check that all the opened types are optimized away in the specialization of test_indirect_class_protocol_guaranteed
2323
// CHECK-LABEL: sil shared @$s39test_indirect_class_protocol_guaranteedTf4e_n : $@convention(thin) <τ_0_0 where τ_0_0 : ClassProtocol> (@in_guaranteed τ_0_0) -> ()
24-
// CHECK-NEXT: //
25-
// CHECK-NEXT: bb0(%0 : $*τ_0_0):
24+
// CHECK: bb0(%0 : $*τ_0_0):
2625
// CHECK-NEXT: [[INPUT:%1]] = load %0
2726
// CHECK-NEXT: [[ARG:%.*]] = unchecked_ref_cast [[INPUT]]
2827
// CHECK-NEXT: [[METHOD:%.*]] = witness_method $C, #ClassProtocol.method
2928
// CHECK-NEXT: apply [[METHOD]]<C>([[ARG]])
3029
// CHECK-NEXT: return undef
30+
// CHECK: } // end sil function '$s39test_indirect_class_protocol_guaranteedTf4e_n'
3131

3232
sil @test_indirect_class_protocol_guaranteed : $@convention(thin) (@in_guaranteed ClassProtocol) -> () {
3333
bb0(%0 : $*ClassProtocol):
@@ -48,8 +48,9 @@ bb0(%0 : $*ClassProtocol):
4848
// Check the generated specialization of test_indirect_class_protocol
4949
// CHECK-LABEL: sil shared @$s28test_indirect_class_protocolTf4e_n4main1CC_Tg5Tf4d_n : $@convention(thin) () -> ()
5050
// Make sure *everything* was inlined / optimized away
51-
// CHECK-NEXT: bb0:
51+
// CHECK: bb0:
5252
// CHECK-NEXT: return undef
53+
// CHECK: } // end sil function '$s28test_indirect_class_protocolTf4e_n4main1CC_Tg5Tf4d_n'
5354

5455
sil @invoke_indirect_class_protocol : $@convention(thin) (@guaranteed C) -> () {
5556
bb0(%0 : $C):

test/SILOptimizer/functionsigopts_crash.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ public struct S : P {
2525
// * FSO: argument explosion
2626

2727
// CHECK-LABEL: sil shared [noinline] @$s4main6testityyAA1P_pFTf4e_nAA1SV_Tg5Tf4x_n : $@convention(thin) (Int) -> () {
28-
// CHECK-NEXT: // %0 "p"
28+
// CHECK: // %0 "p"
29+
// CHECK: } // end sil function '$s4main6testityyAA1P_pFTf4e_nAA1SV_Tg5Tf4x_n'
2930
@inline(never)
3031
func testit(_ p: P) {
3132
p.foo()

test/SILOptimizer/optionset.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,26 @@ public struct TestOptions: OptionSet {
1818
// CHECK: %initval = struct $TestOptions ([[INT]] : $Int)
1919
let globalTestOptions: TestOptions = [.first, .second, .third, .fourth]
2020

21-
// CHECK-LABEL: sil @{{.*}}returnTestOptions{{.*}}
22-
// CHECK-NEXT: bb0:
21+
// CHECK-LABEL: sil @$s4test17returnTestOptionsAA0cD0VyF
22+
// CHECK: bb0:
2323
// CHECK-NEXT: builtin
2424
// CHECK-NEXT: integer_literal {{.*}}, 15
2525
// CHECK-NEXT: struct $Int
2626
// CHECK: struct $TestOptions
2727
// CHECK-NEXT: return
28+
// CHECK: } // end sil function '$s4test17returnTestOptionsAA0cD0VyF'
2829
public func returnTestOptions() -> TestOptions {
2930
return [.first, .second, .third, .fourth]
3031
}
3132

32-
// CHECK-LABEL: sil @{{.*}}returnEmptyTestOptions{{.*}}
33-
// CHECK-NEXT: bb0:
33+
// CHECK-LABEL: sil @$s4test22returnEmptyTestOptionsAA0dE0VyF
34+
// CHECK: bb0:
3435
// CHECK-NEXT: integer_literal {{.*}}, 0
3536
// CHECK-NEXT: struct $Int
3637
// CHECK: builtin "onFastPath"() : $()
3738
// CHECK-NEXT: struct $TestOptions
3839
// CHECK-NEXT: return
40+
// CHECK: } // end sil function '$s4test22returnEmptyTestOptionsAA0dE0VyF'
3941
public func returnEmptyTestOptions() -> TestOptions {
4042
return []
4143
}

0 commit comments

Comments
 (0)