C++: Add an initial pruning stage to prevent this

large TC in 'localFlowToExpr':
```
Evaluated relational algebra for predicate Buffer#61e3d199::localFlowStepToExpr#2#ff@0a49913i with tuple counts:
    4713946   ~0%    {2} r1 = SCAN DataFlowUtil#47741e1f::simpleLocalFlowStep#2#ff OUTPUT In.1, In.0

  40897385  ~46%    {2} r2 = JOIN boundedFastTC:Buffer#61e3d199::localFlowToExprStep#2#ff_10#higher_order_body:DataFlowUtil#47741e1f::simpleLocalFlowStep#2#ff_0#higher_order_body WITH DataFlowUtil#47741e1f::simpleLocalFlowStep#2#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1

  45611331  ~43%    {2} r3 = r1 UNION r2
    3376553  ~14%    {2} r4 = JOIN r3 WITH DataFlowUtil#47741e1f::ExprNode::getExpr#0#dispred#ff ON FIRST 1 OUTPUT Lhs.1, Rhs.1
                    return r4
```

After this commit the tuple counts looks like:
```
Evaluated relational algebra for predicate Buffer#61e3d199::localFlowStepToExpr#2#ff@8cc38x5k on iteration 2 running pipeline standard with tuple counts:
         51367   ~3%    {2} r1 = JOIN Buffer#61e3d199::getBufferSize0#1#f#prev_delta WITH DataFlowUtil#47741e1f::ExprNode::getExpr#0#dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.0

        124933  ~18%    {2} r2 = JOIN r1 WITH #Buffer#61e3d199::localFlowToExprStep#2Plus#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1

        176300  ~17%    {2} r3 = r1 UNION r2
        184685  ~22%    {2} r4 = JOIN r3 WITH DataFlowUtil#47741e1f::simpleLocalFlowStep#2#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1
         56646  ~47%    {2} r5 = JOIN r4 WITH DataFlowUtil#47741e1f::ExprNode::getExpr#0#dispred#ff ON FIRST 1 OUTPUT Lhs.1, Rhs.1
         44635  ~16%    {2} r6 = r5 AND NOT Buffer#61e3d199::localFlowStepToExpr#2#ff#prev(Lhs.0, Lhs.1)
                        return r6
```
This commit is contained in:
Mathias Vorreiter Pedersen
2022-10-30 12:59:32 +01:00
parent aa8214addf
commit 1b50168d08

View File

@@ -79,8 +79,10 @@ private predicate localFlowToExprStep(DataFlow::Node n1, DataFlow::Node n2) {
}
/** Holds if `n2 + delta` may be equal to `n1`. */
private predicate localFlowStepToExpr(DataFlow::Node n1, Expr e2) {
exists(DataFlow::Node mid, DataFlow::Node n2 |
private predicate localFlowStepToExpr(Expr e1, Expr e2) {
getBufferSize0(e1) and
exists(DataFlow::Node n1, DataFlow::Node mid, DataFlow::Node n2 |
n1.asExpr() = e1 and
localFlowToExprStep*(n1, mid) and
DataFlow::localFlowStep(mid, n2) and
n2.asExpr() = e2
@@ -93,6 +95,7 @@ private predicate localFlowStepToExpr(DataFlow::Node n1, Expr e2) {
* expression.
*/
private predicate step(Expr e1, Expr e2, int delta) {
getBufferSize0(e1) and
exists(Variable bufferVar, Class parentClass, VariableAccess parentPtr, int bufferSize |
e1 = parentPtr
|
@@ -109,19 +112,32 @@ private predicate step(Expr e1, Expr e2, int delta) {
delta = bufferSize - parentClass.getSize()
)
or
localFlowStepToExpr(DataFlow::exprNode(e1), e2) and
localFlowStepToExpr(e1, e2) and
delta = 0
}
pragma[nomagic]
private predicate getBufferSize0(Expr e) {
exists(isSource(e, _))
or
exists(Expr e0 |
getBufferSize0(e0) and
step(e0, e, _)
)
}
/**
* Get the size in bytes of the buffer pointed to by an expression (if this can be determined).
*/
int getBufferSize(Expr bufferExpr, Element why) {
result = isSource(bufferExpr, why)
or
exists(Expr e0, int delta, int size |
size = getBufferSize(e0, why) and
delta = unique(int cand | step(e0, bufferExpr, cand) | cand) and
result = size + delta
getBufferSize0(bufferExpr) and
(
result = isSource(bufferExpr, why)
or
exists(Expr e0, int delta, int size |
size = getBufferSize(e0, why) and
delta = unique(int cand | step(e0, bufferExpr, cand) | cand) and
result = size + delta
)
)
}