mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
C++: Fix join order of FlowVar::definedPartiallyAt
This predicate was very slow on kamailio/kamailio:
(696s) Tuple counts for FlowVar::FlowVar::definedPartiallyAt_dispred#ff:
703569 ~3% {3} r1 = SCAN FlowVar::FlowVar_internal::TBlockVar#fff AS I OUTPUT I.<1>, I.<0>, I.<2>
7679540588 ~3% {3} r2 = JOIN r1 WITH FlowVar::PartialDefinitions::PartialDefinition::partiallyDefines_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, r1.<1>, r1.<2>
567217 ~2% {2} r3 = JOIN r2 WITH project#FlowVar::PartialDefinitions::PartialDefinition#class#fff#2 AS R ON FIRST 2 OUTPUT r2.<2>, r2.<0>
return r3
After this change, the predicate takes no time at all:
(22s) Tuple counts for FlowVar::FlowVar::definedPartiallyAt_dispred#ff:
703569 ~3% {3} r1 = SCAN FlowVar::FlowVar_internal::TBlockVar#fff AS I OUTPUT I.<1>, I.<0>, I.<2>
567217 ~2% {2} r2 = JOIN r1 WITH FlowVar::PartialDefinitions::PartialDefinition::partiallyDefinesVariableAt#fff_120#join_rhs AS R ON FIRST 2 OUTPUT r1.<2>, R.<2>
return r2
Looking at the code, it turned out that the predicates
`partiallyDefines` and `getSubBasicBlockStart` were almost always used
together and could therefore be merged into a single predicate to get
better join orderings. The predicate `partiallyDefinesThis` was never
used.
This commit is contained in:
@@ -120,14 +120,19 @@ private module PartialDefinitions {
|
||||
)
|
||||
}
|
||||
|
||||
predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
|
||||
deprecated predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
|
||||
|
||||
predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
|
||||
deprecated predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
|
||||
|
||||
/**
|
||||
* Gets the subBasicBlock where this `PartialDefinition` is defined.
|
||||
* Holds if this `PartialDefinition` defines variable `v` at control-flow
|
||||
* node `cfn`.
|
||||
*/
|
||||
ControlFlowNode getSubBasicBlockStart() { result = node }
|
||||
pragma[noinline]
|
||||
predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) {
|
||||
innerDefinedExpr = v.getAnAccess() and
|
||||
cfn = node
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this partial definition may modify `inner` (or what it points
|
||||
@@ -188,7 +193,7 @@ module FlowVar_internal {
|
||||
predicate fullySupportedSsaVariable(Variable v) {
|
||||
v = any(SsaDefinition def).getAVariable() and
|
||||
// A partially-defined variable is handled using the partial definitions logic.
|
||||
not any(PartialDefinition p).partiallyDefines(v) and
|
||||
not any(PartialDefinition p).partiallyDefinesVariableAt(v, _) and
|
||||
// SSA variables do not exist before their first assignment, but one
|
||||
// feature of this data flow library is to track where uninitialized data
|
||||
// ends up.
|
||||
@@ -232,7 +237,7 @@ module FlowVar_internal {
|
||||
or
|
||||
assignmentLikeOperation(sbb, v, _, _)
|
||||
or
|
||||
sbb = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart()
|
||||
exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, sbb))
|
||||
or
|
||||
blockVarDefinedByVariable(sbb, v)
|
||||
)
|
||||
@@ -363,8 +368,7 @@ module FlowVar_internal {
|
||||
|
||||
override predicate definedPartiallyAt(Expr e) {
|
||||
exists(PartialDefinition p |
|
||||
p.partiallyDefines(v) and
|
||||
sbb = p.getSubBasicBlockStart() and
|
||||
p.partiallyDefinesVariableAt(v, sbb) and
|
||||
p.definesExpressions(_, e)
|
||||
)
|
||||
}
|
||||
@@ -742,7 +746,7 @@ module FlowVar_internal {
|
||||
exists(Variable v | not fullySupportedSsaVariable(v) |
|
||||
assignmentLikeOperation(this, v, _, _)
|
||||
or
|
||||
this = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart()
|
||||
exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, this))
|
||||
// It is not necessary to cut the basic blocks at `Initializer` nodes
|
||||
// because the affected variable can have no _other_ value before its
|
||||
// initializer. It is not necessary to cut basic blocks at procedure
|
||||
|
||||
Reference in New Issue
Block a user