Skip to content

Commit c99ec4c

Browse files
Merge pull request #5284 from swiftwasm/katei/merge-main-2023-02-11
2 parents 1597d04 + 134fe4f commit c99ec4c

File tree

395 files changed

+10554
-8972
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

395 files changed

+10554
-8972
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88

99
swift_compiler_sources(Optimizer
1010
AssumeSingleThreaded.swift
11+
CleanupDebugSteps.swift
1112
ComputeEscapeEffects.swift
1213
ComputeSideEffects.swift
1314
ObjCBridgingOptimization.swift
1415
MergeCondFails.swift
1516
ReleaseDevirtualizer.swift
17+
SimplificationPasses.swift
1618
StackPromotion.swift
1719
)
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//===--- SimplificationPasses.swift ----------------------------------------==//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 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+
/// Removes redundant `debug_step` instructions.
16+
/// If a `debug_step` has the same debug location as a previous or succeeding instruction
17+
/// it is removed. It's just important that there is at least one instruction for a
18+
/// certain debug location so that single stepping on that location will work.
19+
let cleanupDebugStepsPass = FunctionPass(name: "cleanup-debug-steps") {
20+
(function: Function, context: FunctionPassContext) in
21+
22+
for block in function.blocks {
23+
cleanupDebugSteps(in: block, context)
24+
}
25+
}
26+
27+
private func cleanupDebugSteps(in block: BasicBlock, _ context: FunctionPassContext) {
28+
var lastInstWithSameLocation: Instruction?
29+
30+
for inst in block.instructions {
31+
if !inst.location.isDebugSteppable {
32+
if inst is DebugStepInst && !inst.location.isDebugSteppable {
33+
// First case: the instruction which is replaced by the debug_step didn't have a valid
34+
// location itself. Then we don't need the debug_step either.
35+
context.erase(instruction: inst)
36+
}
37+
continue
38+
}
39+
40+
if let li = lastInstWithSameLocation,
41+
!inst.location.hasSameSourceLocation(as: li.location) {
42+
lastInstWithSameLocation = nil
43+
}
44+
45+
// Only instructions which are really compiled down to some machine instructions can be
46+
// single stepped on.
47+
if !inst.producesMachineCode {
48+
continue
49+
}
50+
51+
if let li = lastInstWithSameLocation {
52+
if inst is DebugStepInst {
53+
54+
// Second case:
55+
// %li = some_instruction, loc "l"
56+
// debug_step, loc "l" // current inst -> erase
57+
context.erase(instruction: inst)
58+
continue
59+
} else if li is DebugStepInst {
60+
61+
// Third case:
62+
// debug_step, loc "l" // li -> erase
63+
// %inst = some_instruction, loc "l" // current inst
64+
context.erase(instruction: li)
65+
}
66+
}
67+
lastInstWithSameLocation = inst
68+
}
69+
}
70+
71+
private extension Instruction {
72+
var producesMachineCode: Bool {
73+
switch self {
74+
// We could include more instructions here.
75+
// In worst case a debug_step instruction remains in the code although it's not needed.
76+
// This is harmless.
77+
case is DebugStepInst, is ApplySite, is LoadInst, is StoreInst, is TermInst:
78+
return location.isDebugSteppable
79+
default:
80+
return false
81+
}
82+
}
83+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
//===--- SimplificationPasses.swift ----------------------------------------==//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 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+
//===--------------------------------------------------------------------===//
16+
// Instruction protocols
17+
//===--------------------------------------------------------------------===//
18+
19+
/// Instructions which can be simplified at all optimization levels
20+
protocol Simplifyable : Instruction {
21+
func simplify(_ context: SimplifyContext)
22+
}
23+
24+
/// Instructions which can be simplified at -Onone
25+
protocol OnoneSimplifyable : Simplifyable {
26+
}
27+
28+
/// Instructions which can only be simplified at the end of the -Onone pipeline
29+
protocol LateOnoneSimplifyable : Instruction {
30+
func simplifyLate(_ context: SimplifyContext)
31+
}
32+
33+
//===--------------------------------------------------------------------===//
34+
// Simplification passes
35+
//===--------------------------------------------------------------------===//
36+
37+
let ononeSimplificationPass = FunctionPass(name: "onone-simplification") {
38+
(function: Function, context: FunctionPassContext) in
39+
40+
runSimplification(on: function, context, preserveDebugInfo: true) {
41+
if let i = $0 as? OnoneSimplifyable {
42+
i.simplify($1)
43+
}
44+
}
45+
}
46+
47+
let simplificationPass = FunctionPass(name: "simplification") {
48+
(function: Function, context: FunctionPassContext) in
49+
50+
runSimplification(on: function, context, preserveDebugInfo: false) {
51+
if let i = $0 as? Simplifyable {
52+
i.simplify($1)
53+
}
54+
}
55+
}
56+
57+
let lateOnoneSimplificationPass = FunctionPass(name: "late-onone-simplification") {
58+
(function: Function, context: FunctionPassContext) in
59+
60+
runSimplification(on: function, context, preserveDebugInfo: true) {
61+
if let i = $0 as? LateOnoneSimplifyable {
62+
i.simplifyLate($1)
63+
} else if let i = $0 as? OnoneSimplifyable {
64+
i.simplify($1)
65+
}
66+
}
67+
}
68+
69+
//===--------------------------------------------------------------------===//
70+
// Pass implementation
71+
//===--------------------------------------------------------------------===//
72+
73+
74+
private func runSimplification(on function: Function, _ context: FunctionPassContext,
75+
preserveDebugInfo: Bool,
76+
_ simplify: (Instruction, SimplifyContext) -> ()) {
77+
var worklist = InstructionWorklist(context)
78+
defer { worklist.deinitialize() }
79+
80+
let simplifyCtxt = context.createSimplifyContext(preserveDebugInfo: preserveDebugInfo,
81+
notifyInstructionChanged: {
82+
worklist.pushIfNotVisited($0)
83+
})
84+
85+
// Push in reverse order so that popping from the tail of the worklist visits instruction in forward order again.
86+
worklist.pushIfNotVisited(contentsOf: function.reversedInstructions)
87+
88+
// Run multiple iterations because cleanupDeadCode can add new candidates to the worklist.
89+
repeat {
90+
91+
// The core worklist-loop.
92+
while let instruction = worklist.popAndForget() {
93+
if instruction.isDeleted {
94+
continue
95+
}
96+
if !context.options.enableSimplification(for: instruction) {
97+
continue
98+
}
99+
if !context.continueWithNextSubpassRun(for: instruction) {
100+
return
101+
}
102+
simplify(instruction, simplifyCtxt)
103+
}
104+
105+
cleanupDeadInstructions(in: function, preserveDebugInfo, context)
106+
cleanupDeadBlocks(in: function, pushNewCandidatesTo: &worklist, context)
107+
108+
} while !worklist.isEmpty
109+
110+
if context.needFixStackNesting {
111+
function.fixStackNesting(context)
112+
}
113+
}
114+
115+
private func cleanupDeadInstructions(in function: Function,
116+
_ preserveDebugInfo: Bool,
117+
_ context: FunctionPassContext) {
118+
if preserveDebugInfo {
119+
context.removeTriviallyDeadInstructionsPreservingDebugInfo(in: function)
120+
} else {
121+
context.removeTriviallyDeadInstructionsIgnoringDebugUses(in: function)
122+
}
123+
}
124+
125+
private func cleanupDeadBlocks(in function: Function,
126+
pushNewCandidatesTo worklist: inout InstructionWorklist,
127+
_ context: FunctionPassContext) {
128+
if context.removeDeadBlocks(in: function) {
129+
// After deleting dead blocks their (still alive) successor blocks may become eligible for block merging.
130+
// Therefore we re-run simplification for all branch instructions.
131+
for block in function.blocks.reversed() {
132+
if let bi = block.terminator as? BranchInst {
133+
worklist.pushIfNotVisited(bi)
134+
}
135+
}
136+
}
137+
}

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
88

99
swift_compiler_sources(Optimizer
10+
SimplifyApply.swift
1011
SimplifyBeginCOWMutation.swift
12+
SimplifyBranch.swift
13+
SimplifyBuiltin.swift
14+
SimplifyCondBranch.swift
1115
SimplifyGlobalValue.swift
12-
SimplifyStrongRetainRelease.swift)
16+
SimplifyStrongRetainRelease.swift
17+
SimplifyStructExtract.swift
18+
SimplifyUncheckedEnumData.swift)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//===--- SimplifyApply.swift ----------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 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 ApplyInst : OnoneSimplifyable {
16+
func simplify(_ context: SimplifyContext) {
17+
tryReplaceTrivialApplyOfPartialApply(context)
18+
}
19+
}
20+
21+
private extension ApplyInst {
22+
func tryReplaceTrivialApplyOfPartialApply(_ context: SimplifyContext) {
23+
guard let pa = callee as? PartialApplyInst else {
24+
return
25+
}
26+
27+
if pa.referencedFunction == nil {
28+
return
29+
}
30+
31+
// Currently we don't handle generic closures. For Onone this is good enough.
32+
// TODO: handle it once we replace the SILCombine simplification with this.
33+
if !allArgumentsAreTrivial(arguments) {
34+
return
35+
}
36+
37+
if !allArgumentsAreTrivial(pa.arguments) {
38+
return
39+
}
40+
41+
if !substitutionMap.isEmpty {
42+
return
43+
}
44+
45+
let allArgs = Array<Value>(arguments) + Array<Value>(pa.arguments)
46+
let builder = Builder(before: self, context)
47+
let newApply = builder.createApply(function: pa.callee, pa.substitutionMap, arguments: allArgs,
48+
isNonThrowing: isNonThrowing, isNonAsync: isNonAsync,
49+
specializationInfo: specializationInfo)
50+
uses.replaceAll(with: newApply, context)
51+
context.erase(instruction: self)
52+
53+
if context.tryDeleteDeadClosure(closure: pa) {
54+
context.notifyInvalidatedStackNesting()
55+
}
56+
}
57+
}
58+
59+
private func allArgumentsAreTrivial(_ args: LazyMapSequence<OperandArray, Value>) -> Bool {
60+
return !args.contains { !$0.hasTrivialType }
61+
}

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBeginCOWMutation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import SIL
1414

15-
extension BeginCOWMutationInst : SILCombineSimplifyable {
15+
extension BeginCOWMutationInst : Simplifyable, SILCombineSimplifyable {
1616
func simplify(_ context: SimplifyContext) {
1717

1818
/// The buffer of an empty Array/Set/Dictionary singleton is known to be not

0 commit comments

Comments
 (0)