diff --git a/shared/ssa/codeql/ssa/Ssa.qll b/shared/ssa/codeql/ssa/Ssa.qll index 26f3d9f9771..b58d28c534f 100644 --- a/shared/ssa/codeql/ssa/Ssa.qll +++ b/shared/ssa/codeql/ssa/Ssa.qll @@ -2081,6 +2081,54 @@ 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) + ) + } + + /** + * Holds if `prev` is the block containing the unique predecessor of `phi` + * that reaches `phi` through the input block `input`, and that `mid` is a + * block in the dominator tree between `prev` and `input` that is + * guard-equivalent with `input` in the sense that the set of guards + * controlling `mid` is the same as the set of guards controlling `input`. + * + * This is restricted to phi inputs that are actually read. + */ + private predicate phiInputGuardEquivalenceReaches( + BasicBlock prev, BasicBlock mid, SsaPhiExt phi, BasicBlock input + ) { + phiInputHasRead(phi, input) and + AdjacentSsaRefs::adjacentRefPhi(prev, _, input, phi.getBasicBlock(), phi.getSourceVariable()) and + mid = input + or + exists(BasicBlock mid0 | + phiInputGuardEquivalenceReaches(prev, mid0, phi, input) and + not guardControlledBranchTarget(mid0) and + mid0 != prev and + mid = mid0.getImmediateDominator() + ) + } + + /** + * Holds if the immediately preceding reference to the input to `phi` from + * the block `input` is guard-equivalent with `input`. + * + * This is restricted to phi inputs that are actually read. + */ + private predicate phiInputIsGuardEquivalentWithPreviousRef(SsaPhiExt phi, BasicBlock input) { + exists(BasicBlock prev | phiInputGuardEquivalenceReaches(prev, prev, phi, input)) + } + /** * Holds if the input to `phi` from the block `input` might be relevant for * barrier guards as a separately synthesized `TSsaInputNode`. @@ -2095,7 +2143,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, @@ -2114,15 +2162,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) + // ) + // ) + // ``` ) }