Skip to content

Commit 42bbe18

Browse files
committed
AccessUtils: add AccessBase.isEqual and AccessPath.isEqualOrOverlaps
Also add `Value.referenceRoot`
1 parent 908d7b8 commit 42bbe18

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/AccessUtils.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,29 @@ enum AccessBase : CustomStringConvertible, Hashable {
162162
}
163163
}
164164

165+
// Returns true if it's guaranteed that this access has the same base address as the `other` access.
166+
func isEqual(to other: AccessBase) -> Bool {
167+
switch (self, other) {
168+
case (.box(let pb1), .box(let pb2)):
169+
return pb1.box.referenceRoot == pb2.box.referenceRoot
170+
case (.class(let rea1), .class(let rea2)):
171+
return rea1.fieldIndex == rea2.fieldIndex &&
172+
rea1.instance.referenceRoot == rea2.instance.referenceRoot
173+
case (.stack(let as1), .stack(let as2)):
174+
return as1 == as2
175+
case (.global(let gl1), .global(let gl2)):
176+
return gl1 == gl2
177+
case (.argument(let arg1), .argument(let arg2)):
178+
return arg1 == arg2
179+
case (.yield(let ba1), .yield(let ba2)):
180+
return ba1 == ba2
181+
case (.pointer(let p1), .pointer(let p2)):
182+
return p1 == p2
183+
default:
184+
return false
185+
}
186+
}
187+
165188
/// Returns `true` if the two access bases do not alias.
166189
func isDistinct(from other: AccessBase) -> Bool {
167190

@@ -251,6 +274,13 @@ struct AccessPath : CustomStringConvertible {
251274
}
252275
return false
253276
}
277+
278+
func isEqualOrOverlaps(_ other: AccessPath) -> Bool {
279+
return base.isEqual(to: other.base) &&
280+
// Note: an access with a smaller path overlaps an access with larger path, e.g.
281+
// `s0` overlaps `s0.s1`
282+
projectionPath.isSubPath(of: other.projectionPath)
283+
}
254284
}
255285

256286
private func canBeOperandOfIndexAddr(_ value: Value) -> Bool {
@@ -449,6 +479,25 @@ extension Value {
449479
}
450480
return .base(walker.result.base)
451481
}
482+
483+
/// The root definition of a reference, obtained by skipping casts, etc.
484+
var referenceRoot: Value {
485+
var value: Value = self
486+
while true {
487+
switch value {
488+
case is BeginBorrowInst, is CopyValueInst, is MoveValueInst,
489+
is UpcastInst, is UncheckedRefCastInst, is EndCOWMutationInst:
490+
value = (value as! Instruction).operands[0].value
491+
case let mvr as MultipleValueInstructionResult:
492+
guard let bcm = mvr.parentInstruction as? BeginCOWMutationInst else {
493+
return value
494+
}
495+
value = bcm.instance
496+
default:
497+
return value
498+
}
499+
}
500+
}
452501
}
453502

454503
/// A ValueUseDef walker that that visits access storage paths of an address.

0 commit comments

Comments
 (0)