Skip to content

Commit 6d15e51

Browse files
owen-mcCopilot
andcommitted
SSA: Support retained phi definitions and refinement barriers
Add opt-in phi-definition retention for JavaScript's public SSA node API. Follow value-preserving uncertain definitions when determining guarded phi inputs. Keep phi retention disabled by default for existing clients. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 45805f3 commit 6d15e51

1 file changed

Lines changed: 23 additions & 2 deletions

File tree

‎shared/ssa/codeql/ssa/Ssa.qll‎

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,15 @@ module Make<
14831483
*/
14841484
default predicate includeWriteDefsInFlowStep() { any() }
14851485

1486+
/**
1487+
* Holds if phi definitions should always have a data flow node, even when
1488+
* they have a unique next reference. This is useful for language-specific
1489+
* APIs that expose a node for each SSA definition.
1490+
*
1491+
* Phi reads may still be skipped.
1492+
*/
1493+
default predicate includePhiDefsInFlowStep() { none() }
1494+
14861495
/**
14871496
* Holds if barrier guards should be supported on input edges to phi
14881497
* nodes. Disable this only if barrier guards are not going to be used.
@@ -1540,9 +1549,20 @@ module Make<
15401549
)
15411550
}
15421551

1552+
private Definition getAValuePreservingInputDef(Definition def) {
1553+
result = def
1554+
or
1555+
exists(Definition inp |
1556+
DfInput::allowFlowIntoUncertainDef(def) and
1557+
not DfInput::ssaDefHasSource(def) and
1558+
uncertainWriteDefinitionInput(def, inp) and
1559+
result = getAValuePreservingInputDef(inp)
1560+
)
1561+
}
1562+
15431563
pragma[nomagic]
15441564
private predicate phiInputHasRead(SsaPhiExt phi, BasicBlock input) {
1545-
exists(DfInput::getARead(getAPhiInputDef(phi, input)))
1565+
exists(DfInput::getARead(getAValuePreservingInputDef(getAPhiInputDef(phi, input))))
15461566
}
15471567

15481568
/** Holds if `bb` is the target end of a branch edge of a guard and the guard controls `bb`. */
@@ -1667,6 +1687,7 @@ module Make<
16671687
* flow edges.
16681688
*/
16691689
private predicate phiHasUniqNextNode(SsaPhiExt phi) {
1690+
not (phi instanceof PhiNode and DfInput::includePhiDefsInFlowStep()) and
16701691
not relevantBackEdge(phi, _) and
16711692
exists(int nextPhiInput, int nextPhi, int nextRef |
16721693
1 = nextPhiInput + nextPhi + nextRef and
@@ -2119,7 +2140,7 @@ module Make<
21192140
private predicate guardChecksSsaDef(
21202141
DfInput::Guard g, Definition def, DfInput::GuardValue val, State state
21212142
) {
2122-
guardChecks(g, DfInput::getARead(def), val, state)
2143+
guardChecks(g, DfInput::getARead(getAValuePreservingInputDef(def)), val, state)
21232144
}
21242145

21252146
private module Barrier = BarrierGuardDefWithState<State, guardChecksSsaDef/4>;

0 commit comments

Comments
 (0)