C++: Fix overlappingVariableMemoryLocations perf

The `overlappingVariableMemoryLocations` predicate was a helper
predicate introduced to fix a join-order issue in
`overlappingIRVariableMemoryLocations`. Unfortunately it caused a
performance issue of its own because it could grow too large. On the
small project (38MB zip) awslabs/s2n there were 181M rows in
`overlappingVariableMemoryLocations`, and it took 134s to evaluate.

The fix is to collapse the two predicates into one and fix join ordering
by including an extra column in the predicates being joined.

In addition, some parameters were reordered to avoid the overhead of
auto-generated `join_rhs` predicates.

Tuple counts of `overlappingVariableMemoryLocations` before:

    623285    ~176%     {2} r1 = JOIN AliasedSSA::isCoveredOffset#fff_120#join_rhs AS L WITH AliasedSSA::isCoveredOffset#fff_120#join_rhs AS R ON FIRST 2 OUTPUT L.<2>, R.<2>
    119138    ~3%       {2} r2 = SCAN AliasedSSA::VariableMemoryLocation::getVirtualVariable_dispred#ff AS I OUTPUT I.<1>, I.<0>
    172192346 ~0%       {2} r3 = JOIN r2 WITH AliasedSSA::hasUnknownOffset#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, r2.<1>
    172815631 ~0%       {2} r4 = r1 \/ r3
    172192346 ~0%       {2} r5 = JOIN r2 WITH AliasedSSA::hasUnknownOffset#ff_10#join_rhs AS R ON FIRST 1 OUTPUT r2.<1>, R.<1>
    345007977 ~87%      {2} r6 = r4 \/ r5
                        return r6

Tuple counts of `overlappingIRVariableMemoryLocations` after:

    117021 ~134%     {2} r1 = JOIN AliasedSSA::isCoveredOffset#ffff AS L WITH AliasedSSA::isCoveredOffset#ffff AS R ON FIRST 3 OUTPUT L.<3>, R.<3>
    201486 ~1%       {2} r2 = JOIN AliasedSSA::hasUnknownOffset#fff AS L WITH AliasedSSA::hasVariableAndVirtualVariable#fff AS R ON FIRST 2 OUTPUT L.<2>, R.<2>
    318507 ~26%      {2} r3 = r1 \/ r2
    201486 ~3%       {2} r4 = JOIN AliasedSSA::hasUnknownOffset#fff AS L WITH AliasedSSA::hasVariableAndVirtualVariable#fff AS R ON FIRST 2 OUTPUT R.<2>, L.<2>
    519993 ~92%      {2} r5 = r3 \/ r4
                     return r5
This commit is contained in:
Jonas Jensen
2019-12-27 15:41:42 +01:00
parent 7e84453ec9
commit 4830e43b3e

View File

@@ -401,43 +401,50 @@ private predicate isRelatableMemoryLocation(VariableMemoryLocation vml) {
vml.getStartBitOffset() != Ints::unknown()
}
private predicate isCoveredOffset(VariableMemoryLocation vml, VirtualVariable vv, int offsetRank) {
private predicate isCoveredOffset(
VirtualVariable vv, IRVariable var, int offsetRank, VariableMemoryLocation vml
) {
exists(int startRank, int endRank |
vml.getStartBitOffset() = rank[startRank](IntValue offset_ | isRelevantOffset(vv, offset_)) and
vml.getEndBitOffset() = rank[endRank](IntValue offset_ | isRelevantOffset(vv, offset_)) and
vv = vml.getVirtualVariable() and
hasVariableAndVirtualVariable(vv, var, vml) and
isRelatableMemoryLocation(vml) and
offsetRank in [startRank .. endRank]
)
}
private predicate hasUnknownOffset(VariableMemoryLocation vml, VirtualVariable vv) {
vml.getVirtualVariable() = vv and
private predicate hasUnknownOffset(VirtualVariable vv, IRVariable var, VariableMemoryLocation vml) {
hasVariableAndVirtualVariable(vv, var, vml) and
(
vml.getStartBitOffset() = Ints::unknown() or
vml.getEndBitOffset() = Ints::unknown()
)
}
private predicate overlappingVariableMemoryLocations(
VariableMemoryLocation def, VariableMemoryLocation use
private predicate hasVariableAndVirtualVariable(
VirtualVariable vv, IRVariable var, VariableMemoryLocation vml
) {
exists(VirtualVariable vv, int offsetRank |
isCoveredOffset(def, vv, offsetRank) and isCoveredOffset(use, vv, offsetRank)
)
or
hasUnknownOffset(def, use.getVirtualVariable())
or
hasUnknownOffset(use, def.getVirtualVariable())
var = vml.getVariable() and
vv = vml.getVirtualVariable()
}
// Internal ticket: QL-937
pragma[noopt]
private predicate overlappingIRVariableMemoryLocations(
VariableMemoryLocation def, VariableMemoryLocation use
) {
overlappingVariableMemoryLocations(def, use) and
def.getVariable() = use.getVariable()
exists(VirtualVariable vv, IRVariable var, int offsetRank |
isCoveredOffset(vv, var, offsetRank, def) and
isCoveredOffset(vv, var, offsetRank, use)
)
or
exists(VirtualVariable vv, IRVariable var |
hasUnknownOffset(vv, var, def) and
hasVariableAndVirtualVariable(vv, var, use)
)
or
exists(VirtualVariable vv, IRVariable var |
hasUnknownOffset(vv, var, use) and
hasVariableAndVirtualVariable(vv, var, def)
)
}
private Overlap getVariableMemoryLocationOverlap(