@@ -227,13 +227,15 @@ private newtype TMemoryLocation =
227227 TAllAliasedMemory ( IRFunction irFunc , Boolean isMayAccess )
228228
229229/**
230- * Represents the memory location accessed by a memory operand or memory result. In this implementation, the location is
230+ * A memory location accessed by a memory operand or memory result. In this implementation, the location is
231231 * one of the following:
232232 * - `VariableMemoryLocation` - A location within a known `IRVariable`, at an offset that is either a constant or is
233233 * unknown.
234234 * - `UnknownMemoryLocation` - A location not known to be within a specific `IRVariable`.
235+ *
236+ * Some of these memory locations will be filtered out for performance reasons before being passed to SSA construction.
235237 */
236- abstract class MemoryLocation extends TMemoryLocation {
238+ abstract private class MemoryLocation0 extends TMemoryLocation {
237239 final string toString ( ) {
238240 if this .isMayAccess ( )
239241 then result = "?" + this .toStringInternal ( )
@@ -294,9 +296,9 @@ abstract class MemoryLocation extends TMemoryLocation {
294296 * represented by a `MemoryLocation` that totally overlaps all other
295297 * `MemoryLocations` in the set.
296298 */
297- abstract class VirtualVariable extends MemoryLocation { }
299+ abstract class VirtualVariable extends MemoryLocation0 { }
298300
299- abstract class AllocationMemoryLocation extends MemoryLocation {
301+ abstract class AllocationMemoryLocation extends MemoryLocation0 {
300302 Allocation var ;
301303 boolean isMayAccess ;
302304
@@ -424,7 +426,7 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
424426 * `{a, b}` into a memory location that represents _all_ of the allocations
425427 * in the set.
426428 */
427- class GroupedMemoryLocation extends TGroupedMemoryLocation , MemoryLocation {
429+ class GroupedMemoryLocation extends TGroupedMemoryLocation , MemoryLocation0 {
428430 VariableGroup vg ;
429431 boolean isMayAccess ;
430432 boolean isAll ;
@@ -528,7 +530,7 @@ class GroupedVirtualVariable extends GroupedMemoryLocation, VirtualVariable {
528530/**
529531 * An access to memory that is not known to be confined to a specific `IRVariable`.
530532 */
531- class UnknownMemoryLocation extends TUnknownMemoryLocation , MemoryLocation {
533+ class UnknownMemoryLocation extends TUnknownMemoryLocation , MemoryLocation0 {
532534 IRFunction irFunc ;
533535 boolean isMayAccess ;
534536
@@ -555,7 +557,7 @@ class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation {
555557 * An access to memory that is not known to be confined to a specific `IRVariable`, but is known to
556558 * not access memory on the current function's stack frame.
557559 */
558- class AllNonLocalMemory extends TAllNonLocalMemory , MemoryLocation {
560+ class AllNonLocalMemory extends TAllNonLocalMemory , MemoryLocation0 {
559561 IRFunction irFunc ;
560562 boolean isMayAccess ;
561563
@@ -589,7 +591,7 @@ class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation {
589591/**
590592 * An access to all aliased memory.
591593 */
592- class AllAliasedMemory extends TAllAliasedMemory , MemoryLocation {
594+ class AllAliasedMemory extends TAllAliasedMemory , MemoryLocation0 {
593595 IRFunction irFunc ;
594596 boolean isMayAccess ;
595597
@@ -620,7 +622,7 @@ class AliasedVirtualVariable extends AllAliasedMemory, VirtualVariable {
620622/**
621623 * Gets the overlap relationship between the definition location `def` and the use location `use`.
622624 */
623- Overlap getOverlap ( MemoryLocation def , MemoryLocation use ) {
625+ Overlap getOverlap ( MemoryLocation0 def , MemoryLocation0 use ) {
624626 exists ( Overlap overlap |
625627 // Compute the overlap based only on the extent.
626628 overlap = getExtentOverlap ( def , use ) and
@@ -648,7 +650,7 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
648650 * based only on the set of memory locations accessed. Handling of "may" accesses and read-only
649651 * locations occurs in `getOverlap()`.
650652 */
651- private Overlap getExtentOverlap ( MemoryLocation def , MemoryLocation use ) {
653+ private Overlap getExtentOverlap ( MemoryLocation0 def , MemoryLocation0 use ) {
652654 // The def and the use must have the same virtual variable, or no overlap is possible.
653655 (
654656 // AllAliasedMemory must totally overlap any location within the same virtual variable.
@@ -861,6 +863,40 @@ predicate canReuseSsaForOldResult(Instruction instr) { OldSsa::canReuseSsaForMem
861863bindingset [ result , b]
862864private boolean unbindBool ( boolean b ) { result != b .booleanNot ( ) }
863865
866+ /** Gets the number of overlapping uses of `def`. */
867+ private int numberOfOverlappingUses ( MemoryLocation0 def ) {
868+ result = strictcount ( MemoryLocation0 use | exists ( getOverlap ( def , use ) ) )
869+ }
870+
871+ /**
872+ * Holds if `def` is a busy definition. That is, it has a large number of
873+ * overlapping uses.
874+ */
875+ private predicate isBusyDef ( MemoryLocation0 def ) { numberOfOverlappingUses ( def ) > 1024 }
876+
877+ /** Holds if `use` is a use that overlaps with a busy definition. */
878+ private predicate useOverlapWithBusyDef ( MemoryLocation0 use ) {
879+ exists ( MemoryLocation0 def |
880+ exists ( getOverlap ( def , use ) ) and
881+ isBusyDef ( def )
882+ )
883+ }
884+
885+ final private class FinalMemoryLocation = MemoryLocation0 ;
886+
887+ /**
888+ * A memory location accessed by a memory operand or memory result. In this implementation, the location is
889+ * one of the following:
890+ * - `VariableMemoryLocation` - A location within a known `IRVariable`, at an offset that is either a constant or is
891+ * unknown.
892+ * - `UnknownMemoryLocation` - A location not known to be within a specific `IRVariable`.
893+ *
894+ * Compared to `MemoryLocation0`, this class does not contain memory locations that represent uses of busy definitions.
895+ */
896+ class MemoryLocation extends FinalMemoryLocation {
897+ MemoryLocation ( ) { not useOverlapWithBusyDef ( this ) }
898+ }
899+
864900MemoryLocation getResultMemoryLocation ( Instruction instr ) {
865901 not canReuseSsaForOldResult ( instr ) and
866902 exists ( MemoryAccessKind kind , boolean isMayAccess |
@@ -905,9 +941,9 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
905941 )
906942}
907943
908- MemoryLocation getOperandMemoryLocation ( MemoryOperand operand ) {
944+ private MemoryLocation0 getOperandMemoryLocation0 ( MemoryOperand operand , boolean isMayAccess ) {
909945 not canReuseSsaForOldResult ( operand .getAnyDef ( ) ) and
910- exists ( MemoryAccessKind kind , boolean isMayAccess |
946+ exists ( MemoryAccessKind kind |
911947 kind = operand .getMemoryAccess ( ) and
912948 ( if operand .hasMayReadMemoryAccess ( ) then isMayAccess = true else isMayAccess = false ) and
913949 (
@@ -948,6 +984,19 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
948984 )
949985}
950986
987+ MemoryLocation getOperandMemoryLocation ( MemoryOperand operand ) {
988+ exists ( MemoryLocation0 use0 , boolean isMayAccess |
989+ use0 = getOperandMemoryLocation0 ( operand , isMayAccess )
990+ |
991+ result = use0
992+ or
993+ // If `use0` overlaps with a busy definition we turn it into a use
994+ // of `UnknownMemoryLocation`.
995+ not use0 instanceof MemoryLocation and
996+ result = TUnknownMemoryLocation ( operand .getEnclosingIRFunction ( ) , isMayAccess )
997+ )
998+ }
999+
9511000/** Gets the start bit offset of a `MemoryLocation`, if any. */
9521001int getStartBitOffset ( VariableMemoryLocation location ) {
9531002 result = location .getStartBitOffset ( ) and Ints:: hasValue ( result )
0 commit comments