@@ -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+ SemZeroBound bLeft , SemZeroBound bRight , D:: Delta dLeft , D:: Delta dRight , boolean fbeLeft ,
1068+ boolean fbeRight , D:: Delta odLeft , D:: Delta odRight , SemReason rLeft , SemReason rRight
1069+ |
1070+ boundedMulOperand ( e , upper , bLeft , true , dLeft , fbeLeft , odLeft , rLeft ) and
1071+ boundedMulOperand ( e , upper , bRight , 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 = bLeft and origdelta = odLeft and reason = rLeft
1076+ or
1077+ b = bRight and origdelta = odRight and reason = rRight
1078+ )
10651079 )
10661080 }
10671081
@@ -1095,4 +1109,100 @@ 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) B + k` (for
1117+ * some `B` and `k`) we need to know that `left cmp(upperLeft) B1 + k1` and
1118+ * `right cmp(upperRight) B2 + k2` (for some `B1`, `B2`, `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+ pragma [ nomagic]
1194+ private predicate boundedMulOperand (
1195+ SemMulExpr mul , boolean upper , SemZeroBound b , boolean isLeft , D:: Delta delta ,
1196+ boolean fromBackEdge , D:: Delta origdelta , SemReason reason
1197+ ) {
1198+ exists ( boolean upperLeft , boolean upperRight , SemExpr left , SemExpr right |
1199+ boundedMulOperandCand ( mul , left , right , upper , upperLeft , upperRight )
1200+ |
1201+ isLeft = true and
1202+ bounded ( left , b , delta , upperLeft , fromBackEdge , origdelta , reason )
1203+ or
1204+ isLeft = false and
1205+ bounded ( right , b , delta , upperRight , fromBackEdge , origdelta , reason )
1206+ )
1207+ }
10981208}
0 commit comments