-
Notifications
You must be signed in to change notification settings - Fork 1.9k
SSA: Distinguish between has and controls branch edge. #19567
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -991,13 +991,17 @@ private module DataFlowIntegrationInput implements SsaImpl::DataFlowIntegrationI | |||||||||||||
| class Guard instanceof IRGuards::IRGuardCondition { | ||||||||||||||
| string toString() { result = super.toString() } | ||||||||||||||
|
|
||||||||||||||
| predicate controlsBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) { | ||||||||||||||
| predicate hasBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) { | ||||||||||||||
| exists(EdgeKind kind | | ||||||||||||||
| super.getBlock() = bb1 and | ||||||||||||||
| kind = getConditionalEdge(branch) and | ||||||||||||||
| bb1.getSuccessor(kind) = bb2 | ||||||||||||||
| ) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
|
||||||||||||||
| /** | |
| * Delegates to `hasBranchEdge` to determine if this guard controls | |
| * the branch edge between the given basic blocks (`bb1` and `bb2`) | |
| * for the specified branch condition. | |
| */ |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -732,6 +732,8 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig | |||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| class Guard extends Void { | ||||||||||||||||||||
|
||||||||||||||||||||
| class Guard extends Void { | |
| class Guard extends Void { | |
| /** | |
| * Determines whether there is a branch edge between two basic blocks (`bb1` and `bb2`). | |
| * The `branch` parameter indicates the branch direction (e.g., true for "then" branch, false for "else" branch). | |
| * | |
| * Currently, this predicate returns `none()` because branch edge detection is not implemented | |
| * or not applicable in the current context. | |
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| category: breaking | ||
| --- | ||
| * Adjusted the Guards interface in the SSA data flow integration to distinguish `hasBranchEdge` from `controlsBranchEdge`. Any breakage can be fixed by implementing one with the other as a reasonable fallback solution. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1570,9 +1570,23 @@ module Make<LocationSig Location, InputSig<Location> Input> { | |
| string toString(); | ||
|
|
||
| /** | ||
| * Holds if the control flow branching from `bb1` is dependent on this guard, | ||
| * and that the edge from `bb1` to `bb2` corresponds to the evaluation of this | ||
| * guard to `branch`. | ||
| * Holds if the evaluation of this guard to `branch` corresponds to the edge | ||
| * from `bb1` to `bb2`. | ||
| */ | ||
| predicate hasBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch); | ||
|
|
||
| /** | ||
| * Holds if this guard evaluating to `branch` controls the control-flow | ||
| * branch edge from `bb1` to `bb2`. That is, following the edge from | ||
| * `bb1` to `bb2` implies that this guard evaluated to `branch`. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps add an example to illustrate how this can differ from
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's the general distinction between direct and indirect control. E.g.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that is what I was thinking; simply add that example to the QL doc.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| * | ||
| * This predicate differs from `hasBranchEdge` in that it also covers | ||
| * indirect guards, such as: | ||
| * ``` | ||
| * b = guard; | ||
| * ... | ||
| * if (b) { ... } | ||
| * ``` | ||
| */ | ||
| predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch); | ||
| } | ||
|
|
@@ -1667,7 +1681,7 @@ module Make<LocationSig Location, InputSig<Location> Input> { | |
| ( | ||
| // The input node is relevant either if it sits directly on a branch | ||
| // edge for a guard, | ||
| exists(DfInput::Guard g | g.controlsBranchEdge(input, phi.getBasicBlock(), _)) | ||
| exists(DfInput::Guard g | g.hasBranchEdge(input, phi.getBasicBlock(), _)) | ||
| or | ||
| // or if the unique predecessor is not an equivalent substitute in | ||
| // terms of being controlled by the same guards. | ||
|
|
||
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.
Include a descriptive doc comment above this stubbed
hasBranchEdgeto clarify why it defaults tonone()in this context.