11/**
22 * Provides classes and predicates for range analysis.
33 *
4- * An inferred bound can either be a specific integer or the abstract value of
5- * an IR `Instruction`.
4+ * An inferred bound can either be a specific integer or a `ValueNumber`
5+ * representing the abstract value of a set of `Instruction`s .
66 *
77 * If an inferred bound relies directly on a condition, then this condition is
88 * reported as the reason for the bound.
99 */
1010
11- // TODO: update the following comment
1211/*
1312 * This library tackles range analysis as a flow problem. Consider e.g.:
1413 * ```
2120 * arr.length --> len = .. --> x < len --> x-1 --> y = .. --> y
2221 * ```
2322 *
24- * In its simplest form the step relation `E1 --> E2 ` relates two expressions
25- * such that `E1 <= B` implies `E2 <= B` for any `B` (with a second separate
23+ * In its simplest form the step relation `I1 --> I2 ` relates two `Instruction`s
24+ * such that `I1 <= B` implies `I2 <= B` for any `B` (with a second separate
2625 * step relation handling lower bounds). Examples of such steps include
27- * assignments `E2 = E1 ` and conditions `x <= E1 ` where `E2 ` is a use of `x`
26+ * assignments `I2 = I1 ` and conditions `x <= I1 ` where `I2 ` is a use of `x`
2827 * guarded by the condition.
2928 *
3029 * In order to handle subtractions and additions with constants, and strict
3130 * comparisons, the step relation is augmented with an integer delta. With this
32- * generalization `E1 --(delta)--> E2 ` relates two expressions and an integer
33- * such that `E1 <= B` implies `E2 <= B + delta` for any `B`. This corresponds
31+ * generalization `I1 --(delta)--> I2 ` relates two `Instruction`s and an integer
32+ * such that `I1 <= B` implies `I2 <= B + delta` for any `B`. This corresponds
3433 * to the predicate `boundFlowStep`.
3534 *
3635 * The complete range analysis is then implemented as the transitive closure of
37- * the step relation summing the deltas along the way. If `E1 ` transitively
38- * steps to `E2 `, `delta` is the sum of deltas along the path, and `B` is an
39- * interesting bound equal to the value of `E1 ` then `E2 <= B + delta`. This
40- * corresponds to the predicate `bounded `.
36+ * the step relation summing the deltas along the way. If `I1 ` transitively
37+ * steps to `I2 `, `delta` is the sum of deltas along the path, and `B` is an
38+ * interesting bound equal to the value of `I1 ` then `I2 <= B + delta`. This
39+ * corresponds to the predicate `boundedInstruction `.
4140 *
41+ * Bounds come in two forms: either they are relative to zero (and thus provide
42+ * a constant bound), or they are relative to some program value. This value is
43+ * represented by the `ValueNumber` class, each instance of which represents a
44+ * set of `Instructions` that must have the same value.
45+ *
4246 * Phi nodes need a little bit of extra handling. Consider `x0 = phi(x1, x2)`.
4347 * There are essentially two cases:
4448 * - If `x1 <= B + d1` and `x2 <= B + d2` then `x0 <= B + max(d1,d2)`.
@@ -121,8 +125,8 @@ import RangeAnalysisPublic
121125 * Gets a condition that tests whether `vn` equals `bound + delta`.
122126 *
123127 * If the condition evaluates to `testIsTrue`:
124- * - `isEq = true` : `i == bound + delta`
125- * - `isEq = false` : `i != bound + delta`
128+ * - `isEq = true` : `vn == bound + delta`
129+ * - `isEq = false` : `vn != bound + delta`
126130 */
127131private IRGuardCondition eqFlowCond ( ValueNumber vn , Operand bound , int delta ,
128132 boolean isEq , boolean testIsTrue )
@@ -138,11 +142,6 @@ private IRGuardCondition eqFlowCond(ValueNumber vn, Operand bound, int delta,
138142private predicate boundFlowStepSsa (
139143 NonPhiOperand op2 , Operand op1 , int delta , boolean upper , Reason reason
140144) {
141- /*op2.getDefinitionInstruction().getAnOperand().(CopySourceOperand) = op1 and
142- (upper = true or upper = false) and
143- reason = TNoReason() and
144- delta = 0
145- or*/
146145 exists ( IRGuardCondition guard , boolean testIsTrue |
147146 guard = boundFlowCond ( valueNumberOfOperand ( op2 ) , op1 , delta , upper , testIsTrue ) and
148147 guard .controls ( op2 .getInstruction ( ) .getBlock ( ) , testIsTrue ) and
@@ -170,7 +169,6 @@ private IRGuardCondition boundFlowCond(ValueNumber vn, NonPhiOperand bound, int
170169 or
171170 result = eqFlowCond ( vn , bound , delta , true , testIsTrue ) and
172171 ( upper = true or upper = false )
173- // TODO: strengthening through modulus library
174172}
175173
176174private newtype TReason =
@@ -213,7 +211,6 @@ private predicate safeCast(IntegralType fromtyp, IntegralType totyp) {
213211 fromtyp .isUnsigned ( ) and
214212 totyp .isUnsigned ( )
215213 )
216- // TODO: infer safety using sign analysis?
217214}
218215
219216private class SafeCastInstruction extends ConvertInstruction {
@@ -357,7 +354,7 @@ private predicate boundedNonPhiOperand(NonPhiOperand op, Bound b, int delta, boo
357354 boundedInstruction ( op .getDefinitionInstruction ( ) , b , delta , upper , fromBackEdge , origdelta , reason )
358355 or
359356 exists ( int d , Reason r1 , Reason r2 |
360- boundedInstruction ( op . getDefinitionInstruction ( ) , b , d , upper , fromBackEdge , origdelta , r2 )
357+ boundedNonPhiOperand ( op , b , d , upper , fromBackEdge , origdelta , r2 )
361358 |
362359 unequalOperand ( op , b , d , r1 ) and
363360 (
@@ -426,13 +423,13 @@ private predicate boundedPhiOperand(
426423 )
427424}
428425
429- /** Holds if `v != e + delta` at `pos`. */
426+ /** Holds if `op2 != op1 + delta` at `pos`. */
430427private predicate unequalFlowStep (
431- Operand op1 , Operand op2 , int delta , Reason reason
428+ Operand op2 , Operand op1 , int delta , Reason reason
432429) {
433430 exists ( IRGuardCondition guard , boolean testIsTrue |
434- guard = eqFlowCond ( valueNumberOfOperand ( op1 ) , op2 , delta , false , testIsTrue ) and
435- guard .controls ( op1 .getInstruction ( ) .getBlock ( ) , testIsTrue ) and
431+ guard = eqFlowCond ( valueNumberOfOperand ( op2 ) , op1 , delta , false , testIsTrue ) and
432+ guard .controls ( op2 .getInstruction ( ) .getBlock ( ) , testIsTrue ) and
436433 reason = TCondReason ( guard )
437434 )
438435}
@@ -442,9 +439,9 @@ private predicate unequalFlowStep(
442439 */
443440private predicate unequalOperand ( Operand op , Bound b , int delta , Reason reason ) {
444441 exists ( Operand op2 , int d1 , int d2 |
445- unequalFlowStep ( op , op2 , delta , reason ) and
446- boundedNonPhiOperand ( op2 , b , d2 , true , _, _, _) and
442+ unequalFlowStep ( op , op2 , d1 , reason ) and
447443 boundedNonPhiOperand ( op2 , b , d2 , true , _, _, _) and
444+ boundedNonPhiOperand ( op2 , b , d2 , false , _, _, _) and
448445 delta = d1 + d2
449446 )
450447}
0 commit comments