@@ -125,6 +125,20 @@ class GuardCondition extends Expr {
125
125
cached
126
126
predicate ensuresLt ( Expr left , Expr right , int k , BasicBlock block , boolean isLessThan ) { none ( ) }
127
127
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
+
128
142
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
129
143
cached
130
144
predicate comparesEq ( Expr left , Expr right , int k , boolean areEqual , boolean testIsTrue ) {
@@ -176,12 +190,27 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
176
190
)
177
191
}
178
192
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
+
179
202
override predicate ensuresLt ( Expr left , Expr right , int k , BasicBlock block , boolean isLessThan ) {
180
203
exists ( boolean testIsTrue |
181
204
this .comparesLt ( left , right , k , isLessThan , testIsTrue ) and this .controls ( block , testIsTrue )
182
205
)
183
206
}
184
207
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
+
185
214
override predicate comparesEq ( Expr left , Expr right , int k , boolean areEqual , boolean testIsTrue ) {
186
215
exists ( boolean partIsTrue , GuardCondition part |
187
216
this .( BinaryLogicalOperation ) .impliesValue ( part , partIsTrue , testIsTrue )
@@ -236,6 +265,17 @@ private class GuardConditionFromIR extends GuardCondition {
236
265
)
237
266
}
238
267
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
+
239
279
/**
240
280
* Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
241
281
* If `isLessThan = false` then this implies `left >= right + k`.
@@ -249,6 +289,18 @@ private class GuardConditionFromIR extends GuardCondition {
249
289
)
250
290
}
251
291
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
+
252
304
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
253
305
override predicate comparesEq ( Expr left , Expr right , int k , boolean areEqual , boolean testIsTrue ) {
254
306
exists ( Instruction li , Instruction ri |
@@ -462,6 +514,15 @@ class IRGuardCondition extends Instruction {
462
514
)
463
515
}
464
516
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
+
465
526
/**
466
527
* Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
467
528
* If `isLessThan = false` then this implies `left >= right + k`.
@@ -473,6 +534,17 @@ class IRGuardCondition extends Instruction {
473
534
)
474
535
}
475
536
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
+
476
548
/**
477
549
* Holds if (determined by this guard) `left < right + k` must be `isLessThan` on the edge from
478
550
* `pred` to `succ`. If `isLessThan = false` then this implies `left >= right + k`.
@@ -487,6 +559,18 @@ class IRGuardCondition extends Instruction {
487
559
)
488
560
}
489
561
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
+
490
574
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
491
575
cached
492
576
predicate comparesEq ( Operand left , Operand right , int k , boolean areEqual , boolean testIsTrue ) {
@@ -766,6 +850,24 @@ private predicate compares_lt(
766
850
)
767
851
}
768
852
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
+
769
871
/** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */
770
872
private predicate compares_ge (
771
873
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
796
898
k = 1
797
899
}
798
900
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
+
799
921
private predicate complex_lt (
800
922
CompareInstruction cmp , Operand left , Operand right , int k , boolean isLt , AbstractValue value
801
923
) {
@@ -804,6 +926,14 @@ private predicate complex_lt(
804
926
add_lt ( cmp , left , right , k , isLt , value )
805
927
}
806
928
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
+
807
937
// left - x < right + c => left < right + (c+x)
808
938
// left < (right - x) + c => left < right + (c-x)
809
939
private predicate sub_lt (
@@ -838,6 +968,22 @@ private predicate sub_lt(
838
968
)
839
969
}
840
970
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
+
841
987
// left + x < right + c => left < right + (c-x)
842
988
// left < (right + x) + c => left < right + (c+x)
843
989
private predicate add_lt (
@@ -884,6 +1030,28 @@ private predicate add_lt(
884
1030
)
885
1031
}
886
1032
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
+
887
1055
// left - x == right + c => left == right + (c+x)
888
1056
// left == (right - x) + c => left == right + (c-x)
889
1057
private predicate sub_eq (
0 commit comments