1111 * controls the basic block `A`, in this case because the true branch dominates
1212 * `A`, but more elaborate controls-relationships may also hold.
1313 * For example, in
14- * ```
14+ * ```java
1515 * int sz = a != null ? a.length : 0;
1616 * if (sz != 0) {
1717 * // this block is controlled by:
@@ -104,6 +104,19 @@ signature module InputSig<LocationSig Location> {
104104 predicate strictlyDominates ( BasicBlock bb ) ;
105105 }
106106
107+ /**
108+ * Holds if `bb1` has `bb2` as a direct successor and the edge between `bb1`
109+ * and `bb2` is a dominating edge.
110+ *
111+ * An edge `(bb1, bb2)` is dominating if there exists a basic block that can
112+ * only be reached from the entry block by going through `(bb1, bb2)`. This
113+ * implies that `(bb1, bb2)` dominates its endpoint `bb2`. I.e., `bb2` can
114+ * only be reached from the entry block by going via `(bb1, bb2)`.
115+ *
116+ * This is a necessary and sufficient condition for an edge to dominate some
117+ * block, and therefore `dominatingEdge(bb1, bb2) and bb2.dominates(bb3)`
118+ * means that the edge `(bb1, bb2)` dominates `bb3`.
119+ */
107120 predicate dominatingEdge ( BasicBlock bb1 , BasicBlock bb2 ) ;
108121
109122 class AstNode {
@@ -528,6 +541,17 @@ module Make<LocationSig Location, InputSig<Location> Input> {
528541 module Logic< LogicInputSig LogicInput> {
529542 private import LogicInput
530543
544+ /**
545+ * Holds if `guard` evaluating to `v` directly controls `phi` taking the value
546+ * `inp`. This means that `guard` evaluating to `v` must control all the input
547+ * edges to `phi` that read `inp`.
548+ *
549+ * We also require that `guard` dominates `phi` in order to allow logical inferences
550+ * from the value of `phi` to the value of `guard`.
551+ *
552+ * Trivial cases where `guard` controls `phi` itself are excluded, since that makes
553+ * logical inferences from `phi` to `guard` trivial and irrelevant.
554+ */
531555 private predicate guardControlsPhiBranch (
532556 Guard guard , GuardValue v , SsaPhiNode phi , SsaDefinition inp
533557 ) {
@@ -571,6 +595,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
571595 private predicate guardReadsSsaVar ( Guard guard , SsaDefinition def ) {
572596 def .getARead ( ) = guard
573597 or
598+ // A read of `y` can be considered as a read of `x` if guarded by `x == y`.
574599 exists ( Guard eqtest , SsaDefinition other , boolean branch |
575600 guardChecksEqualVars ( eqtest , def , other , branch ) and
576601 other .getARead ( ) = guard and
@@ -602,21 +627,21 @@ module Make<LocationSig Location, InputSig<Location> Input> {
602627 * boolean `fromBackEdge` indicates whether the flow from `result` to `v` goes
603628 * through a back edge.
604629 */
605- private SsaDefinition getADefinition ( SsaDefinition v , boolean fromBackEdge ) {
630+ private SsaDefinition getAnUltimateDefinition ( SsaDefinition v , boolean fromBackEdge ) {
606631 result = v and not v instanceof SsaPhiNode and fromBackEdge = false
607632 or
608633 exists ( SsaDefinition inp , BasicBlock bb , boolean fbe |
609634 v .( SsaPhiNode ) .hasInputFromBlock ( inp , bb ) and
610- result = getADefinition ( inp , fbe ) and
635+ result = getAnUltimateDefinition ( inp , fbe ) and
611636 ( if v .getBasicBlock ( ) .dominates ( bb ) then fromBackEdge = true else fromBackEdge = fbe )
612637 )
613638 }
614639
615640 /**
616- * Holds if `v` can have a value that is not representable as an `GuardValue`.
641+ * Holds if `v` can have a value that is not representable as a `GuardValue`.
617642 */
618643 private predicate hasPossibleUnknownValue ( SsaDefinition v ) {
619- exists ( SsaDefinition def | def = getADefinition ( v , _) |
644+ exists ( SsaDefinition def | def = getAnUltimateDefinition ( v , _) |
620645 not exists ( def .( SsaWriteDefinition ) .getDefinition ( ) )
621646 or
622647 exists ( Expr e | e = possibleValue ( def .( SsaWriteDefinition ) .getDefinition ( ) ) |
@@ -633,7 +658,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
633658 private predicate possibleValue ( SsaDefinition v , boolean fromBackEdge , Expr e , GuardValue k ) {
634659 not hasPossibleUnknownValue ( v ) and
635660 exists ( SsaWriteDefinition def |
636- def = getADefinition ( v , fromBackEdge ) and
661+ def = getAnUltimateDefinition ( v , fromBackEdge ) and
637662 e = possibleValue ( def .getDefinition ( ) ) and
638663 constantHasValue ( e , k )
639664 )
@@ -676,7 +701,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
676701 or
677702 exists ( SsaDefinition def |
678703 guardReadsSsaVar ( e , def ) and
679- relevantInt ( getADefinition ( def , _) .( SsaWriteDefinition ) .getDefinition ( ) , k )
704+ relevantInt ( getAnUltimateDefinition ( def , _) .( SsaWriteDefinition ) .getDefinition ( ) , k )
680705 )
681706 }
682707
@@ -808,7 +833,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
808833 * starting from a given set of base cases.
809834 */
810835 cached
811- module ImpliesTC< baseGuardValueSig / 2 baseGuardValue> {
836+ private module ImpliesTC< baseGuardValueSig / 2 baseGuardValue> {
812837 /**
813838 * Holds if `tgtGuard` evaluating to `tgtVal` implies that `guard`
814839 * evaluates to `v`.
0 commit comments