@@ -1160,6 +1160,17 @@ private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
11601160 if guardLB > defLB then result = guardLB else result = defLB
11611161 )
11621162 or
1163+ exists ( VariableAccess access , float neConstant , float lower |
1164+ isNEPhi ( v , phi , access , neConstant ) and
1165+ lower = getFullyConvertedLowerBounds ( access ) and
1166+ if lower = neConstant then result = lower + 1 else result = lower
1167+ )
1168+ or
1169+ exists ( VariableAccess access |
1170+ isUnsupportedGuardPhi ( v , phi , access ) and
1171+ result = getFullyConvertedLowerBounds ( access )
1172+ )
1173+ or
11631174 result = getDefLowerBounds ( phi .getAPhiInput ( v ) , v )
11641175}
11651176
@@ -1177,6 +1188,17 @@ private float getPhiUpperBounds(StackVariable v, RangeSsaDefinition phi) {
11771188 if guardUB < defUB then result = guardUB else result = defUB
11781189 )
11791190 or
1191+ exists ( VariableAccess access , float neConstant , float upper |
1192+ isNEPhi ( v , phi , access , neConstant ) and
1193+ upper = getFullyConvertedUpperBounds ( access ) and
1194+ if upper = neConstant then result = upper - 1 else result = upper
1195+ )
1196+ or
1197+ exists ( VariableAccess access |
1198+ isUnsupportedGuardPhi ( v , phi , access ) and
1199+ result = getFullyConvertedUpperBounds ( access )
1200+ )
1201+ or
11801202 result = getDefUpperBounds ( phi .getAPhiInput ( v ) , v )
11811203}
11821204
@@ -1501,22 +1523,13 @@ private predicate linearBoundFromGuard(
15011523 // 1. x <= upperbound(RHS)
15021524 // 2. x >= lowerbound(RHS)
15031525 //
1504- // For x != RHS, we create trivial bounds:
1505- //
1506- // 1. x <= typeUpperBound(RHS.getUnspecifiedType())
1507- // 2. x >= typeLowerBound(RHS.getUnspecifiedType())
1508- //
1509- exists ( Expr lhs , Expr rhs , boolean isEQ |
1526+ exists ( Expr lhs , Expr rhs |
15101527 linearAccess ( lhs , v , p , q ) and
1511- eqOpWithSwapAndNegate ( guard , lhs , rhs , isEQ , branch ) and
1528+ eqOpWithSwapAndNegate ( guard , lhs , rhs , true , branch ) and
1529+ getBounds ( rhs , boundValue , isLowerBound ) and
15121530 strictness = Nonstrict ( )
1513- |
1514- // True branch
1515- isEQ = true and getBounds ( rhs , boundValue , isLowerBound )
1516- or
1517- // False branch: set the bounds to the min/max for the type.
1518- isEQ = false and exprTypeBounds ( rhs , boundValue , isLowerBound )
15191531 )
1532+ // x != RHS and !x are handled elsewhere
15201533}
15211534
15221535/** Utility for `linearBoundFromGuard`. */
@@ -1533,6 +1546,42 @@ private predicate exprTypeBounds(Expr expr, float boundValue, boolean isLowerBou
15331546 isLowerBound = false and boundValue = exprMaxVal ( expr .getFullyConverted ( ) )
15341547}
15351548
1549+ /**
1550+ * Holds if `(v, phi)` ensures that `access` is not equal to `neConstant`. For
1551+ * example, the condition `if (x + 1 != 3)` ensures that `x` is not equal to 2.
1552+ * Only integral types are supported.
1553+ */
1554+ private predicate isNEPhi (
1555+ Variable v , RangeSsaDefinition phi , VariableAccess access , float neConstant
1556+ ) {
1557+ exists (
1558+ ComparisonOperation cmp , boolean branch , Expr linearExpr , Expr rExpr , float p , float q , float r
1559+ |
1560+ access .getTarget ( ) = v and
1561+ phi .isGuardPhi ( access , cmp , branch ) and
1562+ eqOpWithSwapAndNegate ( cmp , linearExpr , rExpr , false , branch ) and
1563+ v .getUnspecifiedType ( ) instanceof IntegralOrEnumType and // Float `!=` is too imprecise
1564+ r = getValue ( rExpr ) .toFloat ( ) and
1565+ linearAccess ( linearExpr , access , p , q ) and
1566+ neConstant = ( r - q ) / p
1567+ )
1568+ }
1569+
1570+ /**
1571+ * Holds if `(v, phi)` constrains the value of `access` but in a way that
1572+ * doesn't allow this library to constrain the upper or lower bounds of
1573+ * `access`. An example is `if (x != y)` if neither `x` nor `y` is a
1574+ * compile-time constant.
1575+ */
1576+ private predicate isUnsupportedGuardPhi ( Variable v , RangeSsaDefinition phi , VariableAccess access ) {
1577+ exists ( ComparisonOperation cmp , boolean branch |
1578+ access .getTarget ( ) = v and
1579+ phi .isGuardPhi ( access , cmp , branch ) and
1580+ eqOpWithSwapAndNegate ( cmp , _, _, false , branch ) and
1581+ not isNEPhi ( v , phi , access , _)
1582+ )
1583+ }
1584+
15361585cached
15371586private module SimpleRangeAnalysisCached {
15381587 /**
0 commit comments