@@ -162,6 +162,29 @@ enum AccessBase : CustomStringConvertible, Hashable {
162
162
}
163
163
}
164
164
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
+
165
188
/// Returns `true` if the two access bases do not alias.
166
189
func isDistinct( from other: AccessBase ) -> Bool {
167
190
@@ -251,6 +274,13 @@ struct AccessPath : CustomStringConvertible {
251
274
}
252
275
return false
253
276
}
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
+ }
254
284
}
255
285
256
286
private func canBeOperandOfIndexAddr( _ value: Value ) -> Bool {
@@ -449,6 +479,25 @@ extension Value {
449
479
}
450
480
return . base( walker. result. base)
451
481
}
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
+ }
452
501
}
453
502
454
503
/// A ValueUseDef walker that that visits access storage paths of an address.
0 commit comments