-
Notifications
You must be signed in to change notification settings - Fork 1.8k
C++: Fix localStepsToExpr
performance
#12477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C++: Fix localStepsToExpr
performance
#12477
Conversation
CI check is failing due to the autoformatter changes. I suggest we ignore those and fix all of those in a follow-up PR once #12230 has been merged into |
// We should never recursive through any of these nodes while | ||
// looking for the next expression. | ||
not n1 instanceof SsaPhiNode and | ||
not n1 instanceof InitialGlobalValue and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment doesn't quite give me sufficient information here as to why this is ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, yes I can see what you mean. I'll expand the explanation. Taking a step back, the point of localStepsToExpr(n1, n2, e2)
is that n2
is the first node after n1
in the dataflow step relation that has a result for asExpr()
. So localStepsToExpr
does a transitive closure over localFlowStep
, but where localFlowStep
is restricted to only take a step as long as there's no result for asExpr()
(this is the localStepFromNonExpr
predicate). Once we find a node for which asExpr()
exists, the transitive closure stops.
On the particular project I was looking at, there apparently were some nasty SsaPhiNode
s that made the transitive closure of localStepFromNonExpr
blow up even with the restriction mentioned above. SsaPhiNode
are trivially includes in localStepFromNonExpr
because both SsaPhiNode
because they clearly satisfy not exists(n1.asExpr())
(as these nodes are not supposed to map to expressions) and they can have many many incoming nodes. This resulted in the tuple explosion.
But when we're looking for the next node after n1
in the dataflow step relation that has a result for asExpr()
, we should never step over an SsaPhiNode
since this node represents incoming data from many different places.
I'll try to write a more carefully worded description of the above and put it in a comment if it makes more sense now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
37d417b adds a version of ^ into the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense now.
Oops. Looks like I broke some query results 😢. I'll investigate! |
not n1 instanceof InitialGlobalValue and | ||
// And dually to the above case for `InitialGlobalValue`: if we're at a | ||
// `FinalGlobalValue` node it means we've reached the final value of a global | ||
// variable as we're exiting a function. That global variable will have a final | ||
// mention somewhere in the body of the function, and that mention will have a | ||
// result for `asExpr()`. | ||
not n2 instanceof FinalGlobalValue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So when I originally commented. I thought that the comment above not n1 instanceof SsaPhiNode
applied to both that and not n1 instanceof InitialGlobalValue
, which it clearly does not. A combined comment for InitialGlobalValue
and FinalGlobalValue
might make slightly more sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that's a good point. I'll write a combined comment once I've figured out why this PR is breaking some query tests.
Turns out this PR wasn't the right way to fix this. It gave some genuine new lost results, and I now realize that weeding out |
localStepFromNonExpr
included a bunch of unnecessary nodes which led to a blowup when taking its transitive closure inlocalStepsToExpr
:(I stopped evaluation midway)
After this PR we get: