@@ -15,7 +15,7 @@ signature module InputSig<LocationSig Location> {
1515 /** Hold if `t` represents a conditional successor type. */
1616 predicate successorTypeIsCondition ( SuccessorType t ) ;
1717
18- /** Represents a delineated part of the AST with its own CFG. */
18+ /** A delineated part of the AST with its own CFG. */
1919 class CfgScope ;
2020
2121 /** The class of control flow nodes. */
@@ -106,24 +106,28 @@ module Make<LocationSig Location, InputSig<Location> Input> {
106106 /**
107107 * Holds if this basic block immediately dominates basic block `bb`.
108108 *
109- * That is, `bb` is an immediate successor of this basic block and all
110- * paths reaching basic block `bb` from some entry point basic block must
111- * go through this basic block.
109+ * That is, this basic block is the unique basic block satisfying:
110+ * 1. This basic block strictly dominates `bb`
111+ * 2. There exists no other basic block that is strictly dominated by this
112+ * basic block and which strictly dominates `bb`.
113+ *
114+ * All basic blocks, except entry basic blocks, have a unique immediate
115+ * dominator.
112116 */
113117 predicate immediatelyDominates ( BasicBlock bb ) { bbIDominates ( this , bb ) }
114118
115119 /**
116120 * Holds if this basic block strictly dominates basic block `bb`.
117121 *
118- * That is, all paths reaching `bb` from some entry point basic block must
122+ * That is, all paths reaching `bb` from the entry point basic block must
119123 * go through this basic block and this basic block is different from `bb`.
120124 */
121125 predicate strictlyDominates ( BasicBlock bb ) { bbIDominates + ( this , bb ) }
122126
123127 /**
124128 * Holds if this basic block dominates basic block `bb`.
125129 *
126- * That is, all paths reaching `bb` from some entry point basic block must
130+ * That is, all paths reaching `bb` from the entry point basic block must
127131 * go through this basic block.
128132 */
129133 predicate dominates ( BasicBlock bb ) {
@@ -154,46 +158,67 @@ module Make<LocationSig Location, InputSig<Location> Input> {
154158 /**
155159 * Gets the basic block that immediately dominates this basic block, if any.
156160 *
157- * That is, all paths reaching this basic block from some entry point
158- * basic block must go through the result, which is an immediate basic block
159- * predecessor of this basic block.
161+ * That is, the result is the unique basic block satisfying:
162+ * 1. The result strictly dominates this basic block.
163+ * 2. There exists no other basic block that is strictly dominated by the
164+ * result and which strictly dominates this basic block.
165+ *
166+ * All basic blocks, except entry basic blocks, have a unique immediate
167+ * dominator.
160168 */
161169 BasicBlock getImmediateDominator ( ) { bbIDominates ( result , this ) }
162170
163171 /**
164172 * Holds if basic block `succ` is immediately controlled by this basic
165- * block with successor type `s`. That is, `succ` is an immediate successor
166- * of this block, and `succ` can only be reached from the entry block by
167- * going via the `s` edge out of this basic block.
173+ * block with successor type `s`.
168174 *
169- * The above implies that this block immediately dominates `succ`. But
170- * "controls" is a stronger notion than "dominates". It is not the case
171- * that any immediate successor that is immediately dominated by this block
172- * is also immediately controlled by this block. To see why, consider this
173- * example corresponding to an `if`-statement without an `else` block:
174- * ```
175- * ... --> cond --[true]--> ... --> if stmt
176- * \ /
177- * ----[false]-----------
178- * ```
179- * The basic block for `cond` immediately dominates the immediately
180- * succeeding basic block for the `if` statement. But the `if` statement
181- * is not immediately controlled by the `cond` basic block and the `false`
182- * edge since it is also possible to reach the `if` statement via a path
183- * through the `true` edge.
175+ * That is, `succ` is an immediate successor of this block, and `succ` can
176+ * only be reached from the entry block by going via the `s` edge out of
177+ * this basic block.
184178 */
185179 pragma [ nomagic]
186180 predicate immediatelyControls ( BasicBlock succ , SuccessorType s ) {
187181 succ = this .getASuccessor ( s ) and
182+ bbIDominates ( this , succ ) and
183+ // The above is not sufficient to ensure that `succ` can only be reached
184+ // through `s`. To see why, consider this example corresponding to an
185+ // `if` expression without an `else` block:
186+ // ```
187+ // ... --> cond --[true]--> ... --> if expr
188+ // \ /
189+ // ----[false]-----------
190+ // ```
191+ // The basic block for `cond` immediately dominates the directly
192+ // succeeding basic block for the `if` expression. But the `if`
193+ // expression is not immediately controlled by the `cond` basic block and
194+ // the `false` edge since it is also possible to reach the `if`
195+ // expression via the `true` edge.
196+ //
197+ // Note that the first and third conjunct implies the second. But
198+ // explicitly including the second conjunct leads to a better join order.
188199 forall ( BasicBlock pred | pred = succ .getAPredecessor ( ) and pred != this |
189200 succ .dominates ( pred )
190201 )
191202 }
192203
193204 /**
194205 * Holds if basic block `controlled` is controlled by this basic block with
195- * successor type `s`. That is, `controlled` can only be reached from the
196- * entry point by going via the `s` edge out of this basic block.
206+ * successor type `s`.
207+ *
208+ * That is, all paths reaching `controlled` from the entry point basic
209+ * block must go through the `s` edge out of this basic block.
210+ *
211+ * Control is similar to dominance except it concerns edges instead of
212+ * nodes: A basic block is _dominated_ by a _basic block_ `bb` if it can
213+ * only be reached through `bb` and _controlled_ by an _edge_ `s` if it can
214+ * only be reached through `s`.
215+ *
216+ * Note that where all basic blocks (except the entry basic block) are
217+ * strictly dominated by at least one basic block, a basic block may not be
218+ * controlled by any edge. If an edge controls a basic block `bb`, then
219+ * both endpoints of the edge dominates `bb`. The converse is not the case,
220+ * as there may be multiple paths between the endpoints with none of them
221+ * dominating.
197222 */
198223 predicate controls ( BasicBlock controlled , SuccessorType s ) {
199224 // For this block to control the block `controlled` with `s` the following must be true:
@@ -308,6 +333,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
308333 * Holds if `bbStart` is the first node in a basic block and `cfn` is the
309334 * `i`th node in the same basic block.
310335 */
336+ pragma [ nomagic]
311337 private predicate bbIndex ( Node bbStart , Node cfn , int i ) =
312338 shortestDistances( startsBB / 1 , intraBBSucc / 2 ) ( bbStart , cfn , i )
313339
0 commit comments