@@ -574,16 +574,6 @@ module RangeStage<
574
574
)
575
575
}
576
576
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
-
587
577
/**
588
578
* Holds if `e1 + delta` is a valid bound for `e2`.
589
579
* - `upper = true` : `e2 <= e1 + delta`
@@ -597,27 +587,6 @@ module RangeStage<
597
587
delta = D:: fromInt ( 0 ) and
598
588
( upper = true or upper = false )
599
589
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
621
590
e2 .( SemRemExpr ) .getRightOperand ( ) = e1 and
622
591
semPositive ( e1 ) and
623
592
delta = D:: fromInt ( - 1 ) and
@@ -1137,6 +1106,30 @@ module RangeStage<
1137
1106
b = bRight and origdelta = odRight and reason = rRight and bLeft instanceof SemZeroBound
1138
1107
)
1139
1108
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
1140
1133
exists (
1141
1134
SemRemExpr rem , D:: Delta d_max , D:: Delta d1 , D:: Delta d2 , boolean fbe1 , boolean fbe2 ,
1142
1135
D:: Delta od1 , D:: Delta od2 , SemReason r1 , SemReason r2
@@ -1201,6 +1194,38 @@ module RangeStage<
1201
1194
)
1202
1195
}
1203
1196
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
+
1204
1229
pragma [ nomagic]
1205
1230
private predicate boundedRemExpr (
1206
1231
SemRemExpr rem , boolean upper , D:: Delta delta , boolean fromBackEdge , D:: Delta origdelta ,
0 commit comments