Skip to content

Commit 2f27c1c

Browse files
author
Robert Marsh
committed
C++: further optimization of overlap computation
1 parent 1f17cfb commit 2f27c1c

File tree

1 file changed

+30
-18
lines changed
  • cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal

1 file changed

+30
-18
lines changed

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

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -232,15 +232,17 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
232232
/*
233233
* The following predicates compute the overlap relation between `VariableMemoryLocation`s in the
234234
* same `VirtualVariable` as follows:
235-
* 1. Compute the set of offsets within each virtual variable in `isRelevantOffset` (linear in
235+
* 1. In `isRelevantOffset`, compute the set of offsets within each virtual variable (linear in
236236
* the number of VMLs)
237-
* 2. Compute the set of offsets that each VML with known start and end offsets covers in
238-
* `isCoveredOffset` (this is currently quadratic in the number of VMLs in a VVar, but
239-
* could be optimized further. The quadratic portion is never materialized, and it seems to
240-
* be performant in practice)
241-
* 3. In `getVariableMemoryLocationOverlap`, compute the set of overlapping pairs of VMLs using a
237+
* 2. In `isCoveredOffset`, rank the offsets within each virtual variable (linear in the number
238+
* of VMLs)
239+
* 3. In `isCoveredOffset`, compute the set of ranks that each VML with known start and end
240+
* offsets covers (linear in the size of the overlap set)
241+
* 4. In `overlappingVariableMemoryLocations`, compute the set of overlapping pairs of VMLs using a
242242
* join on `isCoveredOffset` (linear in the size of the overlap set)
243-
* 4. In `getVariableMemoryLocationOverlap`, compute the precise overlap relation for each
243+
* 5. In `overlappingIRVariableMemoryLocations`, restrict to only the pairs that share an
244+
* `IRVariable` (linear in the size of the overlap set)
245+
* 5. In `getVariableMemoryLocationOverlap`, compute the precise overlap relation for each
244246
* overlapping pair of VMLs (linear in the size of the overlap set)
245247
*/
246248
private predicate isRelevantOffset(VirtualVariable vv, IntValue offset) {
@@ -258,12 +260,14 @@ private predicate isRelatableMemoryLocation(VariableMemoryLocation vml) {
258260
vml.getStartBitOffset() != Ints::unknown()
259261
}
260262

261-
private predicate isCoveredOffset(VariableMemoryLocation vml, VirtualVariable vv, IntValue offset) {
262-
isRelevantOffset(vv, offset) and
263-
vv = vml.getVirtualVariable() and
264-
isRelatableMemoryLocation(vml) and
265-
vml.getStartBitOffset() <= offset and
266-
offset <= vml.getEndBitOffset()
263+
private predicate isCoveredOffset(VariableMemoryLocation vml, VirtualVariable vv, int offsetRank) {
264+
exists(int startRank, int endRank |
265+
vml.getStartBitOffset() = rank[startRank](IntValue offset_ | isRelevantOffset(vv, offset_)) and
266+
vml.getEndBitOffset() = rank[endRank](IntValue offset_ | isRelevantOffset(vv, offset_)) and
267+
vv = vml.getVirtualVariable() and
268+
isRelatableMemoryLocation(vml) and
269+
offsetRank in [startRank .. endRank]
270+
)
267271
}
268272

269273
private predicate hasUnknownOffset(VariableMemoryLocation vml, VirtualVariable vv) {
@@ -274,18 +278,26 @@ private predicate hasUnknownOffset(VariableMemoryLocation vml, VirtualVariable v
274278
)
275279
}
276280

277-
private Overlap getVariableMemoryLocationOverlap(VariableMemoryLocation def, VariableMemoryLocation use) {
278-
def.getVariable() = use.getVariable() and
279-
(
280-
exists(VirtualVariable vv, IntValue offset | isCoveredOffset(def, vv, offset) and isCoveredOffset(use, vv, offset))
281+
private predicate overlappingVariableMemoryLocations(VariableMemoryLocation def, VariableMemoryLocation use) {
282+
exists(VirtualVariable vv, int offsetRank | isCoveredOffset(def, vv, offsetRank) and isCoveredOffset(use, vv, offsetRank))
281283
or
282284
hasUnknownOffset(def, use.getVirtualVariable())
283285
or
284286
hasUnknownOffset(use, def.getVirtualVariable())
285-
) and
287+
}
288+
289+
pragma[noopt] // Internal ticket: QL-937
290+
private predicate overlappingIRVariableMemoryLocations(VariableMemoryLocation def, VariableMemoryLocation use) {
291+
overlappingVariableMemoryLocations(def, use) and
292+
def.getVariable() = use.getVariable()
293+
}
294+
295+
private Overlap getVariableMemoryLocationOverlap(VariableMemoryLocation def, VariableMemoryLocation use) {
296+
overlappingIRVariableMemoryLocations(def, use) and
286297
result = Interval::getOverlap(def.getStartBitOffset(), def.getEndBitOffset(), use.getStartBitOffset(), use.getEndBitOffset())
287298
}
288299

300+
289301
MemoryLocation getResultMemoryLocation(Instruction instr) {
290302
exists(MemoryAccessKind kind |
291303
kind = instr.getResultMemoryAccess() and

0 commit comments

Comments
 (0)