@@ -1062,6 +1062,20 @@ module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<
10621062 or
10631063 upper = false and delta = D:: fromFloat ( - D:: toFloat ( d_max ) .abs ( ) + 1 )
10641064 )
1065+ or
1066+ exists (
1067+ D:: Delta dLeft , D:: Delta dRight , boolean fbeLeft , boolean fbeRight , D:: Delta odLeft ,
1068+ D:: Delta odRight , SemReason rLeft , SemReason rRight
1069+ |
1070+ boundedMulOperand ( e , upper , true , dLeft , fbeLeft , odLeft , rLeft ) and
1071+ boundedMulOperand ( e , upper , false , dRight , fbeRight , odRight , rRight ) and
1072+ delta = D:: fromFloat ( D:: toFloat ( dLeft ) * D:: toFloat ( dRight ) ) and
1073+ fromBackEdge = fbeLeft .booleanOr ( fbeRight )
1074+ |
1075+ b instanceof SemZeroBound and origdelta = odLeft and reason = rLeft
1076+ or
1077+ b instanceof SemZeroBound and origdelta = odRight and reason = rRight
1078+ )
10651079 )
10661080 }
10671081
@@ -1095,4 +1109,109 @@ module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<
10951109 ) {
10961110 bounded ( rem .getRightOperand ( ) , b , delta , upper , fromBackEdge , origdelta , reason )
10971111 }
1112+
1113+ /**
1114+ * Define `cmp(true) = <=` and `cmp(false) = >=`.
1115+ *
1116+ * Holds if `mul = left * right`, and in order to know if `mul cmp(upper) 0 + k` (for
1117+ * some `k`) we need to know that `left cmp(upperLeft) 0 + k1` and
1118+ * `right cmp(upperRight) 0 + k2` (for some `k1` and `k2`).
1119+ */
1120+ pragma [ nomagic]
1121+ private predicate boundedMulOperandCand (
1122+ SemMulExpr mul , SemExpr left , SemExpr right , boolean upper , boolean upperLeft ,
1123+ boolean upperRight
1124+ ) {
1125+ not boundFlowStepMul ( mul , _, _) and
1126+ mul .getLeftOperand ( ) = left and
1127+ mul .getRightOperand ( ) = right and
1128+ (
1129+ semPositive ( left ) and
1130+ (
1131+ // left, right >= 0
1132+ semPositive ( right ) and
1133+ (
1134+ // max(left * right) = max(left) * max(right)
1135+ upper = true and
1136+ upperLeft = true and
1137+ upperRight = true
1138+ or
1139+ // min(left * right) = min(left) * min(right)
1140+ upper = false and
1141+ upperLeft = false and
1142+ upperRight = false
1143+ )
1144+ or
1145+ // left >= 0, right <= 0
1146+ semNegative ( right ) and
1147+ (
1148+ // max(left * right) = min(left) * max(right)
1149+ upper = true and
1150+ upperLeft = false and
1151+ upperRight = true
1152+ or
1153+ // min(left * right) = max(left) * min(right)
1154+ upper = false and
1155+ upperLeft = true and
1156+ upperRight = false
1157+ )
1158+ )
1159+ or
1160+ semNegative ( left ) and
1161+ (
1162+ // left <= 0, right >= 0
1163+ semPositive ( right ) and
1164+ (
1165+ // max(left * right) = max(left) * min(right)
1166+ upper = true and
1167+ upperLeft = true and
1168+ upperRight = false
1169+ or
1170+ // min(left * right) = min(left) * max(right)
1171+ upper = false and
1172+ upperLeft = false and
1173+ upperRight = true
1174+ )
1175+ or
1176+ // left, right <= 0
1177+ semNegative ( right ) and
1178+ (
1179+ // max(left * right) = min(left) * min(right)
1180+ upper = true and
1181+ upperLeft = false and
1182+ upperRight = false
1183+ or
1184+ // min(left * right) = max(left) * max(right)
1185+ upper = false and
1186+ upperLeft = true and
1187+ upperRight = true
1188+ )
1189+ )
1190+ )
1191+ }
1192+
1193+ /**
1194+ * Holds if `isLeft = true` and `mul`'s left operand is bounded by `delta`,
1195+ * or if `isLeft = false` and `mul`'s right operand is bounded by `delta`.
1196+ *
1197+ * If `upper = true` the computed bound contributes to an upper bound of `mul`,
1198+ * and if `upper = false` it contributes to a lower bound.
1199+ * The `fromBackEdge`, `origdelta`, `reason` triple are defined by the recursive
1200+ * call to `bounded`.
1201+ */
1202+ pragma [ nomagic]
1203+ private predicate boundedMulOperand (
1204+ SemMulExpr mul , boolean upper , boolean isLeft , D:: Delta delta , boolean fromBackEdge ,
1205+ D:: Delta origdelta , SemReason reason
1206+ ) {
1207+ exists ( boolean upperLeft , boolean upperRight , SemExpr left , SemExpr right |
1208+ boundedMulOperandCand ( mul , left , right , upper , upperLeft , upperRight )
1209+ |
1210+ isLeft = true and
1211+ bounded ( left , any ( SemZeroBound zb ) , delta , upperLeft , fromBackEdge , origdelta , reason )
1212+ or
1213+ isLeft = false and
1214+ bounded ( right , any ( SemZeroBound zb ) , delta , upperRight , fromBackEdge , origdelta , reason )
1215+ )
1216+ }
10981217}
0 commit comments