Skip to content

Commit 98dc522

Browse files
Merge pull request #4551 from swiftwasm/main
[pull] swiftwasm from main
2 parents aeeb055 + d34d88d commit 98dc522

File tree

89 files changed

+2275
-1022
lines changed

Some content is hidden

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

89 files changed

+2275
-1022
lines changed

SwiftCompilerSources/Sources/Basic/Utils.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,30 @@
1212

1313
@_exported import BasicBridging
1414

15+
//===----------------------------------------------------------------------===//
16+
// StringRef
17+
//===----------------------------------------------------------------------===//
18+
19+
public struct StringRef : CustomStringConvertible, CustomReflectable {
20+
let _bridged : BridgedStringRef
21+
22+
public init(bridged: BridgedStringRef) { self._bridged = bridged }
23+
24+
public var string: String { _bridged.string }
25+
public var description: String { string }
26+
public var customMirror: Mirror { Mirror(self, children: []) }
27+
28+
public static func ==(lhs: StringRef, rhs: StaticString) -> Bool {
29+
let lhsBuffer = UnsafeBufferPointer<UInt8>(start: lhs._bridged.data, count: Int(lhs._bridged.length))
30+
return rhs.withUTF8Buffer { (rhsBuffer: UnsafeBufferPointer<UInt8>) in
31+
if lhsBuffer.count != rhsBuffer.count { return false }
32+
return lhsBuffer.elementsEqual(rhsBuffer, by: ==)
33+
}
34+
}
35+
36+
public static func !=(lhs: StringRef, rhs: StaticString) -> Bool { !(lhs == rhs) }
37+
}
38+
1539
//===----------------------------------------------------------------------===//
1640
// Bridging Utilities
1741
//===----------------------------------------------------------------------===//

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AssumeSingleThreaded.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ let assumeSingleThreadedPass = FunctionPass(
3333
for inst in block.instructions {
3434
guard let rcInst = inst as? RefCountingInst else { continue }
3535

36-
context.setAtomicity(of: rcInst, isAtomic: false)
36+
rcInst.setAtomicity(isAtomic: false, context)
3737
}
3838
}
3939
}

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ private extension EscapeInfo {
207207
var dominatingBlock = value.block
208208

209209
_ = isEscaping(object: value, visitUse: { op, _, _ in
210-
if let defBlock = op.value.definingBlock, defBlock.dominates(dominatingBlock, domTree) {
210+
let defBlock = op.value.definingBlock
211+
if defBlock.dominates(dominatingBlock, domTree) {
211212
dominatingBlock = defBlock
212213
}
213214
return .continueWalking
@@ -230,25 +231,25 @@ private extension EscapeInfo {
230231
outerBlockRange.insert(user.block)
231232

232233
let val = op.value
233-
if let defBlock = val.definingBlock {
234-
// Also insert the operand's definition. Otherwise we would miss allocation
235-
// instructions (for which the `visitUse` closure is not called).
236-
outerBlockRange.insert(defBlock)
237-
238-
// We need to explicitly add predecessor blocks of phi-arguments becaues they
239-
// are not necesesarily visited by `EscapeInfo.walkDown`.
240-
// This is important for the special case where there is a back-edge from the
241-
// inner range to the inner rage's begin-block:
242-
//
243-
// bb0: // <- need to be in the outer range
244-
// br bb1(%some_init_val)
245-
// bb1(%arg):
246-
// %k = alloc_ref $Klass // innerInstRange.begin
247-
// cond_br bb2, bb1(%k) // back-edge to bb1 == innerInstRange.blockRange.begin
248-
//
249-
if val is BlockArgument {
250-
outerBlockRange.insert(contentsOf: defBlock.predecessors)
251-
}
234+
let defBlock = val.definingBlock
235+
236+
// Also insert the operand's definition. Otherwise we would miss allocation
237+
// instructions (for which the `visitUse` closure is not called).
238+
outerBlockRange.insert(defBlock)
239+
240+
// We need to explicitly add predecessor blocks of phi-arguments becaues they
241+
// are not necesesarily visited by `EscapeInfo.walkDown`.
242+
// This is important for the special case where there is a back-edge from the
243+
// inner range to the inner rage's begin-block:
244+
//
245+
// bb0: // <- need to be in the outer range
246+
// br bb1(%some_init_val)
247+
// bb1(%arg):
248+
// %k = alloc_ref $Klass // innerInstRange.begin
249+
// cond_br bb2, bb1(%k) // back-edge to bb1 == innerInstRange.blockRange.begin
250+
//
251+
if val is BlockArgument {
252+
outerBlockRange.insert(contentsOf: defBlock.predecessors)
252253
}
253254
return .continueWalking
254255
})

SwiftCompilerSources/Sources/Optimizer/InstructionPasses/SimplifyBeginCOWMutation.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import Basic
1314
import SIL
1415

1516
/// Simplify begin_cow_mutation instructions.
@@ -66,7 +67,7 @@ private func optimizeEmptySingleton(_ beginCOW: BeginCOWMutationInst,
6667
}
6768
let builder = Builder(at: beginCOW, location: beginCOW.location, context)
6869
let zero = builder.createIntegerLiteral(0, type: beginCOW.uniquenessResult.type);
69-
context.replaceAllUses(of: beginCOW.uniquenessResult, with: zero)
70+
beginCOW.uniquenessResult.uses.replaceAll(with: zero, context)
7071
}
7172

7273
private func isEmptyCOWSingleton(_ value: Value) -> Bool {
@@ -102,7 +103,7 @@ private func optimizeEmptyBeginEndPair(_ beginCOW: BeginCOWMutationInst,
102103

103104
for use in buffer.nonDebugUses {
104105
let endCOW = use.instruction as! EndCOWMutationInst
105-
context.replaceAllUses(of: endCOW, with: beginCOW.operand)
106+
endCOW.uses.replaceAll(with: beginCOW.operand, context)
106107
context.erase(instruction: endCOW)
107108
}
108109
context.erase(instruction: beginCOW, .includingDebugUses)
@@ -121,7 +122,7 @@ private func optimizeEmptyEndBeginPair(_ beginCOW: BeginCOWMutationInst,
121122
return false
122123
}
123124

124-
context.replaceAllUses(of: beginCOW.bufferResult, with: endCOW.operand)
125+
beginCOW.bufferResult.uses.replaceAll(with: endCOW.operand, context)
125126
context.erase(instruction: beginCOW, .includingDebugUses)
126127
context.erase(instruction: endCOW, .includingDebugUses)
127128
return true

SwiftCompilerSources/Sources/Optimizer/InstructionPasses/SimplifyStrongRetainRelease.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ let simplifyStrongReleasePass = InstructionPass<StrongReleaseInst>(
5959
// release of the class, squish the conversion.
6060
if let ier = op as? InitExistentialRefInst {
6161
if ier.uses.isSingleUse {
62-
context.setOperand(of: release, at: 0, to: ier.operand)
62+
release.setOperand(at: 0, to: ier.operand, context)
6363
context.erase(instruction: ier)
6464
return
6565
}

SwiftCompilerSources/Sources/Optimizer/PassManager/CMakeLists.txt

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

99
swift_compiler_sources(Optimizer
10-
PassUtils.swift
10+
Passes.swift
11+
PassContext.swift
1112
PassRegistration.swift)
1213

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
//===--- PassContext.swift - defines the PassContext type -----------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 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+
import OptimizerBridging
15+
16+
public typealias BridgedFunctionPassCtxt =
17+
OptimizerBridging.BridgedFunctionPassCtxt
18+
public typealias BridgedInstructionPassCtxt =
19+
OptimizerBridging.BridgedInstructionPassCtxt
20+
21+
struct PassContext {
22+
23+
let _bridged: BridgedPassContext
24+
25+
func continueWithNextSubpassRun(for inst: Instruction? = nil) -> Bool {
26+
let bridgedInst = OptionalBridgedInstruction(obj: inst?.bridged.obj)
27+
return PassContext_continueWithNextSubpassRun(_bridged, bridgedInst) != 0
28+
}
29+
30+
//===--------------------------------------------------------------------===//
31+
// Analysis
32+
//===--------------------------------------------------------------------===//
33+
34+
var aliasAnalysis: AliasAnalysis {
35+
let bridgedAA = PassContext_getAliasAnalysis(_bridged)
36+
return AliasAnalysis(bridged: bridgedAA)
37+
}
38+
39+
var calleeAnalysis: CalleeAnalysis {
40+
let bridgeCA = PassContext_getCalleeAnalysis(_bridged)
41+
return CalleeAnalysis(bridged: bridgeCA)
42+
}
43+
44+
var deadEndBlocks: DeadEndBlocksAnalysis {
45+
let bridgeDEA = PassContext_getDeadEndBlocksAnalysis(_bridged)
46+
return DeadEndBlocksAnalysis(bridged: bridgeDEA)
47+
}
48+
49+
var dominatorTree: DominatorTree {
50+
let bridgedDT = PassContext_getDomTree(_bridged)
51+
return DominatorTree(bridged: bridgedDT)
52+
}
53+
54+
var postDominatorTree: PostDominatorTree {
55+
let bridgedPDT = PassContext_getPostDomTree(_bridged)
56+
return PostDominatorTree(bridged: bridgedPDT)
57+
}
58+
59+
//===--------------------------------------------------------------------===//
60+
// Interaction with AST and the SIL module
61+
//===--------------------------------------------------------------------===//
62+
63+
func getContextSubstitutionMap(for type: Type) -> SubstitutionMap {
64+
SubstitutionMap(PassContext_getContextSubstitutionMap(_bridged, type.bridged))
65+
}
66+
67+
func loadFunction(name: StaticString) -> Function? {
68+
return name.withUTF8Buffer { (nameBuffer: UnsafeBufferPointer<UInt8>) in
69+
PassContext_loadFunction(_bridged, BridgedStringRef(data: nameBuffer.baseAddress, length: nameBuffer.count)).function
70+
}
71+
}
72+
73+
//===--------------------------------------------------------------------===//
74+
// Modify SIL
75+
//===--------------------------------------------------------------------===//
76+
77+
/// Splits the basic block, which contains `inst`, before `inst` and returns the
78+
/// new block.
79+
///
80+
/// `inst` and all subsequent instructions are moved to the new block, while all
81+
/// instructions _before_ `inst` remain in the original block.
82+
func splitBlock(at inst: Instruction) -> BasicBlock {
83+
notifyBranchesChanged()
84+
return PassContext_splitBlock(inst.bridged).block
85+
}
86+
87+
enum EraseMode {
88+
case onlyInstruction, includingDebugUses
89+
}
90+
91+
func erase(instruction: Instruction, _ mode: EraseMode = .onlyInstruction) {
92+
switch mode {
93+
case .onlyInstruction:
94+
break
95+
case .includingDebugUses:
96+
for result in instruction.results {
97+
for use in result.uses {
98+
assert(use.instruction is DebugValueInst)
99+
PassContext_eraseInstruction(_bridged, use.instruction.bridged)
100+
}
101+
}
102+
}
103+
104+
if instruction is FullApplySite {
105+
notifyCallsChanged()
106+
}
107+
if instruction is TermInst {
108+
notifyBranchesChanged()
109+
}
110+
notifyInstructionsChanged()
111+
112+
PassContext_eraseInstruction(_bridged, instruction.bridged)
113+
}
114+
115+
func fixStackNesting(function: Function) {
116+
PassContext_fixStackNesting(_bridged, function.bridged)
117+
}
118+
119+
func modifyEffects(in function: Function, _ body: (inout FunctionEffects) -> ()) {
120+
function._modifyEffects(body)
121+
// TODO: do we need to notify any changes?
122+
}
123+
124+
//===--------------------------------------------------------------------===//
125+
// Private utilities
126+
//===--------------------------------------------------------------------===//
127+
128+
fileprivate func notifyInstructionsChanged() {
129+
PassContext_notifyChanges(_bridged, instructionsChanged)
130+
}
131+
132+
fileprivate func notifyCallsChanged() {
133+
PassContext_notifyChanges(_bridged, callsChanged)
134+
}
135+
136+
fileprivate func notifyBranchesChanged() {
137+
PassContext_notifyChanges(_bridged, branchesChanged)
138+
}
139+
}
140+
141+
//===----------------------------------------------------------------------===//
142+
// Builder initialization
143+
//===----------------------------------------------------------------------===//
144+
145+
extension Builder {
146+
/// Creates a builder which inserts _before_ `insPnt`, using a custom `location`.
147+
init(at insPnt: Instruction, location: Location, _ context: PassContext) {
148+
self.init(insertAt: .before(insPnt), location: location, passContext: context._bridged)
149+
}
150+
151+
/// Creates a builder which inserts _before_ `insPnt`, using the location of `insPnt`.
152+
init(at insPnt: Instruction, _ context: PassContext) {
153+
self.init(insertAt: .before(insPnt), location: insPnt.location, passContext: context._bridged)
154+
}
155+
156+
/// Creates a builder which inserts _after_ `insPnt`, using the location of `insPnt`.
157+
init(after insPnt: Instruction, _ context: PassContext) {
158+
if let nextInst = insPnt.next {
159+
self.init(insertAt: .before(nextInst), location: insPnt.location, passContext: context._bridged)
160+
} else {
161+
self.init(insertAt: .atEndOf(insPnt.block), location: insPnt.location, passContext: context._bridged)
162+
}
163+
}
164+
165+
/// Creates a builder which inserts at the end of `block`, using a custom `location`.
166+
init(atEndOf block: BasicBlock, location: Location, _ context: PassContext) {
167+
self.init(insertAt: .atEndOf(block), location: location, passContext: context._bridged)
168+
}
169+
170+
/// Creates a builder which inserts at the begin of `block`, using the location of the first
171+
/// instruction of `block`.
172+
init(atBeginOf block: BasicBlock, _ context: PassContext) {
173+
let firstInst = block.instructions.first!
174+
self.init(insertAt: .before(firstInst), location: firstInst.location, passContext: context._bridged)
175+
}
176+
}
177+
178+
//===----------------------------------------------------------------------===//
179+
// Modifying the SIL
180+
//===----------------------------------------------------------------------===//
181+
182+
extension BasicBlock {
183+
func addBlockArgument(type: Type, ownership: Ownership, _ context: PassContext) -> BlockArgument {
184+
context.notifyInstructionsChanged()
185+
return SILBasicBlock_addBlockArgument(bridged, type.bridged, ownership._bridged).blockArgument
186+
}
187+
188+
func eraseArgument(at index: Int, _ context: PassContext) {
189+
context.notifyInstructionsChanged()
190+
SILBasicBlock_eraseArgument(bridged, index)
191+
}
192+
}
193+
194+
extension AllocRefInstBase {
195+
func setIsStackAllocatable(_ context: PassContext) {
196+
context.notifyInstructionsChanged()
197+
AllocRefInstBase_setIsStackAllocatable(bridged)
198+
}
199+
}
200+
201+
extension UseList {
202+
func replaceAll(with replacement: Value, _ context: PassContext) {
203+
for use in self {
204+
use.instruction.setOperand(at: use.index, to: replacement, context)
205+
}
206+
}
207+
}
208+
209+
extension Instruction {
210+
func setOperand(at index : Int, to value: Value, _ context: PassContext) {
211+
if self is FullApplySite && index == ApplyOperands.calleeOperandIndex {
212+
context.notifyCallsChanged()
213+
}
214+
context.notifyInstructionsChanged()
215+
216+
SILInstruction_setOperand(bridged, index, value.bridged)
217+
}
218+
}
219+
220+
extension RefCountingInst {
221+
func setAtomicity(isAtomic: Bool, _ context: PassContext) {
222+
context.notifyInstructionsChanged()
223+
RefCountingInst_setIsAtomic(bridged, isAtomic)
224+
}
225+
}

0 commit comments

Comments
 (0)