Improve performance of ExprChildMapping::reachesBasicBlock()

Since all expressions are now post-order, the logic of `reachesBasicBlock` can
be simplified, and performance can be improved as well.
This commit is contained in:
Tom Hvitved
2021-06-14 11:58:24 +02:00
parent 88fb3c7097
commit b154c936c3

View File

@@ -113,6 +113,13 @@ class ReturningCfgNode extends AstCfgNode {
}
}
private Expr desugar(Expr n) {
result = n.getDesugared()
or
not exists(n.getDesugared()) and
result = n
}
/**
* A class for mapping parent-child AST nodes to parent-child CFG nodes.
*/
@@ -123,43 +130,19 @@ abstract private class ExprChildMapping extends Expr {
*/
abstract predicate relevantChild(Expr child);
pragma[noinline]
private BasicBlock getABasicBlockInScope() {
result.getANode() = TAstCfgNode(this.getAChild*(), _)
}
pragma[nomagic]
private predicate reachesBasicBlockBase(Expr child, CfgNode cfn, BasicBlock bb) {
private predicate reachesBasicBlock(Expr child, CfgNode cfn, BasicBlock bb) {
this.relevantChild(child) and
cfn = this.getAControlFlowNode() and
bb.getANode() = cfn
}
pragma[nomagic]
private predicate reachesBasicBlock(Expr child, CfgNode cfn, BasicBlock bb) {
this.reachesBasicBlockBase(child, cfn, bb)
or
this.relevantChild(child) and
this.reachesBasicBlockRec(child, cfn, bb) and
bb = this.getABasicBlockInScope()
}
pragma[nomagic]
private predicate reachesBasicBlockRec(Expr child, CfgNode cfn, BasicBlock bb) {
exists(BasicBlock mid | this.reachesBasicBlock(child, cfn, mid) |
bb = mid.getASuccessor()
or
bb = mid.getAPredecessor()
exists(BasicBlock mid |
this.reachesBasicBlock(child, cfn, mid) and
bb = mid.getAPredecessor() and
not mid.getANode().getNode() = child
)
}
private Expr desugar(Expr n) {
result = n.getDesugared()
or
not exists(n.getDesugared()) and
result = n
}
/**
* Holds if there is a control-flow path from `cfn` to `cfnChild`, where `cfn`
* is a control-flow node for this expression, and `cfnChild` is a control-flow
@@ -169,17 +152,8 @@ abstract private class ExprChildMapping extends Expr {
*/
cached
predicate hasCfgChild(Expr child, CfgNode cfn, CfgNode cfnChild) {
exists(BasicBlock bb |
this.reachesBasicBlockBase(child, cfn, bb) and
cfnChild = bb.getANode() and
cfnChild = desugar(child).getAControlFlowNode()
)
or
exists(BasicBlock bb |
this.reachesBasicBlockRec(child, cfn, bb) and
cfnChild = bb.getANode() and
cfnChild = desugar(child).getAControlFlowNode()
)
this.reachesBasicBlock(child, cfn, cfnChild.getBasicBlock()) and
cfnChild = desugar(child).getAControlFlowNode()
}
}