Skip to content

Commit c0263be

Browse files
authored
Merge pull request #17062 from MathiasVP/speed-up-alias-analysis-4
C++: Speed up alias analysis
2 parents 6b68cf6 + 087b0da commit c0263be

File tree

6 files changed

+64693
-12
lines changed

6 files changed

+64693
-12
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Improved performance of alias analysis of large function bodies. In rare cases, alerts that depend on alias analysis of large function bodies may be affected.

cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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
861863
bindingset[result, b]
862864
private 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+
864900
MemoryLocation 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. */
9521001
int getStartBitOffset(VariableMemoryLocation location) {
9531002
result = location.getStartBitOffset() and Ints::hasValue(result)

0 commit comments

Comments
 (0)