mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
SIL: streamline Operand Sequence APIs
* remove `filterUsers(ofType:)`, because it's a duplication of `users(ofType:)`
* rename `filterUses(ofType:)` -> `filter(usersOfType:)`
* rename `ignoreUses(ofType:)` -> `ignore(usersOfType:)`
* rename `getSingleUser` -> `singleUser`
* implement `singleUse` with `Sequence.singleElement`
* implement `ignoreDebugUses` with `ignore(usersOfType:)`
This is a follow-up of eb1d5f484c.
This commit is contained in:
@@ -363,7 +363,7 @@ private func createAllocStack(for allocBox: AllocBoxInst, flags: Flags, _ contex
|
||||
isLexical: flags.isLexical,
|
||||
isFromVarDecl: flags.isFromVarDecl)
|
||||
let stackLocation: Value
|
||||
if let mu = allocBox.uses.getSingleUser(ofType: MarkUninitializedInst.self) {
|
||||
if let mu = allocBox.uses.singleUser(ofType: MarkUninitializedInst.self) {
|
||||
stackLocation = builder.createMarkUninitialized(value: asi, kind: mu.kind)
|
||||
} else {
|
||||
stackLocation = asi
|
||||
@@ -484,7 +484,7 @@ private func hoistMarkUnresolvedInsts(stackAddress: Value,
|
||||
builder = Builder(atBeginOf: stackAddress.parentBlock, context)
|
||||
}
|
||||
let mu = builder.createMarkUnresolvedNonCopyableValue(value: stackAddress, checkKind: checkKind, isStrict: false)
|
||||
stackAddress.uses.ignore(user: mu).ignoreDebugUses.ignoreUses(ofType: DeallocStackInst.self)
|
||||
stackAddress.uses.ignore(user: mu).ignoreDebugUses.ignore(usersOfType: DeallocStackInst.self)
|
||||
.replaceAll(with: mu, context)
|
||||
}
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ private func rewritePartialApply(_ partialApply: PartialApplyInst, withSpecializ
|
||||
// leave the key path itself out of the dependency chain, and introduce dependencies on those
|
||||
// operands instead, so that the key path object itself can be made dead.
|
||||
for md in newClosure.uses.users(ofType: MarkDependenceInst.self) {
|
||||
if md.base.uses.getSingleUser(ofType: PartialApplyInst.self) == partialApply {
|
||||
if md.base.uses.singleUser(ofType: PartialApplyInst.self) == partialApply {
|
||||
md.replace(with: newClosure, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ let destroyHoisting = FunctionPass(name: "destroy-hoisting") {
|
||||
private func optimize(value: Value, _ context: FunctionPassContext) {
|
||||
guard value.ownership == .owned,
|
||||
// Avoid all the analysis effort if there are no destroys to hoist.
|
||||
!value.uses.filterUses(ofType: DestroyValueInst.self).isEmpty
|
||||
!value.uses.filter(usersOfType: DestroyValueInst.self).isEmpty
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -478,7 +478,7 @@ private struct InitValueBuilder: AddressDefUseWalker {
|
||||
case .PrepareInitialization:
|
||||
return .continueWalk
|
||||
case .AddressOfRawLayout:
|
||||
if let addr2Ptr = bi.uses.getSingleUser(ofType: PointerToAddressInst.self) {
|
||||
if let addr2Ptr = bi.uses.singleUser(ofType: PointerToAddressInst.self) {
|
||||
return walkDownUses(ofAddress: addr2Ptr, path: path)
|
||||
}
|
||||
return .abortWalk
|
||||
|
||||
@@ -83,7 +83,7 @@ private func tryEliminate(copy: CopyLikeInstruction, keepDebugInfo: Bool, _ cont
|
||||
removeDestroys(of: allocStack, context)
|
||||
}
|
||||
|
||||
allocStack.uses.ignoreUses(ofType: DeallocStackInst.self).replaceAll(with: copy.sourceAddress, context)
|
||||
allocStack.uses.ignore(usersOfType: DeallocStackInst.self).replaceAll(with: copy.sourceAddress, context)
|
||||
|
||||
if keepDebugInfo {
|
||||
Builder(before: copy, context).createDebugStep()
|
||||
@@ -247,7 +247,7 @@ private extension AllocStackInst {
|
||||
var liferange = InstructionRange(begin: self, context)
|
||||
defer { liferange.deinitialize() }
|
||||
|
||||
liferange.insert(contentsOf: uses.ignoreUses(ofType: DeallocStackInst.self).lazy.map { $0.instruction })
|
||||
liferange.insert(contentsOf: uses.ignore(usersOfType: DeallocStackInst.self).lazy.map { $0.instruction })
|
||||
|
||||
for use in uses {
|
||||
switch use.instruction {
|
||||
|
||||
@@ -207,7 +207,7 @@ private extension AllocStackInst {
|
||||
iea.replace(with: newAlloc, context)
|
||||
}
|
||||
case let oea as OpenExistentialAddrInst:
|
||||
assert(oea.uses.ignoreUses(ofType: DestroyAddrInst.self).isEmpty)
|
||||
assert(oea.uses.ignore(usersOfType: DestroyAddrInst.self).isEmpty)
|
||||
oea.replace(with: newAlloc, context)
|
||||
case let cab as CheckedCastAddrBranchInst:
|
||||
let builder = Builder(before: cab, context)
|
||||
@@ -247,7 +247,7 @@ private extension AllocStackInst {
|
||||
is DebugValueInst:
|
||||
break
|
||||
case let oea as OpenExistentialAddrInst:
|
||||
if !oea.uses.ignoreUses(ofType: DestroyAddrInst.self).isEmpty {
|
||||
if !oea.uses.ignore(usersOfType: DestroyAddrInst.self).isEmpty {
|
||||
return nil
|
||||
}
|
||||
case let iea as InitExistentialAddrInst:
|
||||
|
||||
@@ -29,7 +29,7 @@ extension BeginBorrowInst : OnoneSimplifiable, SILCombineSimplifiable {
|
||||
|
||||
extension LoadBorrowInst : Simplifiable, SILCombineSimplifiable {
|
||||
func simplify(_ context: SimplifyContext) {
|
||||
if uses.ignoreDebugUses.ignoreUses(ofType: EndBorrowInst.self).isEmpty {
|
||||
if uses.ignoreDebugUses.ignore(usersOfType: EndBorrowInst.self).isEmpty {
|
||||
context.erase(instructionIncludingAllUsers: self)
|
||||
return
|
||||
}
|
||||
@@ -52,7 +52,7 @@ extension LoadBorrowInst : Simplifiable, SILCombineSimplifiable {
|
||||
|
||||
private func tryCombineWithCopy(_ context: SimplifyContext) {
|
||||
let forwardedValue = lookThroughSingleForwardingUses()
|
||||
guard let singleUser = forwardedValue.uses.ignoreUses(ofType: EndBorrowInst.self).singleUse?.instruction,
|
||||
guard let singleUser = forwardedValue.uses.ignore(usersOfType: EndBorrowInst.self).singleUse?.instruction,
|
||||
let copy = singleUser as? CopyValueInst,
|
||||
copy.parentBlock == self.parentBlock else {
|
||||
return
|
||||
@@ -81,13 +81,13 @@ private func tryReplaceBorrowWithOwnedOperand(beginBorrow: BeginBorrowInst, _ co
|
||||
private func removeBorrowOfThinFunction(beginBorrow: BeginBorrowInst, _ context: SimplifyContext) {
|
||||
guard let thin2thickFn = beginBorrow.borrowedValue as? ThinToThickFunctionInst,
|
||||
// For simplicity don't go into the trouble of removing reborrow phi arguments.
|
||||
beginBorrow.uses.filterUses(ofType: BranchInst.self).isEmpty else
|
||||
beginBorrow.uses.filter(usersOfType: BranchInst.self).isEmpty else
|
||||
{
|
||||
return
|
||||
}
|
||||
// `thin_to_thick_function` has "none" ownership and is compatible with guaranteed values.
|
||||
// Therefore the `begin_borrow` is not needed.
|
||||
beginBorrow.uses.ignoreUses(ofType: EndBorrowInst.self).replaceAll(with: thin2thickFn, context)
|
||||
beginBorrow.uses.ignore(usersOfType: EndBorrowInst.self).replaceAll(with: thin2thickFn, context)
|
||||
context.erase(instructionIncludingAllUsers: beginBorrow)
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ private func tryReplaceCopy(
|
||||
withCopiedOperandOf beginBorrow: BeginBorrowInst,
|
||||
_ context: SimplifyContext
|
||||
) -> Bool {
|
||||
guard let singleUser = forwardedValue.uses.ignoreUses(ofType: EndBorrowInst.self).singleUse?.instruction,
|
||||
guard let singleUser = forwardedValue.uses.ignore(usersOfType: EndBorrowInst.self).singleUse?.instruction,
|
||||
let copy = singleUser as? CopyValueInst,
|
||||
copy.parentBlock == beginBorrow.parentBlock else {
|
||||
return false
|
||||
@@ -153,7 +153,7 @@ private extension Value {
|
||||
/// ```
|
||||
/// Returns self if this value has no uses which are ForwardingInstructions.
|
||||
func lookThroughSingleForwardingUses() -> Value {
|
||||
if let singleUse = uses.ignoreUses(ofType: EndBorrowInst.self).singleUse,
|
||||
if let singleUse = uses.ignore(usersOfType: EndBorrowInst.self).singleUse,
|
||||
let fwdInst = singleUse.instruction as? (SingleValueInstruction & ForwardingInstruction),
|
||||
fwdInst.canConvertToOwned,
|
||||
fwdInst.isSingleForwardedOperand(singleUse),
|
||||
@@ -165,17 +165,17 @@ private extension Value {
|
||||
}
|
||||
|
||||
var allUsesCanBeConvertedToOwned: Bool {
|
||||
let relevantUses = uses.ignoreUses(ofType: EndBorrowInst.self)
|
||||
let relevantUses = uses.ignore(usersOfType: EndBorrowInst.self)
|
||||
return relevantUses.allSatisfy { $0.canAccept(ownership: .owned) }
|
||||
}
|
||||
|
||||
func isDestroyed(after nonDestroyUser: Instruction) -> Bool {
|
||||
return uses.getSingleUser(notOfType: DestroyValueInst.self) == nonDestroyUser &&
|
||||
return uses.singleUser(notOfType: DestroyValueInst.self) == nonDestroyUser &&
|
||||
nonDestroyUser.dominates(destroysOf: self)
|
||||
}
|
||||
|
||||
func replaceAllDestroys(with replacement: Value, _ context: SimplifyContext) {
|
||||
uses.filterUses(ofType: DestroyValueInst.self).replaceAll(with: replacement, context)
|
||||
uses.filter(usersOfType: DestroyValueInst.self).replaceAll(with: replacement, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ private extension Instruction {
|
||||
// The value and instruction are in the same block. All uses are dominated by both.
|
||||
return true
|
||||
}
|
||||
let destroys = value.uses.filterUses(ofType: DestroyValueInst.self)
|
||||
let destroys = value.uses.filter(usersOfType: DestroyValueInst.self)
|
||||
return destroys.allSatisfy({ $0.instruction.parentBlock == parentBlock})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,7 +406,7 @@ private extension Value {
|
||||
// var p = Point(x: 10, y: 20)
|
||||
// let o = UnsafePointer(&p)
|
||||
// Therefore ignore the `end_access` use of a `begin_access`.
|
||||
let relevantUses = singleUseValue.uses.ignoreDebugUses.ignoreUses(ofType: EndAccessInst.self)
|
||||
let relevantUses = singleUseValue.uses.ignoreDebugUses.ignore(usersOfType: EndAccessInst.self)
|
||||
|
||||
guard let use = relevantUses.singleUse else {
|
||||
return nil
|
||||
|
||||
@@ -361,7 +361,7 @@ private struct StackProtectionOptimization {
|
||||
let builder = Builder(after: beginAccess, location: beginAccess.location.asAutoGenerated, context)
|
||||
let temporary = builder.createAllocStack(beginAccess.type)
|
||||
|
||||
beginAccess.uses.ignoreUses(ofType: EndAccessInst.self).replaceAll(with: temporary, context)
|
||||
beginAccess.uses.ignore(usersOfType: EndAccessInst.self).replaceAll(with: temporary, context)
|
||||
|
||||
for endAccess in beginAccess.endInstructions {
|
||||
let endBuilder = Builder(before: endAccess, location: endAccess.location.asAutoGenerated, context)
|
||||
|
||||
@@ -432,7 +432,7 @@ extension Instruction {
|
||||
case .USubOver:
|
||||
// Handle StringObjectOr(tuple_extract(usub_with_overflow(x, offset)), bits)
|
||||
// This pattern appears in UTF8 String literal construction.
|
||||
if let tei = bi.uses.getSingleUser(ofType: TupleExtractInst.self),
|
||||
if let tei = bi.uses.singleUser(ofType: TupleExtractInst.self),
|
||||
tei.isResultOfOffsetSubtract {
|
||||
return true
|
||||
}
|
||||
@@ -446,7 +446,7 @@ extension Instruction {
|
||||
// Handle StringObjectOr(tuple_extract(usub_with_overflow(x, offset)), bits)
|
||||
// This pattern appears in UTF8 String literal construction.
|
||||
if tei.isResultOfOffsetSubtract,
|
||||
let bi = tei.uses.getSingleUser(ofType: BuiltinInst.self),
|
||||
let bi = tei.uses.singleUser(ofType: BuiltinInst.self),
|
||||
bi.id == .StringObjectOr {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -717,7 +717,7 @@ extension InteriorUseWalker: AddressUseVisitor {
|
||||
if handleInner(borrowed: sb) == .abortWalk {
|
||||
return .abortWalk
|
||||
}
|
||||
return sb.uses.filterUses(ofType: EndBorrowInst.self).walk {
|
||||
return sb.uses.filter(usersOfType: EndBorrowInst.self).walk {
|
||||
useVisitor($0)
|
||||
}
|
||||
case let load as LoadBorrowInst:
|
||||
|
||||
@@ -143,16 +143,7 @@ extension Sequence where Element == Operand {
|
||||
self.lazy.map { $0.value }
|
||||
}
|
||||
|
||||
public var singleUse: Operand? {
|
||||
var result: Operand? = nil
|
||||
for op in self {
|
||||
if result != nil {
|
||||
return nil
|
||||
}
|
||||
result = op
|
||||
}
|
||||
return result
|
||||
}
|
||||
public var singleUse: Operand? { singleElement }
|
||||
|
||||
public var isSingleUse: Bool { singleUse != nil }
|
||||
|
||||
@@ -161,18 +152,14 @@ extension Sequence where Element == Operand {
|
||||
}
|
||||
|
||||
public var ignoreDebugUses: LazyFilterSequence<Self> {
|
||||
self.lazy.filter { !($0.instruction is DebugValueInst) }
|
||||
ignore(usersOfType: DebugValueInst.self)
|
||||
}
|
||||
|
||||
public func filterUses<I: Instruction>(ofType: I.Type) -> LazyFilterSequence<Self> {
|
||||
public func filter<I: Instruction>(usersOfType: I.Type) -> LazyFilterSequence<Self> {
|
||||
self.lazy.filter { $0.instruction is I }
|
||||
}
|
||||
|
||||
public func filterUsers<I: Instruction>(ofType: I.Type) -> LazyMapSequence<LazyFilterSequence<Self>, I> {
|
||||
self.lazy.filter { $0.instruction is I }.lazy.map { $0.instruction as! I }
|
||||
}
|
||||
|
||||
public func ignoreUses<I: Instruction>(ofType: I.Type) -> LazyFilterSequence<Self> {
|
||||
public func ignore<I: Instruction>(usersOfType: I.Type) -> LazyFilterSequence<Self> {
|
||||
self.lazy.filter { !($0.instruction is I) }
|
||||
}
|
||||
|
||||
@@ -180,12 +167,12 @@ extension Sequence where Element == Operand {
|
||||
self.lazy.filter { !($0.instruction == user) }
|
||||
}
|
||||
|
||||
public func getSingleUser<I: Instruction>(ofType: I.Type) -> I? {
|
||||
filterUses(ofType: I.self).singleUse?.instruction as? I
|
||||
public func singleUser<I: Instruction>(ofType: I.Type) -> I? {
|
||||
filter(usersOfType: I.self).singleUse?.instruction as? I
|
||||
}
|
||||
|
||||
public func getSingleUser<I: Instruction>(notOfType: I.Type) -> Instruction? {
|
||||
ignoreUses(ofType: I.self).singleUse?.instruction
|
||||
public func singleUser<I: Instruction>(notOfType: I.Type) -> Instruction? {
|
||||
ignore(usersOfType: I.self).singleUse?.instruction
|
||||
}
|
||||
|
||||
public var endingLifetime: LazyFilterSequence<Self> {
|
||||
|
||||
@@ -300,7 +300,7 @@ public enum BorrowingInstruction : CustomStringConvertible, Hashable {
|
||||
extension BorrowingInstruction {
|
||||
private func visitEndBorrows(value: Value, _ context: Context, _ visitor: @escaping (Operand) -> WalkResult)
|
||||
-> WalkResult {
|
||||
return value.lookThroughBorrowedFromUser.uses.filterUses(ofType: EndBorrowInst.self).walk {
|
||||
return value.lookThroughBorrowedFromUser.uses.filter(usersOfType: EndBorrowInst.self).walk {
|
||||
visitor($0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ private func createEmptyBorrowedFrom(for phi: Phi, _ context: some MutatingConte
|
||||
}
|
||||
let builder = Builder(atBeginOf: phi.value.parentBlock, context)
|
||||
let bfi = builder.createBorrowedFrom(borrowedValue: phi.value, enclosingValues: [])
|
||||
phi.value.uses.ignoreUses(ofType: BorrowedFromInst.self).replaceAll(with: bfi, context)
|
||||
phi.value.uses.ignore(usersOfType: BorrowedFromInst.self).replaceAll(with: bfi, context)
|
||||
}
|
||||
|
||||
/// Replaces a phi with the unique incoming value if all incoming values are the same:
|
||||
|
||||
Reference in New Issue
Block a user