@@ -72,6 +72,20 @@ abstract private class GuardConditionImpl extends Expr {
7272 */
7373 abstract predicate valueControls ( BasicBlock controlled , AbstractValue v ) ;
7474
75+ /**
76+ * Holds if the control-flow edge `(pred, succ)` may be taken only if
77+ * the value of this condition is `v`.
78+ */
79+ abstract predicate valueControlsEdge ( BasicBlock pred , BasicBlock succ , AbstractValue v ) ;
80+
81+ /**
82+ * Holds if the control-flow edge `(pred, succ)` may be taken only if
83+ * this the value of this condition is `testIsTrue`.
84+ */
85+ final predicate controlsEdge ( BasicBlock pred , BasicBlock succ , boolean testIsTrue ) {
86+ this .valueControlsEdge ( pred , succ , any ( BooleanValue bv | bv .getValue ( ) = testIsTrue ) )
87+ }
88+
7589 /**
7690 * Holds if this condition controls `controlled`, meaning that `controlled` is only
7791 * entered if the value of this condition is `testIsTrue`.
@@ -175,6 +189,58 @@ abstract private class GuardConditionImpl extends Expr {
175189 */
176190 pragma [ inline]
177191 abstract predicate ensuresEq ( Expr e , int k , BasicBlock block , boolean areEqual ) ;
192+
193+ /**
194+ * Holds if (determined by this guard) `left == right + k` must be `areEqual` on the edge from
195+ * `pred` to `succ`. If `areEqual = false` then this implies `left != right + k`.
196+ */
197+ pragma [ inline]
198+ final predicate ensuresEqEdge (
199+ Expr left , Expr right , int k , BasicBlock pred , BasicBlock succ , boolean areEqual
200+ ) {
201+ exists ( boolean testIsTrue |
202+ this .comparesEq ( left , right , k , areEqual , testIsTrue ) and
203+ this .controlsEdge ( pred , succ , testIsTrue )
204+ )
205+ }
206+
207+ /**
208+ * Holds if (determined by this guard) `e == k` must be `areEqual` on the edge from
209+ * `pred` to `succ`. If `areEqual = false` then this implies `e != k`.
210+ */
211+ pragma [ inline]
212+ final predicate ensuresEqEdge ( Expr e , int k , BasicBlock pred , BasicBlock succ , boolean areEqual ) {
213+ exists ( AbstractValue v |
214+ this .comparesEq ( e , k , areEqual , v ) and
215+ this .valueControlsEdge ( pred , succ , v )
216+ )
217+ }
218+
219+ /**
220+ * Holds if (determined by this guard) `left < right + k` must be `isLessThan` on the edge from
221+ * `pred` to `succ`. If `isLessThan = false` then this implies `left >= right + k`.
222+ */
223+ pragma [ inline]
224+ final predicate ensuresLtEdge (
225+ Expr left , Expr right , int k , BasicBlock pred , BasicBlock succ , boolean isLessThan
226+ ) {
227+ exists ( boolean testIsTrue |
228+ this .comparesLt ( left , right , k , isLessThan , testIsTrue ) and
229+ this .controlsEdge ( pred , succ , testIsTrue )
230+ )
231+ }
232+
233+ /**
234+ * Holds if (determined by this guard) `e < k` must be `isLessThan` on the edge from
235+ * `pred` to `succ`. If `isLessThan = false` then this implies `e >= k`.
236+ */
237+ pragma [ inline]
238+ final predicate ensuresLtEdge ( Expr e , int k , BasicBlock pred , BasicBlock succ , boolean isLessThan ) {
239+ exists ( AbstractValue v |
240+ this .comparesLt ( e , k , isLessThan , v ) and
241+ this .valueControlsEdge ( pred , succ , v )
242+ )
243+ }
178244}
179245
180246final class GuardCondition = GuardConditionImpl ;
@@ -187,6 +253,16 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardConditionImpl
187253 this .( BinaryLogicalOperation ) .getAnOperand ( ) instanceof GuardCondition
188254 }
189255
256+ override predicate valueControlsEdge ( BasicBlock pred , BasicBlock succ , AbstractValue v ) {
257+ exists ( BinaryLogicalOperation binop , GuardCondition lhs , GuardCondition rhs |
258+ this = binop and
259+ lhs = binop .getLeftOperand ( ) and
260+ rhs = binop .getRightOperand ( ) and
261+ lhs .valueControlsEdge ( pred , succ , v ) and
262+ rhs .valueControlsEdge ( pred , succ , v )
263+ )
264+ }
265+
190266 override predicate valueControls ( BasicBlock controlled , AbstractValue v ) {
191267 exists ( BinaryLogicalOperation binop , GuardCondition lhs , GuardCondition rhs |
192268 this = binop and
@@ -274,6 +350,25 @@ private predicate controlsBlock(IRGuardCondition ir, BasicBlock controlled, Abst
274350 )
275351}
276352
353+ /**
354+ * Holds if `ir` controls the `(pred, succ)` edge, meaning that the edge
355+ * `(pred, succ)` is only taken if the value of this condition is `v`. This
356+ * helper predicate does not necessarily hold for binary logical operations
357+ * like `&&` and `||`.
358+ * See the detailed explanation on predicate `controlsEdge`.
359+ */
360+ private predicate controlsEdge (
361+ IRGuardCondition ir , BasicBlock pred , BasicBlock succ , AbstractValue v
362+ ) {
363+ exists ( IRBlock irPred , IRBlock irSucc |
364+ ir .valueControlsEdge ( irPred , irSucc , v ) and
365+ nonExcludedIRAndBasicBlock ( irPred , pred ) and
366+ nonExcludedIRAndBasicBlock ( irSucc , succ ) and
367+ not isUnreachedBlock ( irPred ) and
368+ not isUnreachedBlock ( irSucc )
369+ )
370+ }
371+
277372private class GuardConditionFromNotExpr extends GuardConditionImpl {
278373 IRGuardCondition ir ;
279374
@@ -295,6 +390,10 @@ private class GuardConditionFromNotExpr extends GuardConditionImpl {
295390 controlsBlock ( ir , controlled , v .getDualValue ( ) )
296391 }
297392
393+ override predicate valueControlsEdge ( BasicBlock pred , BasicBlock succ , AbstractValue v ) {
394+ controlsEdge ( ir , pred , succ , v .getDualValue ( ) )
395+ }
396+
298397 pragma [ inline]
299398 override predicate comparesLt ( Expr left , Expr right , int k , boolean isLessThan , boolean testIsTrue ) {
300399 exists ( Instruction li , Instruction ri |
@@ -383,6 +482,10 @@ private class GuardConditionFromIR extends GuardConditionImpl {
383482 controlsBlock ( ir , controlled , v )
384483 }
385484
485+ override predicate valueControlsEdge ( BasicBlock pred , BasicBlock succ , AbstractValue v ) {
486+ controlsEdge ( ir , pred , succ , v )
487+ }
488+
386489 pragma [ inline]
387490 override predicate comparesLt ( Expr left , Expr right , int k , boolean isLessThan , boolean testIsTrue ) {
388491 exists ( Instruction li , Instruction ri |
0 commit comments