Skip to content

Commit 2a604e2

Browse files
authored
Merge pull request #68814 from atrick/blockarg
SwiftCompilerSources: Replace BlockArgument with Phi and TermResult.
2 parents 6ed46be + a5d8aaf commit 2a604e2

File tree

11 files changed

+104
-57
lines changed

11 files changed

+104
-57
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ObjCBridgingOptimization.swift

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,11 @@ private func optimizeNonOptionalBridging(_ apply: ApplyInst,
211211

212212
// In the some-case just forward the original NSString.
213213
let objCType = emptyObjCValue.type
214-
let forwardedValue = someBlock.addBlockArgument(type: objCType, ownership: .owned, context)
214+
let forwardedValue = someBlock.addArgument(type: objCType, ownership: .owned, context)
215215
let someBuilder = Builder(atEndOf: someBlock, location: bridgeToSwiftCall.location, context)
216216
someBuilder.createBranch(to: continueBlock, arguments: [forwardedValue])
217217

218-
let s = continueBlock.addBlockArgument(type: objCType, ownership: .owned, context)
218+
let s = continueBlock.addArgument(type: objCType, ownership: .owned, context)
219219

220220
// Now replace the bridged value with the original value in the destination block.
221221
let replacement = s.makeAvailable(in: bridgeToObjcCall.parentBlock, context)
@@ -272,16 +272,13 @@ private func lookThroughOwnershipInsts(_ value: Value) -> Value {
272272
/// continue_bb(%value): // passed value
273273
/// ```
274274
private func isOptionalBridging(of value: Value, isBridging: (Value) -> ApplyInst?) -> SwitchEnumInst? {
275-
guard let arg = value as? BlockArgument,
276-
arg.isPhiArgument else {
277-
return nil
278-
}
275+
guard let phi = Phi(value) else { return nil }
279276

280277
var noneSwitch: SwitchEnumInst?
281278
var someSwitch: SwitchEnumInst?
282279

283280
// Check if one incoming value is the none-case and the other is the some-case.
284-
for incomingVal in arg.incomingPhiValues {
281+
for incomingVal in phi.incomingValues {
285282
// In both branches, the result must be an `enum` which is passed to the
286283
// continue_bb's phi-argument.
287284
guard let enumInst = incomingVal as? EnumInst,
@@ -338,10 +335,9 @@ private func isOptionalBridging(of value: Value, isBridging: (Value) -> ApplyIns
338335
/// Returns the `switch_enum` together with the enum case index, if `value` is
339336
/// the payload block argument of the `switch_enum`.
340337
private func isPayloadOfSwitchEnum(_ value: Value) -> (SwitchEnumInst, case: Int)? {
341-
if let payloadArg = value as? BlockArgument,
342-
let pred = payloadArg.parentBlock.singlePredecessor,
343-
let se = pred.terminator as? SwitchEnumInst,
344-
let caseIdx = se.getUniqueCase(forSuccessor: payloadArg.parentBlock) {
338+
if let payloadArg = TerminatorResult(value),
339+
let se = payloadArg.terminator as? SwitchEnumInst,
340+
let caseIdx = se.getUniqueCase(forSuccessor: payloadArg.successor) {
345341
return (se, caseIdx)
346342
}
347343
return nil

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ private struct ComputeOuterBlockrange : EscapeVisitorWithResult {
267267
// instructions (for which the `visitUse` closure is not called).
268268
result.insert(operandsDefinitionBlock)
269269

270-
// We need to explicitly add predecessor blocks of phi-arguments becaues they
270+
// We need to explicitly add predecessor blocks of phis becaues they
271271
// are not necesesarily visited during the down-walk in `isEscaping()`.
272272
// This is important for the special case where there is a back-edge from the
273273
// inner range to the inner rage's begin-block:
@@ -278,8 +278,8 @@ private struct ComputeOuterBlockrange : EscapeVisitorWithResult {
278278
// %k = alloc_ref $Klass // innerInstRange.begin
279279
// cond_br bb2, bb1(%k) // back-edge to bb1 == innerInstRange.blockRange.begin
280280
//
281-
if value is BlockArgument {
282-
result.insert(contentsOf: operandsDefinitionBlock.predecessors)
281+
if let phi = Phi(value) {
282+
result.insert(contentsOf: phi.predecessors)
283283
}
284284
return .continueWalk
285285
}

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyRefCasts.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ private extension UnaryInstruction {
111111
private func insertCompensatingInstructions(for inst: Instruction, in failureBlock: BasicBlock, _ context: SimplifyContext) {
112112
assert(failureBlock.arguments.count == 1)
113113
let sourceValue = inst.operands[0].value
114-
let newArg = failureBlock.addBlockArgument(type: sourceValue.type, ownership: sourceValue.ownership, context)
114+
let newArg = failureBlock.addArgument(type: sourceValue.type, ownership: sourceValue.ownership, context)
115115
let builder = Builder(atBeginOf: failureBlock, context)
116116
let newInst: SingleValueInstruction
117117
switch inst {

SwiftCompilerSources/Sources/Optimizer/PassManager/Context.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,9 +400,9 @@ extension Undef {
400400
}
401401

402402
extension BasicBlock {
403-
func addBlockArgument(type: Type, ownership: Ownership, _ context: some MutatingContext) -> BlockArgument {
403+
func addArgument(type: Type, ownership: Ownership, _ context: some MutatingContext) -> Argument {
404404
context.notifyInstructionsChanged()
405-
return bridged.addBlockArgument(type.bridged, ownership._bridged).blockArgument
405+
return bridged.addBlockArgument(type.bridged, ownership._bridged).argument
406406
}
407407

408408
func eraseArgument(at index: Int, _ context: some MutatingContext) {

SwiftCompilerSources/Sources/Optimizer/TestPasses/SILPrinter.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ func runSILPrinter(function: Function, context: FunctionPassContext) {
2929
for use in arg.uses {
3030
print(" user: \(use.instruction)")
3131
}
32-
if let blockArg = arg as? BlockArgument, blockArg.isPhiArgument {
33-
for incoming in blockArg.incomingPhiValues {
32+
if let phi = Phi(arg) {
33+
for incoming in phi.incomingValues {
3434
print(" incoming: \(incoming)")
3535
}
3636
}

SwiftCompilerSources/Sources/Optimizer/Utilities/AccessUtils.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,8 @@ extension PointerToAddressInst {
389389

390390
mutating func walkUp(value: Value, path: SmallProjectionPath) -> WalkResult {
391391
switch value {
392-
case is BlockArgument, is MarkDependenceInst, is CopyValueInst,
393-
is StructExtractInst, is TupleExtractInst, is StructInst, is TupleInst,
394-
is FunctionArgument, is AddressToPointerInst:
392+
case is Argument, is MarkDependenceInst, is CopyValueInst,
393+
is StructExtractInst, is TupleExtractInst, is StructInst, is TupleInst, is AddressToPointerInst:
395394
return walkUpDefault(value: value, path: path)
396395
default:
397396
return .abortWalk

SwiftCompilerSources/Sources/Optimizer/Utilities/EscapeUtils.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -680,11 +680,11 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
680680
return cachedWalkDown(addressOrValue: def, path: path.with(knownType: def.type))
681681
case is AllocBoxInst:
682682
return cachedWalkDown(addressOrValue: def, path: path.with(knownType: nil))
683-
case let arg as BlockArgument:
684-
let block = arg.parentBlock
685-
switch block.singlePredecessor!.terminator {
683+
case let arg as Argument:
684+
guard let termResult = TerminatorResult(arg) else { return isEscaping }
685+
switch termResult.terminator {
686686
case let ta as TryApplyInst:
687-
if block != ta.normalBlock { return isEscaping }
687+
if termResult.successor != ta.normalBlock { return isEscaping }
688688
return walkUpApplyResult(apply: ta, path: path.with(knownType: nil))
689689
default:
690690
return isEscaping

SwiftCompilerSources/Sources/Optimizer/Utilities/WalkUtils.swift

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,9 @@ extension ValueUseDefWalker {
673673
is BeginDeallocRefInst,
674674
is RefToBridgeObjectInst, is BridgeObjectToRefInst, is MarkUnresolvedNonCopyableValueInst:
675675
return walkUp(value: (def as! Instruction).operands[0].value, path: path)
676-
case let arg as BlockArgument:
677-
if arg.isPhiArgument {
678-
for incoming in arg.incomingPhiValues {
676+
case let arg as Argument:
677+
if let phi = Phi(arg) {
678+
for incoming in phi.incomingValues {
679679
// Check the cache to avoid cycles in the walk
680680
if let path = walkUpCache.needWalk(for: incoming, path: path) {
681681
if walkUp(value: incoming, path: path) == .abortWalk {
@@ -685,14 +685,13 @@ extension ValueUseDefWalker {
685685
}
686686
return .continueWalk
687687
}
688-
689-
let block = arg.parentBlock
690-
if let pred = block.singlePredecessor,
691-
let se = pred.terminator as? SwitchEnumInst,
692-
let caseIdx = se.getUniqueCase(forSuccessor: block) {
693-
return walkUp(value: se.enumOp, path: path.push(.enumCase, index: caseIdx))
688+
if let termResult = TerminatorResult(arg) {
689+
let pred = termResult.predecessor
690+
if let se = pred.terminator as? SwitchEnumInst,
691+
let caseIdx = se.getUniqueCase(forSuccessor: termResult.successor) {
692+
return walkUp(value: se.enumOp, path: path.push(.enumCase, index: caseIdx))
693+
}
694694
}
695-
696695
return rootDef(value: def, path: path)
697696
default:
698697
return rootDef(value: def, path: path)

SwiftCompilerSources/Sources/SIL/Argument.swift

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,37 +52,91 @@ final public class FunctionArgument : Argument {
5252
}
5353
}
5454

55-
final public class BlockArgument : Argument {
56-
public var isPhiArgument: Bool {
57-
parentBlock.predecessors.allSatisfy {
58-
let term = $0.terminator
59-
return term is BranchInst || term is CondBranchInst
60-
}
55+
public struct Phi {
56+
public let value: Argument
57+
58+
// TODO: Remove the CondBr case. All passes avoid critical edges. It is only included here for compatibility with .sil tests that have not been migrated.
59+
public init?(_ value: Value) {
60+
guard let argument = value as? Argument else { return nil }
61+
var preds = argument.parentBlock.predecessors
62+
guard let pred = preds.next() else { return nil }
63+
let term = pred.terminator
64+
guard term is BranchInst || term is CondBranchInst else { return nil }
65+
self.value = argument
66+
}
67+
68+
public var predecessors: PredecessorList {
69+
return value.parentBlock.predecessors
6170
}
6271

63-
public var incomingPhiOperands: LazyMapSequence<PredecessorList, Operand> {
64-
assert(isPhiArgument)
65-
let idx = index
66-
return parentBlock.predecessors.lazy.map {
72+
public var successor: BasicBlock {
73+
return value.parentBlock
74+
}
75+
76+
public var incomingOperands: LazyMapSequence<PredecessorList, Operand> {
77+
let blockArgIdx = value.index
78+
return predecessors.lazy.map {
6779
switch $0.terminator {
6880
case let br as BranchInst:
69-
return br.operands[idx]
81+
return br.operands[blockArgIdx]
7082
case let condBr as CondBranchInst:
71-
if condBr.trueBlock == self.parentBlock {
72-
assert(condBr.falseBlock != self.parentBlock)
73-
return condBr.trueOperands[idx]
83+
if condBr.trueBlock == successor {
84+
assert(condBr.falseBlock != successor)
85+
return condBr.trueOperands[blockArgIdx]
7486
} else {
75-
assert(condBr.falseBlock == self.parentBlock)
76-
return condBr.falseOperands[idx]
87+
assert(condBr.falseBlock == successor)
88+
return condBr.falseOperands[blockArgIdx]
7789
}
7890
default:
7991
fatalError("wrong terminator for phi-argument")
8092
}
8193
}
8294
}
8395

84-
public var incomingPhiValues: LazyMapSequence<LazyMapSequence<PredecessorList, Operand>, Value> {
85-
incomingPhiOperands.lazy.map { $0.value }
96+
public var incomingValues: LazyMapSequence<LazyMapSequence<PredecessorList, Operand>, Value> {
97+
incomingOperands.lazy.map { $0.value }
98+
}
99+
100+
public static func ==(lhs: Phi, rhs: Phi) -> Bool {
101+
lhs.value === rhs.value
102+
}
103+
104+
public func hash(into hasher: inout Hasher) {
105+
value.hash(into: &hasher)
106+
}
107+
}
108+
109+
public struct TerminatorResult {
110+
public let value: Argument
111+
112+
public init?(_ value: Value) {
113+
guard let argument = value as? Argument else { return nil }
114+
var preds = argument.parentBlock.predecessors
115+
guard let pred = preds.next() else { return nil }
116+
let term = pred.terminator
117+
if term is BranchInst || term is CondBranchInst { return nil }
118+
self.value = argument
119+
}
120+
121+
public var terminator: TermInst {
122+
var preds = value.parentBlock.predecessors
123+
return preds.next()!.terminator
124+
}
125+
126+
public var predecessor: BasicBlock {
127+
return terminator.parentBlock
128+
}
129+
130+
public var successor: BasicBlock {
131+
return value.parentBlock
132+
}
133+
134+
public static func ==(lhs: TerminatorResult, rhs: TerminatorResult) -> Bool {
135+
lhs.value == rhs.value
136+
}
137+
138+
public func hash(into hasher: inout Hasher) {
139+
value.hash(into: &hasher)
86140
}
87141
}
88142

@@ -242,7 +296,6 @@ public enum ArgumentConvention {
242296

243297
extension BridgedArgument {
244298
public var argument: Argument { obj.getAs(Argument.self) }
245-
public var blockArgument: BlockArgument { obj.getAs(BlockArgument.self) }
246299
public var functionArgument: FunctionArgument { obj.getAs(FunctionArgument.self) }
247300
}
248301

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public func registerSILClasses() {
3636
register(PlaceholderValue.self)
3737

3838
register(FunctionArgument.self)
39-
register(BlockArgument.self)
39+
register(Argument.self)
4040

4141
register(StoreInst.self)
4242
register(StoreWeakInst.self)

0 commit comments

Comments
 (0)