Skip to content

Commit 1fdce43

Browse files
Merge pull request #1587 from rdmarsh2/rdmarsh/cpp/ir-overlap-speedup
C++: improve performance of overlap computation
2 parents 81b78dc + 1f17cfb commit 1fdce43

File tree

1 file changed

+67
-15
lines changed
  • cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal

1 file changed

+67
-15
lines changed

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

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -182,35 +182,30 @@ class UnknownVirtualVariable extends TUnknownVirtualVariable, VirtualVariable {
182182

183183
Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
184184
// The def and the use must have the same virtual variable, or no overlap is possible.
185-
def.getVirtualVariable() = use.getVirtualVariable() and
186185
(
187186
// An UnknownVirtualVariable must totally overlap any location within the same virtual variable.
188-
def instanceof UnknownVirtualVariable and result instanceof MustTotallyOverlap or
187+
def.getVirtualVariable() = use.getVirtualVariable() and
188+
def instanceof UnknownVirtualVariable and result instanceof MustTotallyOverlap
189+
or
189190
// An UnknownMemoryLocation may partially overlap any Location within the same virtual variable.
190-
def instanceof UnknownMemoryLocation and result instanceof MayPartiallyOverlap or
191+
def.getVirtualVariable() = use.getVirtualVariable() and
192+
def instanceof UnknownMemoryLocation and result instanceof MayPartiallyOverlap
193+
or
191194
exists(VariableMemoryLocation defVariableLocation |
192195
defVariableLocation = def and
193196
(
194197
(
195198
// A VariableMemoryLocation may partially overlap an unknown location within the same virtual variable.
199+
def.getVirtualVariable() = use.getVirtualVariable() and
196200
((use instanceof UnknownMemoryLocation) or (use instanceof UnknownVirtualVariable)) and
197201
result instanceof MayPartiallyOverlap
198202
) or
199203
// A VariableMemoryLocation overlaps another location within the same variable based on the relationship
200204
// of the two offset intervals.
201-
exists(VariableMemoryLocation useVariableLocation, IntValue defStartOffset, IntValue defEndOffset,
202-
IntValue useStartOffset, IntValue useEndOffset, Overlap intervalOverlap |
203-
useVariableLocation = use and
204-
// The def and use must access the same `IRVariable`.
205-
defVariableLocation.getVariable() = useVariableLocation.getVariable() and
206-
// The def and use intervals must overlap.
207-
defStartOffset = defVariableLocation.getStartBitOffset() and
208-
defEndOffset = defVariableLocation.getEndBitOffset() and
209-
useStartOffset = useVariableLocation.getStartBitOffset() and
210-
useEndOffset = useVariableLocation.getEndBitOffset() and
211-
intervalOverlap = Interval::getOverlap(defStartOffset, defEndOffset, useStartOffset, useEndOffset) and
205+
exists(Overlap intervalOverlap |
206+
intervalOverlap = getVariableMemoryLocationOverlap(def, use) and
212207
if intervalOverlap instanceof MustExactlyOverlap then (
213-
if defVariableLocation.getType() = useVariableLocation.getType() then (
208+
if def.getType() = use.getType() then (
214209
// The def and use types match, so it's an exact overlap.
215210
result instanceof MustExactlyOverlap
216211
)
@@ -234,6 +229,63 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
234229
)
235230
}
236231

232+
/*
233+
* The following predicates compute the overlap relation between `VariableMemoryLocation`s in the
234+
* same `VirtualVariable` as follows:
235+
* 1. Compute the set of offsets within each virtual variable in `isRelevantOffset` (linear in
236+
* 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
242+
* join on `isCoveredOffset` (linear in the size of the overlap set)
243+
* 4. In `getVariableMemoryLocationOverlap`, compute the precise overlap relation for each
244+
* overlapping pair of VMLs (linear in the size of the overlap set)
245+
*/
246+
private predicate isRelevantOffset(VirtualVariable vv, IntValue offset) {
247+
exists(VariableMemoryLocation ml |
248+
ml.getVirtualVariable() = vv
249+
|
250+
ml.getStartBitOffset() = offset
251+
or
252+
ml.getEndBitOffset() = offset
253+
)
254+
}
255+
256+
private predicate isRelatableMemoryLocation(VariableMemoryLocation vml) {
257+
vml.getEndBitOffset() != Ints::unknown() and
258+
vml.getStartBitOffset() != Ints::unknown()
259+
}
260+
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()
267+
}
268+
269+
private predicate hasUnknownOffset(VariableMemoryLocation vml, VirtualVariable vv) {
270+
vml.getVirtualVariable() = vv and
271+
(
272+
vml.getStartBitOffset() = Ints::unknown() or
273+
vml.getEndBitOffset() = Ints::unknown()
274+
)
275+
}
276+
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+
or
282+
hasUnknownOffset(def, use.getVirtualVariable())
283+
or
284+
hasUnknownOffset(use, def.getVirtualVariable())
285+
) and
286+
result = Interval::getOverlap(def.getStartBitOffset(), def.getEndBitOffset(), use.getStartBitOffset(), use.getEndBitOffset())
287+
}
288+
237289
MemoryLocation getResultMemoryLocation(Instruction instr) {
238290
exists(MemoryAccessKind kind |
239291
kind = instr.getResultMemoryAccess() and

0 commit comments

Comments
 (0)