@@ -125,6 +125,20 @@ class GuardCondition extends Expr {
125125 cached
126126 predicate ensuresLt ( Expr left , Expr right , int k , BasicBlock block , boolean isLessThan ) { none ( ) }
127127
128+ /**
129+ * Holds if (determined by this guard) `e < k` evaluates to `isLessThan` if
130+ * this expression evaluates to `value`.
131+ */
132+ cached
133+ predicate comparesLt ( Expr e , int k , boolean isLessThan , AbstractValue value ) { none ( ) }
134+
135+ /**
136+ * Holds if (determined by this guard) `e < k` must be `isLessThan` in `block`.
137+ * If `isLessThan = false` then this implies `left >= k`.
138+ */
139+ cached
140+ predicate ensuresLt ( Expr e , int k , BasicBlock block , boolean isLessThan ) { none ( ) }
141+
128142 /** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
129143 cached
130144 predicate comparesEq ( Expr left , Expr right , int k , boolean areEqual , boolean testIsTrue ) {
@@ -176,12 +190,27 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
176190 )
177191 }
178192
193+ override predicate comparesLt ( Expr e , int k , boolean isLessThan , AbstractValue value ) {
194+ exists ( BooleanValue partValue , GuardCondition part |
195+ this .( BinaryLogicalOperation )
196+ .impliesValue ( part , partValue .getValue ( ) , value .( BooleanValue ) .getValue ( ) )
197+ |
198+ part .comparesLt ( e , k , isLessThan , partValue )
199+ )
200+ }
201+
179202 override predicate ensuresLt ( Expr left , Expr right , int k , BasicBlock block , boolean isLessThan ) {
180203 exists ( boolean testIsTrue |
181204 this .comparesLt ( left , right , k , isLessThan , testIsTrue ) and this .controls ( block , testIsTrue )
182205 )
183206 }
184207
208+ override predicate ensuresLt ( Expr e , int k , BasicBlock block , boolean isLessThan ) {
209+ exists ( AbstractValue value |
210+ this .comparesLt ( e , k , isLessThan , value ) and this .valueControls ( block , value )
211+ )
212+ }
213+
185214 override predicate comparesEq ( Expr left , Expr right , int k , boolean areEqual , boolean testIsTrue ) {
186215 exists ( boolean partIsTrue , GuardCondition part |
187216 this .( BinaryLogicalOperation ) .impliesValue ( part , partIsTrue , testIsTrue )
@@ -236,6 +265,17 @@ private class GuardConditionFromIR extends GuardCondition {
236265 )
237266 }
238267
268+ /**
269+ * Holds if (determined by this guard) `e < k` evaluates to `isLessThan` if
270+ * this expression evaluates to `value`.
271+ */
272+ override predicate comparesLt ( Expr e , int k , boolean isLessThan , AbstractValue value ) {
273+ exists ( Instruction i |
274+ i .getUnconvertedResultExpression ( ) = e and
275+ ir .comparesLt ( i .getAUse ( ) , k , isLessThan , value )
276+ )
277+ }
278+
239279 /**
240280 * Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
241281 * If `isLessThan = false` then this implies `left >= right + k`.
@@ -249,6 +289,18 @@ private class GuardConditionFromIR extends GuardCondition {
249289 )
250290 }
251291
292+ /**
293+ * Holds if (determined by this guard) `e < k` must be `isLessThan` in `block`.
294+ * If `isLessThan = false` then this implies `e >= k`.
295+ */
296+ override predicate ensuresLt ( Expr e , int k , BasicBlock block , boolean isLessThan ) {
297+ exists ( Instruction i , AbstractValue value |
298+ i .getUnconvertedResultExpression ( ) = e and
299+ ir .comparesLt ( i .getAUse ( ) , k , isLessThan , value ) and
300+ this .valueControls ( block , value )
301+ )
302+ }
303+
252304 /** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
253305 override predicate comparesEq ( Expr left , Expr right , int k , boolean areEqual , boolean testIsTrue ) {
254306 exists ( Instruction li , Instruction ri |
@@ -462,6 +514,15 @@ class IRGuardCondition extends Instruction {
462514 )
463515 }
464516
517+ /**
518+ * Holds if (determined by this guard) `op < k` evaluates to `isLessThan` if
519+ * this expression evaluates to `value`.
520+ */
521+ cached
522+ predicate comparesLt ( Operand op , int k , boolean isLessThan , AbstractValue value ) {
523+ compares_lt ( this , op , k , isLessThan , value )
524+ }
525+
465526 /**
466527 * Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
467528 * If `isLessThan = false` then this implies `left >= right + k`.
@@ -473,6 +534,17 @@ class IRGuardCondition extends Instruction {
473534 )
474535 }
475536
537+ /**
538+ * Holds if (determined by this guard) `op < k` must be `isLessThan` in `block`.
539+ * If `isLessThan = false` then this implies `op >= k`.
540+ */
541+ cached
542+ predicate ensuresLt ( Operand op , int k , IRBlock block , boolean isLessThan ) {
543+ exists ( AbstractValue value |
544+ compares_lt ( this , op , k , isLessThan , value ) and this .valueControls ( block , value )
545+ )
546+ }
547+
476548 /**
477549 * Holds if (determined by this guard) `left < right + k` must be `isLessThan` on the edge from
478550 * `pred` to `succ`. If `isLessThan = false` then this implies `left >= right + k`.
@@ -487,6 +559,18 @@ class IRGuardCondition extends Instruction {
487559 )
488560 }
489561
562+ /**
563+ * Holds if (determined by this guard) `op < k` must be `isLessThan` on the edge from
564+ * `pred` to `succ`. If `isLessThan = false` then this implies `op >= k`.
565+ */
566+ cached
567+ predicate ensuresLtEdge ( Operand left , int k , IRBlock pred , IRBlock succ , boolean isLessThan ) {
568+ exists ( AbstractValue value |
569+ compares_lt ( this , left , k , isLessThan , value ) and
570+ this .valueControlsEdge ( pred , succ , value )
571+ )
572+ }
573+
490574 /** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
491575 cached
492576 predicate comparesEq ( Operand left , Operand right , int k , boolean areEqual , boolean testIsTrue ) {
@@ -766,6 +850,24 @@ private predicate compares_lt(
766850 )
767851}
768852
853+ /** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
854+ private predicate compares_lt ( Instruction test , Operand op , int k , boolean isLt , AbstractValue value ) {
855+ simple_comparison_lt ( test , op , k , isLt , value )
856+ or
857+ complex_lt ( test , op , k , isLt , value )
858+ or
859+ /* (x is true => (op < k)) => (!x is false => (op < k)) */
860+ exists ( AbstractValue dual | value = dual .getDualValue ( ) |
861+ compares_lt ( test .( LogicalNotInstruction ) .getUnary ( ) , op , k , isLt , dual )
862+ )
863+ or
864+ exists ( int k1 , int k2 , ConstantInstruction const |
865+ compares_lt ( test , op , const .getAUse ( ) , k2 , isLt , value ) and
866+ int_value ( const ) = k1 and
867+ k = k1 + k2
868+ )
869+ }
870+
769871/** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */
770872private predicate compares_ge (
771873 Instruction test , Operand left , Operand right , int k , boolean isGe , AbstractValue value
@@ -796,6 +898,26 @@ private predicate simple_comparison_lt(CompareInstruction cmp, Operand left, Ope
796898 k = 1
797899}
798900
901+ /** Rearrange various simple comparisons into `op < k` form. */
902+ private predicate simple_comparison_lt (
903+ Instruction test , Operand op , int k , boolean isLt , AbstractValue value
904+ ) {
905+ exists ( SwitchInstruction switch , CaseEdge case |
906+ test = switch .getExpression ( ) and
907+ op .getDef ( ) = test and
908+ case = value .( MatchValue ) .getCase ( ) and
909+ exists ( switch .getSuccessor ( case ) ) and
910+ case .getMaxValue ( ) > case .getMinValue ( )
911+ |
912+ // op <= k => op < k - 1
913+ isLt = true and
914+ case .getMaxValue ( ) .toInt ( ) = k - 1
915+ or
916+ isLt = false and
917+ case .getMinValue ( ) .toInt ( ) = k
918+ )
919+ }
920+
799921private predicate complex_lt (
800922 CompareInstruction cmp , Operand left , Operand right , int k , boolean isLt , AbstractValue value
801923) {
@@ -804,6 +926,14 @@ private predicate complex_lt(
804926 add_lt ( cmp , left , right , k , isLt , value )
805927}
806928
929+ private predicate complex_lt (
930+ Instruction test , Operand left , int k , boolean isLt , AbstractValue value
931+ ) {
932+ sub_lt ( test , left , k , isLt , value )
933+ or
934+ add_lt ( test , left , k , isLt , value )
935+ }
936+
807937// left - x < right + c => left < right + (c+x)
808938// left < (right - x) + c => left < right + (c-x)
809939private predicate sub_lt (
@@ -838,6 +968,22 @@ private predicate sub_lt(
838968 )
839969}
840970
971+ private predicate sub_lt ( Instruction test , Operand left , int k , boolean isLt , AbstractValue value ) {
972+ exists ( SubInstruction lhs , int c , int x |
973+ compares_lt ( test , lhs .getAUse ( ) , c , isLt , value ) and
974+ left = lhs .getLeftOperand ( ) and
975+ x = int_value ( lhs .getRight ( ) ) and
976+ k = c + x
977+ )
978+ or
979+ exists ( PointerSubInstruction lhs , int c , int x |
980+ compares_lt ( test , lhs .getAUse ( ) , c , isLt , value ) and
981+ left = lhs .getLeftOperand ( ) and
982+ x = int_value ( lhs .getRight ( ) ) and
983+ k = c + x
984+ )
985+ }
986+
841987// left + x < right + c => left < right + (c-x)
842988// left < (right + x) + c => left < right + (c+x)
843989private predicate add_lt (
@@ -884,6 +1030,28 @@ private predicate add_lt(
8841030 )
8851031}
8861032
1033+ private predicate add_lt ( Instruction test , Operand left , int k , boolean isLt , AbstractValue value ) {
1034+ exists ( AddInstruction lhs , int c , int x |
1035+ compares_lt ( test , lhs .getAUse ( ) , c , isLt , value ) and
1036+ (
1037+ left = lhs .getLeftOperand ( ) and x = int_value ( lhs .getRight ( ) )
1038+ or
1039+ left = lhs .getRightOperand ( ) and x = int_value ( lhs .getLeft ( ) )
1040+ ) and
1041+ k = c - x
1042+ )
1043+ or
1044+ exists ( PointerAddInstruction lhs , int c , int x |
1045+ compares_lt ( test , lhs .getAUse ( ) , c , isLt , value ) and
1046+ (
1047+ left = lhs .getLeftOperand ( ) and x = int_value ( lhs .getRight ( ) )
1048+ or
1049+ left = lhs .getRightOperand ( ) and x = int_value ( lhs .getLeft ( ) )
1050+ ) and
1051+ k = c - x
1052+ )
1053+ }
1054+
8871055// left - x == right + c => left == right + (c+x)
8881056// left == (right - x) + c => left == right + (c-x)
8891057private predicate sub_eq (
0 commit comments