@@ -293,6 +293,50 @@ predicate analyzableDef(RangeSsaDefinition def, LocalScopeVariable v) {
293293 assignmentDef ( def , v , _) or defDependsOnDef ( def , v , _, _)
294294}
295295
296+ /**
297+ * Computes `x + y`, rounded towards +Inf. This is the general case where both
298+ * `x` and `y` may be large numbers.
299+ */
300+ bindingset [ x, y]
301+ private float addRoundingUp ( float x , float y ) {
302+ if ( x + y ) - x < y or ( x + y ) - y < x
303+ then result = ( x + y ) .nextUp ( )
304+ else result = ( x + y )
305+ }
306+
307+ /**
308+ * Computes `x + y`, rounded towards -Inf. This is the general case where both
309+ * `x` and `y` may be large numbers.
310+ */
311+ bindingset [ x, y]
312+ private float addRoundingDown ( float x , float y ) {
313+ if ( x + y ) - x > y or ( x + y ) - y > x
314+ then result = ( x + y ) .nextDown ( )
315+ else result = ( x + y )
316+ }
317+
318+ /**
319+ * Computes `x + small`, rounded towards +Inf, where `small` is a small
320+ * constant.
321+ */
322+ bindingset [ x, small]
323+ private float addRoundingUpSmall ( float x , float small ) {
324+ if ( x + small ) - x < small
325+ then result = ( x + small ) .nextUp ( )
326+ else result = ( x + small )
327+ }
328+
329+ /**
330+ * Computes `x + small`, rounded towards -Inf, where `small` is a small
331+ * constant.
332+ */
333+ bindingset [ x, small]
334+ private float addRoundingDownSmall ( float x , float small ) {
335+ if ( x + small ) - x > small
336+ then result = ( x + small ) .nextDown ( )
337+ else result = ( x + small )
338+ }
339+
296340/**
297341 * Gets the truncated lower bounds of the fully converted expression.
298342 */
@@ -469,20 +513,14 @@ float getLowerBoundsImpl(Expr expr) {
469513 exists ( AddExpr addExpr , float xLow , float yLow
470514 | expr = addExpr and
471515 xLow = getFullyConvertedLowerBounds ( addExpr .getLeftOperand ( ) ) and
472- yLow = getFullyConvertedLowerBounds ( addExpr .getRightOperand ( ) )
473- | // Make sure that we round towards -Inf, not to nearest.
474- if ( xLow + yLow ) - xLow > yLow or ( xLow + yLow ) - yLow > xLow
475- then result = ( xLow + yLow ) .nextDown ( )
476- else result = xLow + yLow )
516+ yLow = getFullyConvertedLowerBounds ( addExpr .getRightOperand ( ) ) and
517+ result = addRoundingDown ( xLow , yLow ) )
477518 or
478519 exists ( SubExpr subExpr , float xLow , float yHigh
479520 | expr = subExpr and
480521 xLow = getFullyConvertedLowerBounds ( subExpr .getLeftOperand ( ) ) and
481- yHigh = getFullyConvertedUpperBounds ( subExpr .getRightOperand ( ) )
482- | // Make sure that we round towards -Inf, not to nearest.
483- if ( xLow - yHigh ) - xLow > - yHigh or ( xLow - yHigh ) + yHigh > xLow
484- then result = ( xLow - yHigh ) .nextDown ( )
485- else result = xLow - yHigh )
522+ yHigh = getFullyConvertedUpperBounds ( subExpr .getRightOperand ( ) ) and
523+ result = addRoundingDown ( xLow , - yHigh ) )
486524 or
487525 exists ( PrefixIncrExpr incrExpr , float xLow
488526 | expr = incrExpr and
@@ -491,11 +529,8 @@ float getLowerBoundsImpl(Expr expr) {
491529 or
492530 exists ( PrefixDecrExpr decrExpr , float xLow
493531 | expr = decrExpr and
494- xLow = getFullyConvertedLowerBounds ( decrExpr .getOperand ( ) )
495- | // Make sure that we round towards -Inf, not to nearest.
496- if ( xLow - 1 ) - xLow > - 1
497- then result = ( xLow - 1 ) .nextDown ( )
498- else result = xLow - 1 )
532+ xLow = getFullyConvertedLowerBounds ( decrExpr .getOperand ( ) ) and
533+ result = addRoundingDownSmall ( xLow , - 1 ) )
499534 or
500535 // `PostfixIncrExpr` and `PostfixDecrExpr` return the value of their
501536 // operand. The incrementing/decrementing behavior is handled in
@@ -600,28 +635,19 @@ float getUpperBoundsImpl(Expr expr) {
600635 exists ( AddExpr addExpr , float xHigh , float yHigh
601636 | expr = addExpr and
602637 xHigh = getFullyConvertedUpperBounds ( addExpr .getLeftOperand ( ) ) and
603- yHigh = getFullyConvertedUpperBounds ( addExpr .getRightOperand ( ) )
604- | // Make sure that we round towards +Inf, not to nearest.
605- if ( xHigh + yHigh ) - xHigh < yHigh or ( xHigh + yHigh ) - yHigh < xHigh
606- then result = ( xHigh + yHigh ) .nextUp ( )
607- else result = xHigh + yHigh )
638+ yHigh = getFullyConvertedUpperBounds ( addExpr .getRightOperand ( ) ) and
639+ result = addRoundingUp ( xHigh , yHigh ) )
608640 or
609641 exists ( SubExpr subExpr , float xHigh , float yLow
610642 | expr = subExpr and
611643 xHigh = getFullyConvertedUpperBounds ( subExpr .getLeftOperand ( ) ) and
612- yLow = getFullyConvertedLowerBounds ( subExpr .getRightOperand ( ) )
613- | // Make sure that we round towards +Inf, not to nearest.
614- if ( xHigh - yLow ) - xHigh < - yLow or ( xHigh - yLow ) + yLow < xHigh
615- then result = ( xHigh - yLow ) .nextUp ( )
616- else result = xHigh - yLow )
644+ yLow = getFullyConvertedLowerBounds ( subExpr .getRightOperand ( ) ) and
645+ result = addRoundingUp ( xHigh , - yLow ) )
617646 or
618647 exists ( PrefixIncrExpr incrExpr , float xHigh
619648 | expr = incrExpr and
620- xHigh = getFullyConvertedUpperBounds ( incrExpr .getOperand ( ) )
621- | // Make sure that we round towards +Inf, not to nearest.
622- if ( xHigh + 1 ) - xHigh < 1
623- then result = ( xHigh + 1 ) .nextUp ( )
624- else result = xHigh + 1 )
649+ xHigh = getFullyConvertedUpperBounds ( incrExpr .getOperand ( ) ) and
650+ result = addRoundingUpSmall ( xHigh , 1 ) )
625651 or
626652 exists ( PrefixDecrExpr decrExpr , float xHigh
627653 | expr = decrExpr and
@@ -813,22 +839,16 @@ float getDefLowerBoundsImpl(RangeSsaDefinition def, LocalScopeVariable v) {
813839 | def = assignAdd and
814840 assignAdd .getLValue ( ) = nextDef .getAUse ( v ) and
815841 lhsLB = getDefLowerBounds ( nextDef , v ) and
816- rhsLB = getFullyConvertedLowerBounds ( assignAdd .getRValue ( ) )
817- | // Make sure that we round towards -Inf, not to nearest.
818- if ( lhsLB + rhsLB ) - lhsLB > rhsLB or ( lhsLB + rhsLB ) - rhsLB > lhsLB
819- then result = ( lhsLB + rhsLB ) .nextDown ( )
820- else result = lhsLB + rhsLB )
842+ rhsLB = getFullyConvertedLowerBounds ( assignAdd .getRValue ( ) ) and
843+ result = addRoundingDown ( lhsLB , rhsLB ) )
821844 or
822845 exists (
823846 AssignSubExpr assignSub , RangeSsaDefinition nextDef , float lhsLB , float rhsUB
824847 | def = assignSub and
825848 assignSub .getLValue ( ) = nextDef .getAUse ( v ) and
826849 lhsLB = getDefLowerBounds ( nextDef , v ) and
827- rhsUB = getFullyConvertedUpperBounds ( assignSub .getRValue ( ) )
828- | // Make sure that we round towards -Inf, not to nearest.
829- if ( lhsLB - rhsUB ) - lhsLB > - rhsUB or ( lhsLB - rhsUB ) + rhsUB > lhsLB
830- then result = ( lhsLB - rhsUB ) .nextDown ( )
831- else result = lhsLB - rhsUB )
850+ rhsUB = getFullyConvertedUpperBounds ( assignSub .getRValue ( ) ) and
851+ result = addRoundingDown ( lhsLB , - rhsUB ) )
832852 or
833853 exists ( IncrementOperation incr , float newLB
834854 | def = incr and
@@ -839,11 +859,8 @@ float getDefLowerBoundsImpl(RangeSsaDefinition def, LocalScopeVariable v) {
839859 exists ( DecrementOperation decr , float newLB
840860 | def = decr and
841861 decr .getOperand ( ) = v .getAnAccess ( ) and
842- newLB = getFullyConvertedLowerBounds ( decr .getOperand ( ) )
843- | // Make sure that we round towards -Inf, not to nearest.
844- if ( newLB - 1 ) - newLB > - 1
845- then result = ( newLB - 1 ) .nextDown ( )
846- else result = newLB - 1 )
862+ newLB = getFullyConvertedLowerBounds ( decr .getOperand ( ) ) and
863+ result = addRoundingDownSmall ( newLB , - 1 ) )
847864 or
848865 // Phi nodes.
849866 result = getPhiLowerBounds ( v , def )
@@ -865,31 +882,22 @@ float getDefUpperBoundsImpl(RangeSsaDefinition def, LocalScopeVariable v) {
865882 | def = assignAdd and
866883 assignAdd .getLValue ( ) = nextDef .getAUse ( v ) and
867884 lhsUB = getDefUpperBounds ( nextDef , v ) and
868- rhsUB = getFullyConvertedUpperBounds ( assignAdd .getRValue ( ) )
869- | // Make sure that we round towards +Inf, not to nearest.
870- if ( lhsUB + rhsUB ) - lhsUB < rhsUB or ( lhsUB + rhsUB ) - rhsUB < lhsUB
871- then result = ( lhsUB + rhsUB ) .nextUp ( )
872- else result = lhsUB + rhsUB )
885+ rhsUB = getFullyConvertedUpperBounds ( assignAdd .getRValue ( ) ) and
886+ result = addRoundingUp ( lhsUB , rhsUB ) )
873887 or
874888 exists (
875889 AssignSubExpr assignSub , RangeSsaDefinition nextDef , float lhsUB , float rhsLB
876890 | def = assignSub and
877891 assignSub .getLValue ( ) = nextDef .getAUse ( v ) and
878892 lhsUB = getDefUpperBounds ( nextDef , v ) and
879- rhsLB = getFullyConvertedLowerBounds ( assignSub .getRValue ( ) )
880- | // Make sure that we round towards +Inf, not to nearest.
881- if ( lhsUB - rhsLB ) - lhsUB < - rhsLB or ( lhsUB - rhsLB ) + rhsLB < lhsUB
882- then result = ( lhsUB - rhsLB ) .nextUp ( )
883- else result = lhsUB - rhsLB )
893+ rhsLB = getFullyConvertedLowerBounds ( assignSub .getRValue ( ) ) and
894+ result = addRoundingUp ( lhsUB , - rhsLB ) )
884895 or
885896 exists ( IncrementOperation incr , float newUB
886897 | def = incr and
887898 incr .getOperand ( ) = v .getAnAccess ( ) and
888- newUB = getFullyConvertedUpperBounds ( incr .getOperand ( ) )
889- | // Make sure that we round towards +Inf, not to nearest.
890- if ( newUB + 1 ) - newUB < 1
891- then result = ( newUB + 1 ) .nextUp ( )
892- else result = newUB + 1 )
899+ newUB = getFullyConvertedUpperBounds ( incr .getOperand ( ) ) and
900+ result = addRoundingUpSmall ( newUB , 1 ) )
893901 or
894902 exists ( DecrementOperation decr , float newUB
895903 | def = decr and
0 commit comments