Skip to content

Commit b97f9d5

Browse files
Merge remote-tracking branch 'apple/main' into katei/merge-main-2022-11-03
2 parents af7b2ee + 60952b8 commit b97f9d5

File tree

959 files changed

+24891
-20755
lines changed

Some content is hidden

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

959 files changed

+24891
-20755
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ endif()
116116
if(SWIFT_HOST_VARIANT_ARCH)
117117
set(SWIFT_HOST_VARIANT_ARCH_default "${SWIFT_HOST_VARIANT_ARCH}")
118118
else()
119-
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
119+
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64")
120120
set(SWIFT_HOST_VARIANT_ARCH_default "x86_64")
121121
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64|arm64")
122122
if(SWIFT_HOST_VARIANT_SDK_default STREQUAL OSX)

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ to track the status of our builds, please refer to our [GitHub Actions page](htt
4545
|**[Ubuntu 20.04](https://github.com/apple/swift-community-hosted-continuous-integration/blob/main/nodes/wasm32_ubuntu_20.04.json)** | wasm32 |[![Build Status](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-20.04-webassembly/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-20.04-webassembly)|
4646
|**[Android](https://github.com/apple/swift-community-hosted-continuous-integration/blob/main/nodes/x86_64_ubuntu_16_04_LTS_android.json)** | ARMv7 |[![Build Status](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-16.04-android/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-16.04-android)|
4747
|**[Android](https://github.com/apple/swift-community-hosted-continuous-integration/blob/main/nodes/x86_64_ubuntu_16_04_LTS_android.json)** | AArch64 |[![Build Status](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-16.04-android-arm64/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-16.04-android-arm64)|
48-
|**[Windows 2019 (VS 2017)](https://github.com/apple/swift-community-hosted-continuous-integration/blob/main/nodes/x86_64_windows_2019.json)** | x86_64 | [![Build Status](https://ci-external.swift.org/job/oss-swift-windows-x86_64/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-windows-x86_64)|
4948
|**[Windows 2019 (VS 2019)](https://github.com/apple/swift-community-hosted-continuous-integration/blob/main/nodes/x86_64_windows_2019_VS2019.json)** | x86_64 | [![Build Status](https://ci-external.swift.org/job/oss-swift-windows-x86_64-vs2019/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-windows-x86_64-vs2019)|
5049

5150
## Welcome to Swift

SwiftCompilerSources/Sources/Optimizer/Analysis/AliasAnalysis.swift

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,148 @@ struct AliasAnalysis {
6060
// Any other non-address value means: all addresses of any referenced class instances within the value.
6161
return SmallProjectionPath(.anyValueFields).push(.anyClassField).push(.anyValueFields)
6262
}
63+
64+
static func register() {
65+
AliasAnalysis_register(
66+
// getMemEffectsFn
67+
{ (bridgedCtxt: BridgedPassContext, bridgedVal: BridgedValue, bridgedInst: BridgedInstruction) -> BridgedMemoryBehavior in
68+
let context = PassContext(_bridged: bridgedCtxt)
69+
let inst = bridgedInst.instruction
70+
let val = bridgedVal.value
71+
let path = AliasAnalysis.getPtrOrAddressPath(for: val)
72+
if let apply = inst as? ApplySite {
73+
let effect = getMemoryEffect(of: apply, for: val, path: path, context)
74+
switch (effect.read, effect.write) {
75+
case (false, false): return NoneBehavior
76+
case (true, false): return MayReadBehavior
77+
case (false, true): return MayWriteBehavior
78+
case (true, true): return MayReadWriteBehavior
79+
}
80+
}
81+
if val.at(path).isAddressEscaping(using: EscapesToInstructionVisitor(target: inst), context) {
82+
return MayReadWriteBehavior
83+
}
84+
return NoneBehavior
85+
},
86+
87+
// isObjReleasedFn
88+
{ (bridgedCtxt: BridgedPassContext, bridgedObj: BridgedValue, bridgedInst: BridgedInstruction) -> Bool in
89+
let context = PassContext(_bridged: bridgedCtxt)
90+
let inst = bridgedInst.instruction
91+
let obj = bridgedObj.value
92+
let path = SmallProjectionPath(.anyValueFields)
93+
if let apply = inst as? ApplySite {
94+
let effect = getOwnershipEffect(of: apply, for: obj, path: path, context)
95+
return effect.destroy
96+
}
97+
return obj.at(path).isEscaping(using: EscapesToInstructionVisitor(target: inst), context)
98+
},
99+
100+
// isAddrVisibleFromObj
101+
{ (bridgedCtxt: BridgedPassContext, bridgedAddr: BridgedValue, bridgedObj: BridgedValue) -> Bool in
102+
let context = PassContext(_bridged: bridgedCtxt)
103+
let addr = bridgedAddr.value.at(AliasAnalysis.getPtrOrAddressPath(for: bridgedAddr.value))
104+
105+
// This is similar to `canReferenceSameFieldFn`, except that all addresses of all objects are
106+
// considered which are transitively visible from `bridgedObj`.
107+
let anythingReachableFromObj = bridgedObj.value.at(SmallProjectionPath(.anything))
108+
return addr.canAddressAlias(with: anythingReachableFromObj, context)
109+
},
110+
111+
// canReferenceSameFieldFn
112+
{ (bridgedCtxt: BridgedPassContext, bridgedLhs: BridgedValue, bridgedRhs: BridgedValue) -> Bool in
113+
let context = PassContext(_bridged: bridgedCtxt)
114+
115+
// If `lhs` or `rhs` is not an address, but an object, it means: check for alias of any class
116+
// field address of the object.
117+
let lhs = bridgedLhs.value.at(AliasAnalysis.getPtrOrAddressPath(for: bridgedLhs.value))
118+
let rhs = bridgedRhs.value.at(AliasAnalysis.getPtrOrAddressPath(for: bridgedRhs.value))
119+
return lhs.canAddressAlias(with: rhs, context)
120+
}
121+
)
122+
}
123+
}
124+
125+
private func getMemoryEffect(of apply: ApplySite, for address: Value, path: SmallProjectionPath, _ context: PassContext) -> SideEffects.Memory {
126+
let calleeAnalysis = context.calleeAnalysis
127+
let visitor = SideEffectsVisitor(apply: apply, calleeAnalysis: calleeAnalysis)
128+
let memoryEffects: SideEffects.Memory
129+
130+
// First try to figure out to which argument(s) the address "escapes" to.
131+
if let result = address.at(path).visitAddress(using: visitor, context) {
132+
// The resulting effects are the argument effects to which `address` escapes to.
133+
memoryEffects = result.memory
134+
} else {
135+
// `address` has unknown escapes. So we have to take the global effects of the called function(s).
136+
memoryEffects = calleeAnalysis.getSideEffects(of: apply).memory
137+
}
138+
// Do some magic for `let` variables. Function calls cannot modify let variables.
139+
// The only exception is that the let variable is directly passed to an indirect out of the
140+
// apply.
141+
// TODO: make this a more formal and verified approach.
142+
if memoryEffects.write && address.accessBase.isLet && !address.isIndirectResult(of: apply) {
143+
return SideEffects.Memory(read: memoryEffects.read, write: false)
144+
}
145+
return memoryEffects
146+
}
147+
148+
private func getOwnershipEffect(of apply: ApplySite, for value: Value, path: SmallProjectionPath, _ context: PassContext) -> SideEffects.Ownership {
149+
let visitor = SideEffectsVisitor(apply: apply, calleeAnalysis: context.calleeAnalysis)
150+
if let result = value.at(path).visit(using: visitor, context) {
151+
// The resulting effects are the argument effects to which `value` escapes to.
152+
return result.ownership
153+
} else {
154+
// `value` has unknown escapes. So we have to take the global effects of the called function(s).
155+
return visitor.calleeAnalysis.getSideEffects(of: apply).ownership
156+
}
157+
}
158+
159+
private struct SideEffectsVisitor : EscapeVisitorWithResult {
160+
let apply: ApplySite
161+
let calleeAnalysis: CalleeAnalysis
162+
var result = SideEffects.GlobalEffects()
163+
164+
mutating func visitUse(operand: Operand, path: EscapePath) -> UseResult {
165+
let user = operand.instruction
166+
if user is ReturnInst {
167+
// Anything which is returned cannot escape to an instruction inside the function.
168+
return .ignore
169+
}
170+
if user == apply {
171+
if let argIdx = apply.argumentIndex(of: operand) {
172+
let e = calleeAnalysis.getSideEffects(of: apply, forArgument: argIdx, path: path.projectionPath)
173+
result.merge(with: e)
174+
}
175+
}
176+
return .continueWalk
177+
}
178+
}
179+
180+
private extension Value {
181+
/// Returns true if this address is passed as indirect out of `apply`.
182+
func isIndirectResult(of apply: ApplySite) -> Bool {
183+
guard let fullApply = apply as? FullApplySite else {
184+
return false
185+
}
186+
if fullApply.numIndirectResultArguments == 0 {
187+
return false
188+
}
189+
190+
var walker = IsIndirectResultWalker(apply: fullApply)
191+
return walker.walkDownUses(ofAddress: self, path: UnusedWalkingPath()) == .abortWalk
192+
}
193+
}
194+
195+
private struct IsIndirectResultWalker: AddressDefUseWalker {
196+
let apply: FullApplySite
197+
198+
mutating func leafUse(address: Operand, path: UnusedWalkingPath) -> WalkResult {
199+
if address.instruction == apply,
200+
let argIdx = apply.argumentIndex(of: address),
201+
argIdx < apply.numIndirectResultArguments {
202+
return .abortWalk
203+
}
204+
return .continueWalk
205+
}
63206
}
207+

SwiftCompilerSources/Sources/Optimizer/DataStructures/InstructionRange.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
9494
var isValid: Bool {
9595
blockRange.isValid &&
9696
// Check if there are any inserted instructions before the begin instruction in its block.
97-
!ReverseList(first: begin).dropFirst().contains { insertedInsts.contains($0) }
97+
!ReverseInstructionList(first: begin).dropFirst().contains { insertedInsts.contains($0) }
9898
}
9999

100100
/// Returns the end instructions.
@@ -115,7 +115,7 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
115115
/// Returns the interior instructions.
116116
var interiors: LazySequence<FlattenSequence<
117117
LazyMapSequence<Stack<BasicBlock>,
118-
LazyFilterSequence<ReverseList<Instruction>>>>> {
118+
LazyFilterSequence<ReverseInstructionList>>>> {
119119
blockRange.inserted.lazy.flatMap {
120120
var include = blockRange.contains($0)
121121
return $0.instructions.reversed().lazy.filter {

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,10 @@ private func registerSwiftPasses() {
7575
registerPass(deadEndBlockDumper, { deadEndBlockDumper.run($0) })
7676
registerPass(rangeDumper, { rangeDumper.run($0) })
7777
registerPass(runUnitTests, { runUnitTests.run($0) })
78+
registerPass(testInstructionIteration, { testInstructionIteration.run($0) })
7879
}
7980

8081
private func registerSwiftAnalyses() {
82+
AliasAnalysis.register()
8183
CalleeAnalysis.register()
8284
}

SwiftCompilerSources/Sources/Optimizer/TestPasses/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ swift_compiler_sources(Optimizer
1414
SILPrinter.swift
1515
RangeDumper.swift
1616
RunUnitTests.swift
17+
TestInstructionIteration.swift
1718
)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===--- TestInstructionIteration.swift -----------------------------------===//
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+
15+
/// Tests instruction iteration while modifying the instruction list.
16+
///
17+
/// This pass iterates over the instruction list of the function's block and performs
18+
/// modifications of the instruction list - mostly deleting instructions.
19+
/// Modifications are triggered by `string_literal` instructions with known "commands".
20+
/// E.g. if a
21+
/// ```
22+
/// %1 = string_literal utf8 "delete_strings"
23+
/// ```
24+
/// is encountered during the iteration, it triggers the deletion of all `string_literal`
25+
/// instructions of the basic block (including the current one).
26+
let testInstructionIteration = FunctionPass(name: "test-instruction-iteration") {
27+
(function: Function, context: PassContext) in
28+
29+
print("Test instruction iteration in \(function.name):")
30+
31+
let reverse = function.name.string.hasSuffix("backward")
32+
33+
for block in function.blocks {
34+
print("\(block.name):")
35+
let termLoc = block.terminator.location
36+
if reverse {
37+
for inst in block.instructions.reversed() {
38+
handle(instruction: inst, context)
39+
}
40+
} else {
41+
for inst in block.instructions {
42+
handle(instruction: inst, context)
43+
}
44+
}
45+
if block.instructions.isEmpty || !(block.instructions.reversed().first is TermInst) {
46+
let builder = Builder(atEndOf: block, location: termLoc, context)
47+
builder.createUnreachable()
48+
}
49+
}
50+
print("End function \(function.name):")
51+
}
52+
53+
private func handle(instruction: Instruction, _ context: PassContext) {
54+
print(instruction)
55+
if let sl = instruction as? StringLiteralInst {
56+
switch sl.string {
57+
case "delete_strings":
58+
deleteAllInstructions(ofType: StringLiteralInst.self, in: instruction.block, context)
59+
case "delete_ints":
60+
deleteAllInstructions(ofType: IntegerLiteralInst.self, in: instruction.block, context)
61+
case "delete_branches":
62+
deleteAllInstructions(ofType: BranchInst.self, in: instruction.block, context)
63+
case "split_block":
64+
_ = context.splitBlock(at: instruction)
65+
default:
66+
break
67+
}
68+
}
69+
}
70+
71+
private func deleteAllInstructions<InstType: Instruction>(ofType: InstType.Type, in block: BasicBlock, _ context: PassContext) {
72+
for inst in block.instructions {
73+
if inst is InstType {
74+
context.erase(instruction: inst)
75+
}
76+
}
77+
}

SwiftCompilerSources/Sources/SIL/Argument.swift

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,6 @@ public enum ArgumentConvention {
8686
/// object.
8787
case indirectIn
8888

89-
/// This argument is passed indirectly, i.e. by directly passing the address
90-
/// of an object in memory. The callee must treat the object as read-only
91-
/// The callee may assume that the address does not alias any valid object.
92-
case indirectInConstant
93-
9489
/// This argument is passed indirectly, i.e. by directly passing the address
9590
/// of an object in memory. The callee may not modify and does not destroy
9691
/// the object.
@@ -130,7 +125,7 @@ public enum ArgumentConvention {
130125

131126
public var isIndirect: Bool {
132127
switch self {
133-
case .indirectIn, .indirectInConstant, .indirectInGuaranteed,
128+
case .indirectIn, .indirectInGuaranteed,
134129
.indirectInout, .indirectInoutAliasable, .indirectOut:
135130
return true
136131
case .directOwned, .directUnowned, .directGuaranteed:
@@ -140,7 +135,7 @@ public enum ArgumentConvention {
140135

141136
public var isIndirectIn: Bool {
142137
switch self {
143-
case .indirectIn, .indirectInConstant, .indirectInGuaranteed:
138+
case .indirectIn, .indirectInGuaranteed:
144139
return true
145140
case .directOwned, .directUnowned, .directGuaranteed,
146141
.indirectInout, .indirectInoutAliasable, .indirectOut:
@@ -152,7 +147,7 @@ public enum ArgumentConvention {
152147
switch self {
153148
case .indirectInGuaranteed, .directGuaranteed:
154149
return true
155-
case .indirectIn, .indirectInConstant, .directOwned, .directUnowned,
150+
case .indirectIn, .directOwned, .directUnowned,
156151
.indirectInout, .indirectInoutAliasable, .indirectOut:
157152
return false
158153
}
@@ -161,7 +156,6 @@ public enum ArgumentConvention {
161156
public var isExclusiveIndirect: Bool {
162157
switch self {
163158
case .indirectIn,
164-
.indirectInConstant,
165159
.indirectOut,
166160
.indirectInGuaranteed,
167161
.indirectInout:
@@ -182,7 +176,6 @@ public enum ArgumentConvention {
182176
return true
183177

184178
case .indirectIn,
185-
.indirectInConstant,
186179
.indirectOut,
187180
.indirectInGuaranteed,
188181
.directUnowned,
@@ -205,7 +198,6 @@ extension BridgedArgumentConvention {
205198
var convention: ArgumentConvention {
206199
switch self {
207200
case ArgumentConvention_Indirect_In: return .indirectIn
208-
case ArgumentConvention_Indirect_In_Constant: return .indirectInConstant
209201
case ArgumentConvention_Indirect_In_Guaranteed: return .indirectInGuaranteed
210202
case ArgumentConvention_Indirect_Inout: return .indirectInout
211203
case ArgumentConvention_Indirect_InoutAliasable: return .indirectInoutAliasable

0 commit comments

Comments
 (0)