@@ -574,16 +574,6 @@ module RangeStage<
574574 )
575575 }
576576
577- /** Holds if `e >= 1` as determined by sign analysis. */
578- private predicate strictlyPositiveIntegralExpr ( SemExpr e ) {
579- semStrictlyPositive ( e ) and getTrackedType ( e ) instanceof SemIntegerType
580- }
581-
582- /** Holds if `e <= -1` as determined by sign analysis. */
583- private predicate strictlyNegativeIntegralExpr ( SemExpr e ) {
584- semStrictlyNegative ( e ) and getTrackedType ( e ) instanceof SemIntegerType
585- }
586-
587577 /**
588578 * Holds if `e1 + delta` is a valid bound for `e2`.
589579 * - `upper = true` : `e2 <= e1 + delta`
@@ -597,27 +587,6 @@ module RangeStage<
597587 delta = D:: fromInt ( 0 ) and
598588 ( upper = true or upper = false )
599589 or
600- exists ( SemExpr x , SemSubExpr sub |
601- e2 = sub and
602- sub .getLeftOperand ( ) = e1 and
603- sub .getRightOperand ( ) = x
604- |
605- // `x instanceof ConstantIntegerExpr` is covered by valueFlowStep
606- not x instanceof SemConstantIntegerExpr and
607- if strictlyPositiveIntegralExpr ( x )
608- then upper = true and delta = D:: fromInt ( - 1 )
609- else
610- if semPositive ( x )
611- then upper = true and delta = D:: fromInt ( 0 )
612- else
613- if strictlyNegativeIntegralExpr ( x )
614- then upper = false and delta = D:: fromInt ( 1 )
615- else
616- if semNegative ( x )
617- then upper = false and delta = D:: fromInt ( 0 )
618- else none ( )
619- )
620- or
621590 e2 .( SemRemExpr ) .getRightOperand ( ) = e1 and
622591 semPositive ( e1 ) and
623592 delta = D:: fromInt ( - 1 ) and
@@ -1137,6 +1106,30 @@ module RangeStage<
11371106 b = bRight and origdelta = odRight and reason = rRight and bLeft instanceof SemZeroBound
11381107 )
11391108 or
1109+ exists (
1110+ D:: Delta dLeft , D:: Delta dRight , boolean fbeLeft , boolean fbeRight , D:: Delta odLeft ,
1111+ D:: Delta odRight , SemReason rLeft , SemReason rRight
1112+ |
1113+ boundedSubOperandLeft ( e , upper , b , dLeft , fbeLeft , odLeft , rLeft ) and
1114+ boundedSubOperandRight ( e , upper , dRight , fbeRight , odRight , rRight ) and
1115+ // when `upper` is `true` we have:
1116+ // left <= b + dLeft
1117+ // right >= 0 + dRight
1118+ // left - right <= b + dLeft - (0 + dRight)
1119+ // = b + (dLeft - dRight)
1120+ // and when `upper` is `false` we have:
1121+ // left >= b + dLeft
1122+ // right <= 0 + dRight
1123+ // left - right >= b + dLeft - (0 + dRight)
1124+ // = b + (dLeft - dRight)
1125+ delta = D:: fromFloat ( D:: toFloat ( dLeft ) - D:: toFloat ( dRight ) ) and
1126+ fromBackEdge = fbeLeft .booleanOr ( fbeRight )
1127+ |
1128+ origdelta = odLeft and reason = rLeft
1129+ or
1130+ origdelta = odRight and reason = rRight
1131+ )
1132+ or
11401133 exists (
11411134 SemRemExpr rem , D:: Delta d_max , D:: Delta d1 , D:: Delta d2 , boolean fbe1 , boolean fbe2 ,
11421135 D:: Delta od1 , D:: Delta od2 , SemReason r1 , SemReason r2
@@ -1201,6 +1194,38 @@ module RangeStage<
12011194 )
12021195 }
12031196
1197+ /**
1198+ * Holds if `sub = left - right` and `left <= b + delta` if `upper` is `true`
1199+ * and `left >= b + delta` is `upper` is `false`.
1200+ */
1201+ pragma [ nomagic]
1202+ private predicate boundedSubOperandLeft (
1203+ SemSubExpr sub , boolean upper , SemBound b , D:: Delta delta , boolean fromBackEdge ,
1204+ D:: Delta origdelta , SemReason reason
1205+ ) {
1206+ // `semValueFlowStep` already handles the case where one of the operands is a constant.
1207+ not semValueFlowStep ( sub , _, _) and
1208+ bounded ( sub .getLeftOperand ( ) , b , delta , upper , fromBackEdge , origdelta , reason )
1209+ }
1210+
1211+ /**
1212+ * Holds if `sub = left - right` and `right <= 0 + delta` if `upper` is `false`
1213+ * and `right >= 0 + delta` is `upper` is `true`.
1214+ *
1215+ * Note that the boolean value of `upper` is flipped compared to many other predicates in
1216+ * this file. This ensures a clean join at the call-site.
1217+ */
1218+ pragma [ nomagic]
1219+ private predicate boundedSubOperandRight (
1220+ SemSubExpr sub , boolean upper , D:: Delta delta , boolean fromBackEdge , D:: Delta origdelta ,
1221+ SemReason reason
1222+ ) {
1223+ // `semValueFlowStep` already handles the case where one of the operands is a constant.
1224+ not semValueFlowStep ( sub , _, _) and
1225+ bounded ( sub .getRightOperand ( ) , any ( SemZeroBound zb ) , delta , upper .booleanNot ( ) , fromBackEdge ,
1226+ origdelta , reason )
1227+ }
1228+
12041229 pragma [ nomagic]
12051230 private predicate boundedRemExpr (
12061231 SemRemExpr rem , boolean upper , D:: Delta delta , boolean fromBackEdge , D:: Delta origdelta ,
0 commit comments