@@ -591,24 +591,6 @@ module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<
591591 delta = D:: fromInt ( 0 ) and
592592 ( upper = true or upper = false )
593593 or
594- exists ( SemExpr x | e2 .( SemAddExpr ) .hasOperands ( e1 , x ) |
595- // `x instanceof ConstantIntegerExpr` is covered by valueFlowStep
596- not x instanceof SemConstantIntegerExpr and
597- not e1 instanceof SemConstantIntegerExpr and
598- if strictlyPositiveIntegralExpr ( x )
599- then upper = false and delta = D:: fromInt ( 1 )
600- else
601- if semPositive ( x )
602- then upper = false and delta = D:: fromInt ( 0 )
603- else
604- if strictlyNegativeIntegralExpr ( x )
605- then upper = true and delta = D:: fromInt ( - 1 )
606- else
607- if semNegative ( x )
608- then upper = true and delta = D:: fromInt ( 0 )
609- else none ( )
610- )
611- or
612594 exists ( SemExpr x , SemSubExpr sub |
613595 e2 = sub and
614596 sub .getLeftOperand ( ) = e1 and
@@ -1043,13 +1025,193 @@ module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<
10431025 delta = D:: fromFloat ( f ) and
10441026 if semPositive ( e ) then f >= 0 else any ( )
10451027 )
1028+ or
1029+ exists (
1030+ SemBound bLeft , SemBound bRight , D:: Delta dLeft , D:: Delta dRight , boolean fbeLeft ,
1031+ boolean fbeRight , D:: Delta odLeft , D:: Delta odRight , SemReason rLeft , SemReason rRight
1032+ |
1033+ boundedAddOperand ( e , upper , bLeft , false , dLeft , fbeLeft , odLeft , rLeft ) and
1034+ boundedAddOperand ( e , upper , bRight , true , dRight , fbeRight , odRight , rRight ) and
1035+ delta = D:: fromFloat ( D:: toFloat ( dLeft ) + D:: toFloat ( dRight ) ) and
1036+ fromBackEdge = fbeLeft .booleanOr ( fbeRight )
1037+ |
1038+ b = bLeft and origdelta = odLeft and reason = rLeft and bRight instanceof SemZeroBound
1039+ or
1040+ b = bRight and origdelta = odRight and reason = rRight and bLeft instanceof SemZeroBound
1041+ )
1042+ or
1043+ exists (
1044+ SemRemExpr rem , SemZeroBound b1 , SemZeroBound b2 , D:: Delta d_max , D:: Delta d1 , D:: Delta d2 ,
1045+ boolean fbe1 , boolean fbe2 , D:: Delta od1 , D:: Delta od2 , SemReason r1 , SemReason r2
1046+ |
1047+ rem = e and
1048+ not ( upper = true and semPositive ( rem .getRightOperand ( ) ) ) and
1049+ not ( upper = true and semPositive ( rem .getLeftOperand ( ) ) ) and
1050+ boundedRemExpr ( rem , b1 , true , d1 , fbe1 , od1 , r1 ) and
1051+ boundedRemExpr ( rem , b2 , false , d2 , fbe2 , od2 , r2 ) and
1052+ (
1053+ if D:: toFloat ( d1 ) .abs ( ) > D:: toFloat ( d2 ) .abs ( )
1054+ then (
1055+ b = b1 and d_max = d1 and fromBackEdge = fbe1 and origdelta = od1 and reason = r1
1056+ ) else (
1057+ b = b2 and d_max = d2 and fromBackEdge = fbe2 and origdelta = od2 and reason = r2
1058+ )
1059+ )
1060+ |
1061+ upper = true and delta = D:: fromFloat ( D:: toFloat ( d_max ) .abs ( ) - 1 )
1062+ or
1063+ upper = false and delta = D:: fromFloat ( - D:: toFloat ( d_max ) .abs ( ) + 1 )
1064+ )
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+ )
10461079 )
10471080 }
10481081
1082+ pragma [ nomagic]
10491083 private predicate boundedConditionalExpr (
10501084 SemConditionalExpr cond , SemBound b , boolean upper , boolean branch , D:: Delta delta ,
10511085 boolean fromBackEdge , D:: Delta origdelta , SemReason reason
10521086 ) {
10531087 bounded ( cond .getBranchExpr ( branch ) , b , delta , upper , fromBackEdge , origdelta , reason )
10541088 }
1089+
1090+ pragma [ nomagic]
1091+ private predicate boundedAddOperand (
1092+ SemAddExpr add , boolean upper , SemBound b , boolean isLeft , D:: Delta delta , boolean fromBackEdge ,
1093+ D:: Delta origdelta , SemReason reason
1094+ ) {
1095+ // `semValueFlowStep` already handles the case where one of the operands is a constant.
1096+ not semValueFlowStep ( add , _, _) and
1097+ (
1098+ isLeft = true and
1099+ bounded ( add .getLeftOperand ( ) , b , delta , upper , fromBackEdge , origdelta , reason )
1100+ or
1101+ isLeft = false and
1102+ bounded ( add .getRightOperand ( ) , b , delta , upper , fromBackEdge , origdelta , reason )
1103+ )
1104+ }
1105+
1106+ private predicate boundedRemExpr (
1107+ SemRemExpr rem , SemZeroBound b , boolean upper , D:: Delta delta , boolean fromBackEdge ,
1108+ D:: Delta origdelta , SemReason reason
1109+ ) {
1110+ bounded ( rem .getRightOperand ( ) , b , delta , upper , fromBackEdge , origdelta , reason )
1111+ }
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+ }
10551217}
0 commit comments