@@ -119,13 +119,26 @@ module RangeAnalysis {
119119 result = expr .flow ( )
120120 }
121121
122+ /**
123+ * A 30-bit integer.
124+ *
125+ * Adding two such integers is guaranteed not to overflow. We simply omit constraints
126+ * whose parameters would exceed this range.
127+ */
128+ private class Bias extends int {
129+ bindingset [ this ]
130+ Bias ( ) {
131+ - 536870912 < this and this < 536870912
132+ }
133+ }
134+
122135 /**
123136 * Holds if `r` can be modelled as `r = root * sign + bias`.
124137 *
125138 * Only looks "one step", that is, does not follow data flow and does not recursively
126139 * unfold nested arithmetic expressions.
127140 */
128- private predicate linearDefinitionStep ( DataFlow:: Node r , DataFlow:: Node root , int sign , int bias ) {
141+ private predicate linearDefinitionStep ( DataFlow:: Node r , DataFlow:: Node root , int sign , Bias bias ) {
129142 not exists ( r .asExpr ( ) .getIntValue ( ) ) and
130143 (
131144 exists ( AddExpr expr | r .asExpr ( ) = expr |
@@ -183,7 +196,7 @@ module RangeAnalysis {
183196 /**
184197 * Holds if `r` can be modelled as `r = root * sign + bias`.
185198 */
186- predicate linearDefinition ( DataFlow:: Node r , DataFlow:: Node root , int sign , int bias ) {
199+ predicate linearDefinition ( DataFlow:: Node r , DataFlow:: Node root , int sign , Bias bias ) {
187200 if hasUniquePredecessor ( r ) then
188201 linearDefinition ( r .getAPredecessor ( ) , root , sign , bias )
189202 else if linearDefinitionStep ( r , _, _, _) then
@@ -202,7 +215,7 @@ module RangeAnalysis {
202215 /**
203216 * Holds if `r` can be modelled as `r = xroot * xsign + yroot * ysign + bias`.
204217 */
205- predicate linearDefinitionSum ( DataFlow:: Node r , DataFlow:: Node xroot , int xsign , DataFlow:: Node yroot , int ysign , int bias ) {
218+ predicate linearDefinitionSum ( DataFlow:: Node r , DataFlow:: Node xroot , int xsign , DataFlow:: Node yroot , int ysign , Bias bias ) {
206219 if hasUniquePredecessor ( r ) then
207220 linearDefinitionSum ( r .getAPredecessor ( ) , xroot , xsign , yroot , ysign , bias )
208221 else if exists ( r .asExpr ( ) .getIntValue ( ) ) then
@@ -225,7 +238,7 @@ module RangeAnalysis {
225238 /**
226239 * Holds if the given comparison can be modelled as `A <op> B + bias` where `<op>` is the comparison operator.
227240 */
228- predicate linearComparison ( Comparison comparison , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int bias ) {
241+ predicate linearComparison ( Comparison comparison , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , Bias bias ) {
229242 exists ( Expr left , Expr right , int bias1 , int bias2 | left = comparison .getLeftOperand ( ) and right = comparison .getRightOperand ( ) |
230243 // A <= B + c
231244 linearDefinition ( left .flow ( ) , a , asign , bias1 ) and
@@ -247,7 +260,7 @@ module RangeAnalysis {
247260 /**
248261 * Holds if `guard` asserts that the outcome of `A <op> B + bias` is true, where `<op>` is a comparison operator.
249262 */
250- predicate linearComparisonGuard ( ConditionGuardNode guard , DataFlow:: Node a , int asign , string operator , DataFlow:: Node b , int bsign , int bias ) {
263+ predicate linearComparisonGuard ( ConditionGuardNode guard , DataFlow:: Node a , int asign , string operator , DataFlow:: Node b , int bsign , Bias bias ) {
251264 exists ( Comparison compare | compare = getDefinition ( guard .getTest ( ) .flow ( ) ) .asExpr ( ) |
252265 linearComparison ( compare , a , asign , b , bsign , bias ) and
253266 (
@@ -279,7 +292,7 @@ module RangeAnalysis {
279292 *
280293 * The dual constraint `-B <= -A + c` is not included in this predicate.
281294 */
282- predicate comparisonEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int bias , boolean sharp ) {
295+ predicate comparisonEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , Bias bias , boolean sharp ) {
283296 // A <= B + c
284297 linearComparisonGuard ( cfg , a , asign , "<=" , b , bsign , bias ) and
285298 sharp = false
@@ -321,14 +334,14 @@ module RangeAnalysis {
321334 /**
322335 * Holds if `A <= B + c` can be determined based on a phi node.
323336 */
324- predicate phiEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c ) {
337+ predicate phiEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , Bias c ) {
325338 exists ( DataFlow:: Node phi , DataFlow:: Node left , DataFlow:: Node right |
326339 binaryPhiNode ( phi , left , right ) and
327340 cfg = phi .getBasicBlock ( )
328341 |
329342 // Both inputs are defined in terms of the same root:
330343 // phi = PHI(root + bias1, root + bias2)
331- exists ( DataFlow:: Node root , int sign , int bias1 , int bias2 |
344+ exists ( DataFlow:: Node root , int sign , Bias bias1 , Bias bias2 |
332345 linearDefinition ( left , root , sign , bias1 ) and
333346 linearDefinition ( right , root , sign , bias2 ) and
334347 bias1 < bias2 and
@@ -348,7 +361,7 @@ module RangeAnalysis {
348361 or
349362 // One input is defined in terms of the phi node itself:
350363 // phi = PHI(phi + increment, x)
351- exists ( int increment , DataFlow:: Node root , int sign , int bias |
364+ exists ( int increment , DataFlow:: Node root , int sign , Bias bias |
352365 linearDefinition ( left , phi , 1 , increment ) and
353366 linearDefinition ( right , root , sign , bias ) and
354367 (
@@ -378,8 +391,9 @@ module RangeAnalysis {
378391 * A + A <= 2c becomes A <= -A + 2c
379392 * A + A >= 2c becomes -A <= A - 2c
380393 */
381- predicate constantEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c ) {
394+ predicate constantEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , Bias c ) {
382395 exists ( NumberLiteral literal | cfg = literal |
396+ literal .getIntValue ( ) instanceof Bias and // avoid overflow
383397 a = literal .flow ( ) and
384398 b = a and
385399 ( asign = 1 or asign = - 1 ) and
@@ -390,7 +404,7 @@ module RangeAnalysis {
390404 /**
391405 * The set of initial edges including those from dual constraints.
392406 */
393- private predicate seedEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c , boolean sharp ) {
407+ predicate seedEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , Bias c , boolean sharp ) {
394408 // A <= B + c
395409 comparisonEdge ( cfg , a , asign , b , bsign , c , sharp )
396410 or
@@ -399,7 +413,7 @@ module RangeAnalysis {
399413 constantEdge ( cfg , a , asign , b , bsign , c ) and sharp = false
400414 }
401415
402- private predicate seedEdgeWithDual ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c , boolean sharp ) {
416+ private predicate seedEdgeWithDual ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , Bias c , boolean sharp ) {
403417 // A <= B + c
404418 seedEdge ( cfg , a , asign , b , bsign , c , sharp )
405419 or
@@ -452,10 +466,10 @@ module RangeAnalysis {
452466 *
453467 * This means negative-weight cycles (contradictions) can be detected using simple cycle detection.
454468 */
455- private predicate extendedEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c , boolean sharp ) {
469+ private predicate extendedEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , Bias c , boolean sharp ) {
456470 seedEdgeWithDual ( cfg , a , asign , b , bsign , c , sharp )
457471 or
458- exists ( DataFlow:: Node mid , int midx , ControlFlowNode cfg1 , int c1 , ControlFlowNode cfg2 , int c2 , boolean sharp1 , boolean sharp2 |
472+ exists ( DataFlow:: Node mid , int midx , ControlFlowNode cfg1 , Bias c1 , ControlFlowNode cfg2 , Bias c2 , boolean sharp1 , boolean sharp2 |
459473 extendedEdge ( cfg1 , a , asign , mid , midx , c1 , sharp1 ) and
460474 extendedEdge ( cfg2 , mid , midx , b , bsign , c2 , sharp2 ) and
461475 sharp = sharp1 .booleanOr ( sharp2 ) and
0 commit comments