Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 49 additions & 10 deletions shared/ssa/codeql/ssa/Ssa.qll
Original file line number Diff line number Diff line change
Expand Up @@ -2081,6 +2081,41 @@ module Make<
)
}

pragma[nomagic]
private predicate phiInputHasRead(SsaPhiExt phi, BasicBlock input) {
exists(DfInput::getARead(getAPhiInputDef(phi, input)))
}

/** Holds if `bb` is the target end of a branch edge of a guard and the guard controls `bb`. */
pragma[nomagic]
private predicate guardControlledBranchTarget(BasicBlock bb) {
exists(BasicBlock guard |
any(DfInput::Guard g).hasValueBranchEdge(guard, bb, _) and
dominatingEdge(guard, bb)
)
}

private BasicBlock getGuardEquivalentImmediateDominator(BasicBlock bb) {
result = bb.getImmediateDominator() and
not guardControlledBranchTarget(bb)
}

/**
* Holds if the immediately preceding reference to the input to `phi` from
* the block `input` is guard-equivalent with `input` in the sense that the
* set of guards controlling the preceding reference is the same as the set
* of guards controlling `input`.
*
* This is restricted to phi inputs that are actually read.
*/
private predicate phiInputIsGuardEquivalentWithPreviousRef(SsaPhiExt phi, BasicBlock input) {
exists(BasicBlock prev |
phiInputHasRead(phi, input) and
AdjacentSsaRefs::adjacentRefPhi(prev, _, input, phi.getBasicBlock(), phi.getSourceVariable()) and
prev = getGuardEquivalentImmediateDominator*(input)
)
}

/**
* Holds if the input to `phi` from the block `input` might be relevant for
* barrier guards as a separately synthesized `TSsaInputNode`.
Expand All @@ -2095,7 +2130,7 @@ module Make<
or
DfInput::supportBarrierGuardsOnPhiEdges() and
// If the input isn't explicitly read then a guard cannot check it.
exists(DfInput::getARead(getAPhiInputDef(phi, input))) and
phiInputHasRead(phi, input) and
(
// The input node is relevant either if it sits directly on a branch
// edge for a guard,
Expand All @@ -2114,15 +2149,19 @@ module Make<
// }
// // phi-read node for `x`
// ```
exists(BasicBlock prev |
AdjacentSsaRefs::adjacentRefPhi(prev, _, input, phi.getBasicBlock(),
phi.getSourceVariable()) and
prev != input and
exists(DfInput::Guard g, DfInput::GuardValue val |
DfInput::guardDirectlyControlsBlock(g, input, val) and
not DfInput::guardDirectlyControlsBlock(g, prev, val)
)
)
not phiInputIsGuardEquivalentWithPreviousRef(phi, input)
// An equivalent, but less performant, way to express this is as follows:
// ```
// exists(BasicBlock prev |
// AdjacentSsaRefs::adjacentRefPhi(prev, _, input, phi.getBasicBlock(),
// phi.getSourceVariable()) and
// prev != input and
// exists(DfInput::Guard g, DfInput::GuardValue val |
// DfInput::guardDirectlyControlsBlock(g, input, val) and
// not DfInput::guardDirectlyControlsBlock(g, prev, val)
// )
// )
// ```
)
}

Expand Down
Loading