@@ -232,8 +232,10 @@ private newtype TMemoryLocation =
232
232
* - `VariableMemoryLocation` - A location within a known `IRVariable`, at an offset that is either a constant or is
233
233
* unknown.
234
234
* - `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.
235
237
*/
236
- abstract class MemoryLocation extends TMemoryLocation {
238
+ abstract private class MemoryLocation0 extends TMemoryLocation {
237
239
final string toString ( ) {
238
240
if this .isMayAccess ( )
239
241
then result = "?" + this .toStringInternal ( )
@@ -294,9 +296,9 @@ abstract class MemoryLocation extends TMemoryLocation {
294
296
* represented by a `MemoryLocation` that totally overlaps all other
295
297
* `MemoryLocations` in the set.
296
298
*/
297
- abstract class VirtualVariable extends MemoryLocation { }
299
+ abstract class VirtualVariable extends MemoryLocation0 { }
298
300
299
- abstract class AllocationMemoryLocation extends MemoryLocation {
301
+ abstract class AllocationMemoryLocation extends MemoryLocation0 {
300
302
Allocation var ;
301
303
boolean isMayAccess ;
302
304
@@ -424,7 +426,7 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
424
426
* `{a, b}` into a memory location that represents _all_ of the allocations
425
427
* in the set.
426
428
*/
427
- class GroupedMemoryLocation extends TGroupedMemoryLocation , MemoryLocation {
429
+ class GroupedMemoryLocation extends TGroupedMemoryLocation , MemoryLocation0 {
428
430
VariableGroup vg ;
429
431
boolean isMayAccess ;
430
432
boolean isAll ;
@@ -528,7 +530,7 @@ class GroupedVirtualVariable extends GroupedMemoryLocation, VirtualVariable {
528
530
/**
529
531
* An access to memory that is not known to be confined to a specific `IRVariable`.
530
532
*/
531
- class UnknownMemoryLocation extends TUnknownMemoryLocation , MemoryLocation {
533
+ class UnknownMemoryLocation extends TUnknownMemoryLocation , MemoryLocation0 {
532
534
IRFunction irFunc ;
533
535
boolean isMayAccess ;
534
536
@@ -555,7 +557,7 @@ class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation {
555
557
* An access to memory that is not known to be confined to a specific `IRVariable`, but is known to
556
558
* not access memory on the current function's stack frame.
557
559
*/
558
- class AllNonLocalMemory extends TAllNonLocalMemory , MemoryLocation {
560
+ class AllNonLocalMemory extends TAllNonLocalMemory , MemoryLocation0 {
559
561
IRFunction irFunc ;
560
562
boolean isMayAccess ;
561
563
@@ -589,7 +591,7 @@ class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation {
589
591
/**
590
592
* An access to all aliased memory.
591
593
*/
592
- class AllAliasedMemory extends TAllAliasedMemory , MemoryLocation {
594
+ class AllAliasedMemory extends TAllAliasedMemory , MemoryLocation0 {
593
595
IRFunction irFunc ;
594
596
boolean isMayAccess ;
595
597
@@ -620,7 +622,7 @@ class AliasedVirtualVariable extends AllAliasedMemory, VirtualVariable {
620
622
/**
621
623
* Gets the overlap relationship between the definition location `def` and the use location `use`.
622
624
*/
623
- Overlap getOverlap ( MemoryLocation def , MemoryLocation use ) {
625
+ Overlap getOverlap ( MemoryLocation0 def , MemoryLocation0 use ) {
624
626
exists ( Overlap overlap |
625
627
// Compute the overlap based only on the extent.
626
628
overlap = getExtentOverlap ( def , use ) and
@@ -648,7 +650,7 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
648
650
* based only on the set of memory locations accessed. Handling of "may" accesses and read-only
649
651
* locations occurs in `getOverlap()`.
650
652
*/
651
- private Overlap getExtentOverlap ( MemoryLocation def , MemoryLocation use ) {
653
+ private Overlap getExtentOverlap ( MemoryLocation0 def , MemoryLocation0 use ) {
652
654
// The def and the use must have the same virtual variable, or no overlap is possible.
653
655
(
654
656
// AllAliasedMemory must totally overlap any location within the same virtual variable.
@@ -861,6 +863,40 @@ predicate canReuseSsaForOldResult(Instruction instr) { OldSsa::canReuseSsaForMem
861
863
bindingset [ result , b]
862
864
private boolean unbindBool ( boolean b ) { result != b .booleanNot ( ) }
863
865
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
+ * Represents the 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
+
864
900
MemoryLocation getResultMemoryLocation ( Instruction instr ) {
865
901
not canReuseSsaForOldResult ( instr ) and
866
902
exists ( MemoryAccessKind kind , boolean isMayAccess |
@@ -905,9 +941,9 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
905
941
)
906
942
}
907
943
908
- MemoryLocation getOperandMemoryLocation ( MemoryOperand operand ) {
944
+ private MemoryLocation0 getOperandMemoryLocation0 ( MemoryOperand operand , boolean isMayAccess ) {
909
945
not canReuseSsaForOldResult ( operand .getAnyDef ( ) ) and
910
- exists ( MemoryAccessKind kind , boolean isMayAccess |
946
+ exists ( MemoryAccessKind kind |
911
947
kind = operand .getMemoryAccess ( ) and
912
948
( if operand .hasMayReadMemoryAccess ( ) then isMayAccess = true else isMayAccess = false ) and
913
949
(
@@ -948,6 +984,19 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
948
984
)
949
985
}
950
986
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
+
951
1000
/** Gets the start bit offset of a `MemoryLocation`, if any. */
952
1001
int getStartBitOffset ( VariableMemoryLocation location ) {
953
1002
result = location .getStartBitOffset ( ) and Ints:: hasValue ( result )
0 commit comments