C++: convert RangeAnalysis to float

This commit is contained in:
Robert Marsh
2022-12-14 16:32:31 -05:00
parent eebada46b1
commit b8c43d7a71

View File

@@ -64,13 +64,12 @@
*/ */
private import RangeAnalysisSpecific as Specific private import RangeAnalysisSpecific as Specific
private import RangeUtils private import RangeUtils as Utils
private import SignAnalysisCommon private import SignAnalysisCommon
private import ModulusAnalysis private import ModulusAnalysis
private import experimental.semmle.code.cpp.semantic.Semantic private import experimental.semmle.code.cpp.semantic.Semantic
private import ConstantAnalysis private import ConstantAnalysis
/** /**
* An expression that does conversion, boxing, or unboxing * An expression that does conversion, boxing, or unboxing
*/ */
@@ -89,8 +88,8 @@ private class ConvertOrBoxExpr extends SemUnaryExpr {
*/ */
private class SafeCastExpr extends ConvertOrBoxExpr { private class SafeCastExpr extends ConvertOrBoxExpr {
SafeCastExpr() { SafeCastExpr() {
conversionCannotOverflow(getTrackedType(pragma[only_bind_into](getOperand())), conversionCannotOverflow(Utils::getTrackedType(pragma[only_bind_into](getOperand())),
getTrackedType(this)) Utils::getTrackedType(this))
} }
} }
@@ -119,19 +118,49 @@ private predicate typeBound(SemIntegerType typ, int lowerbound, int upperbound)
private class NarrowingCastExpr extends ConvertOrBoxExpr { private class NarrowingCastExpr extends ConvertOrBoxExpr {
NarrowingCastExpr() { NarrowingCastExpr() {
not this instanceof SafeCastExpr and not this instanceof SafeCastExpr and
typeBound(getTrackedType(this), _, _) typeBound(Utils::getTrackedType(this), _, _)
} }
/** Gets the lower bound of the resulting type. */ /** Gets the lower bound of the resulting type. */
int getLowerBound() { typeBound(getTrackedType(this), result, _) } int getLowerBound() { typeBound(Utils::getTrackedType(this), result, _) }
/** Gets the upper bound of the resulting type. */ /** Gets the upper bound of the resulting type. */
int getUpperBound() { typeBound(getTrackedType(this), _, result) } int getUpperBound() { typeBound(Utils::getTrackedType(this), _, result) }
} }
signature module RangeSig { } signature module DeltaSig {
class Delta;
module RangeStage<RangeSig RangeParam> { bindingset[d]
bindingset[result]
float toFloat(Delta d);
bindingset[d]
bindingset[result]
int toInt(Delta d);
bindingset[n]
bindingset[result]
Delta fromInt(int n);
bindingset[f]
bindingset[result]
Delta fromFloat(float f);
}
signature module UtilSig<DeltaSig DeltaParam> {
SemExpr semSsaRead(SemSsaVariable v, DeltaParam::Delta delta);
SemGuard semEqFlowCond(
SemSsaVariable v, SemExpr e, DeltaParam::Delta delta, boolean isEq, boolean testIsTrue
);
predicate semSsaUpdateStep(SemSsaExplicitUpdate v, SemExpr e, DeltaParam::Delta delta);
predicate semValueFlowStep(SemExpr e2, SemExpr e1, DeltaParam::Delta delta);
}
module RangeStage<DeltaSig D, UtilSig<D> UtilParam> {
cached cached
private module RangeAnalysisCache { private module RangeAnalysisCache {
cached cached
@@ -146,7 +175,7 @@ module RangeStage<RangeSig RangeParam> {
* condition. * condition.
*/ */
cached cached
predicate semBounded(SemExpr e, SemBound b, int delta, boolean upper, SemReason reason) { predicate semBounded(SemExpr e, SemBound b, float delta, boolean upper, SemReason reason) {
bounded(e, b, delta, upper, _, _, reason) and bounded(e, b, delta, upper, _, _, reason) and
bestBound(e, b, delta, upper) bestBound(e, b, delta, upper)
} }
@@ -157,7 +186,7 @@ module RangeStage<RangeSig RangeParam> {
*/ */
cached cached
predicate possibleReason(SemGuard guard) { predicate possibleReason(SemGuard guard) {
guard = boundFlowCond(_, _, _, _, _) or guard = semEqFlowCond(_, _, _, _, _) guard = boundFlowCond(_, _, _, _, _) or guard = UtilParam::semEqFlowCond(_, _, _, _, _)
} }
} }
@@ -169,10 +198,12 @@ module RangeStage<RangeSig RangeParam> {
* - `upper = true` : `e <= b + delta` * - `upper = true` : `e <= b + delta`
* - `upper = false` : `e >= b + delta` * - `upper = false` : `e >= b + delta`
*/ */
private predicate bestBound(SemExpr e, SemBound b, int delta, boolean upper) { private predicate bestBound(SemExpr e, SemBound b, float delta, boolean upper) {
delta = min(int d | bounded(e, b, d, upper, _, _, _)) and upper = true delta = min(float d | bounded(e, b, d, upper, _, _, _)) and
upper = true
or or
delta = max(int d | bounded(e, b, d, upper, _, _, _)) and upper = false delta = max(float d | bounded(e, b, d, upper, _, _, _)) and
upper = false
} }
/** /**
@@ -181,19 +212,21 @@ module RangeStage<RangeSig RangeParam> {
* - `upper = false` : `v >= e + delta` or `v > e + delta` * - `upper = false` : `v >= e + delta` or `v > e + delta`
*/ */
private predicate boundCondition( private predicate boundCondition(
SemRelationalExpr comp, SemSsaVariable v, SemExpr e, int delta, boolean upper SemRelationalExpr comp, SemSsaVariable v, SemExpr e, float delta, boolean upper
) { ) {
comp.getLesserOperand() = semSsaRead(v, delta) and e = comp.getGreaterOperand() and upper = true comp.getLesserOperand() = UtilParam::semSsaRead(v, D::fromFloat(delta)) and
e = comp.getGreaterOperand() and
upper = true
or or
comp.getGreaterOperand() = semSsaRead(v, delta) and comp.getGreaterOperand() = UtilParam::semSsaRead(v, D::fromFloat(delta)) and
e = comp.getLesserOperand() and e = comp.getLesserOperand() and
upper = false upper = false
or or
exists(SemSubExpr sub, SemConstantIntegerExpr c, int d | exists(SemSubExpr sub, SemConstantIntegerExpr c, float d |
// (v - d) - e < c // (v - d) - e < c
comp.getLesserOperand() = sub and comp.getLesserOperand() = sub and
comp.getGreaterOperand() = c and comp.getGreaterOperand() = c and
sub.getLeftOperand() = semSsaRead(v, d) and sub.getLeftOperand() = UtilParam::semSsaRead(v, D::fromFloat(d)) and
sub.getRightOperand() = e and sub.getRightOperand() = e and
upper = true and upper = true and
delta = d + c.getIntValue() delta = d + c.getIntValue()
@@ -201,7 +234,7 @@ module RangeStage<RangeSig RangeParam> {
// (v - d) - e > c // (v - d) - e > c
comp.getGreaterOperand() = sub and comp.getGreaterOperand() = sub and
comp.getLesserOperand() = c and comp.getLesserOperand() = c and
sub.getLeftOperand() = semSsaRead(v, d) and sub.getLeftOperand() = UtilParam::semSsaRead(v, D::fromFloat(d)) and
sub.getRightOperand() = e and sub.getRightOperand() = e and
upper = false and upper = false and
delta = d + c.getIntValue() delta = d + c.getIntValue()
@@ -210,7 +243,7 @@ module RangeStage<RangeSig RangeParam> {
comp.getLesserOperand() = sub and comp.getLesserOperand() = sub and
comp.getGreaterOperand() = c and comp.getGreaterOperand() = c and
sub.getLeftOperand() = e and sub.getLeftOperand() = e and
sub.getRightOperand() = semSsaRead(v, d) and sub.getRightOperand() = UtilParam::semSsaRead(v, D::fromFloat(d)) and
upper = false and upper = false and
delta = d - c.getIntValue() delta = d - c.getIntValue()
or or
@@ -218,7 +251,7 @@ module RangeStage<RangeSig RangeParam> {
comp.getGreaterOperand() = sub and comp.getGreaterOperand() = sub and
comp.getLesserOperand() = c and comp.getLesserOperand() = c and
sub.getLeftOperand() = e and sub.getLeftOperand() = e and
sub.getRightOperand() = semSsaRead(v, d) and sub.getRightOperand() = UtilParam::semSsaRead(v, D::fromFloat(d)) and
upper = true and upper = true and
delta = d - c.getIntValue() delta = d - c.getIntValue()
) )
@@ -271,10 +304,10 @@ module RangeStage<RangeSig RangeParam> {
* - `upper = false` : `v >= e + delta` * - `upper = false` : `v >= e + delta`
*/ */
private SemGuard boundFlowCond( private SemGuard boundFlowCond(
SemSsaVariable v, SemExpr e, int delta, boolean upper, boolean testIsTrue SemSsaVariable v, SemExpr e, float delta, boolean upper, boolean testIsTrue
) { ) {
exists( exists(
SemRelationalExpr comp, int d1, int d2, int d3, int strengthen, boolean compIsUpper, SemRelationalExpr comp, float d1, float d2, float d3, int strengthen, boolean compIsUpper,
boolean resultIsStrict boolean resultIsStrict
| |
comp = result.asExpr() and comp = result.asExpr() and
@@ -288,8 +321,8 @@ module RangeStage<RangeSig RangeParam> {
) and ) and
( (
if if
getTrackedTypeForSsaVariable(v) instanceof SemIntegerType or Utils::getTrackedTypeForSsaVariable(v) instanceof SemIntegerType or
getTrackedTypeForSsaVariable(v) instanceof SemAddressType Utils::getTrackedTypeForSsaVariable(v) instanceof SemAddressType
then then
upper = true and strengthen = -1 upper = true and strengthen = -1
or or
@@ -314,13 +347,15 @@ module RangeStage<RangeSig RangeParam> {
semImplies_v2(result, testIsTrue, boundFlowCond(v, e, delta, upper, testIsTrue0), testIsTrue0) semImplies_v2(result, testIsTrue, boundFlowCond(v, e, delta, upper, testIsTrue0), testIsTrue0)
) )
or or
result = semEqFlowCond(v, e, delta, true, testIsTrue) and result = UtilParam::semEqFlowCond(v, e, D::fromFloat(delta), true, testIsTrue) and
(upper = true or upper = false) (upper = true or upper = false)
or or
// guard that tests whether `v2` is bounded by `e + delta + d1 - d2` and // guard that tests whether `v2` is bounded by `e + delta + d1 - d2` and
// exists a guard `guardEq` such that `v = v2 - d1 + d2`. // exists a guard `guardEq` such that `v = v2 - d1 + d2`.
exists(SemSsaVariable v2, SemGuard guardEq, boolean eqIsTrue, int d1, int d2 | exists(SemSsaVariable v2, SemGuard guardEq, boolean eqIsTrue, float d1, float d2 |
guardEq = semEqFlowCond(v, semSsaRead(v2, d1), d2, true, eqIsTrue) and guardEq =
UtilParam::semEqFlowCond(v, UtilParam::semSsaRead(v2, D::fromFloat(d1)), D::fromFloat(d2),
true, eqIsTrue) and
result = boundFlowCond(v2, e, delta + d1 - d2, upper, testIsTrue) and result = boundFlowCond(v2, e, delta + d1 - d2, upper, testIsTrue) and
// guardEq needs to control guard // guardEq needs to control guard
guardEq.directlyControls(result.getBasicBlock(), eqIsTrue) guardEq.directlyControls(result.getBasicBlock(), eqIsTrue)
@@ -363,9 +398,10 @@ module RangeStage<RangeSig RangeParam> {
* - `upper = false` : `v >= e + delta` * - `upper = false` : `v >= e + delta`
*/ */
private predicate boundFlowStepSsa( private predicate boundFlowStepSsa(
SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta, boolean upper, SemReason reason SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, float delta, boolean upper,
SemReason reason
) { ) {
semSsaUpdateStep(v, e, delta) and UtilParam::semSsaUpdateStep(v, e, D::fromFloat(delta)) and
pos.hasReadOfVar(v) and pos.hasReadOfVar(v) and
(upper = true or upper = false) and (upper = true or upper = false) and
reason = TSemNoReason() reason = TSemNoReason()
@@ -380,12 +416,12 @@ module RangeStage<RangeSig RangeParam> {
/** Holds if `v != e + delta` at `pos` and `v` is of integral type. */ /** Holds if `v != e + delta` at `pos` and `v` is of integral type. */
private predicate unequalFlowStepIntegralSsa( private predicate unequalFlowStepIntegralSsa(
SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta, SemReason reason SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, float delta, SemReason reason
) { ) {
getTrackedTypeForSsaVariable(v) instanceof SemIntegerType and Utils::getTrackedTypeForSsaVariable(v) instanceof SemIntegerType and
exists(SemGuard guard, boolean testIsTrue | exists(SemGuard guard, boolean testIsTrue |
pos.hasReadOfVar(v) and pos.hasReadOfVar(v) and
guard = semEqFlowCond(v, e, delta, false, testIsTrue) and guard = UtilParam::semEqFlowCond(v, e, D::fromFloat(delta), false, testIsTrue) and
semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) and semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) and
reason = TSemCondReason(guard) reason = TSemCondReason(guard)
) )
@@ -393,12 +429,12 @@ module RangeStage<RangeSig RangeParam> {
/** Holds if `e >= 1` as determined by sign analysis. */ /** Holds if `e >= 1` as determined by sign analysis. */
private predicate strictlyPositiveIntegralExpr(SemExpr e) { private predicate strictlyPositiveIntegralExpr(SemExpr e) {
semStrictlyPositive(e) and getTrackedType(e) instanceof SemIntegerType semStrictlyPositive(e) and Utils::getTrackedType(e) instanceof SemIntegerType
} }
/** Holds if `e <= -1` as determined by sign analysis. */ /** Holds if `e <= -1` as determined by sign analysis. */
private predicate strictlyNegativeIntegralExpr(SemExpr e) { private predicate strictlyNegativeIntegralExpr(SemExpr e) {
semStrictlyNegative(e) and getTrackedType(e) instanceof SemIntegerType semStrictlyNegative(e) and Utils::getTrackedType(e) instanceof SemIntegerType
} }
/** /**
@@ -406,8 +442,8 @@ module RangeStage<RangeSig RangeParam> {
* - `upper = true` : `e2 <= e1 + delta` * - `upper = true` : `e2 <= e1 + delta`
* - `upper = false` : `e2 >= e1 + delta` * - `upper = false` : `e2 >= e1 + delta`
*/ */
private predicate boundFlowStep(SemExpr e2, SemExpr e1, int delta, boolean upper) { private predicate boundFlowStep(SemExpr e2, SemExpr e1, float delta, boolean upper) {
semValueFlowStep(e2, e1, delta) and UtilParam::semValueFlowStep(e2, e1, D::fromFloat(delta)) and
(upper = true or upper = false) (upper = true or upper = false)
or or
e2.(SafeCastExpr).getOperand() = e1 and e2.(SafeCastExpr).getOperand() = e1 and
@@ -474,7 +510,7 @@ module RangeStage<RangeSig RangeParam> {
} }
/** Holds if `e2 = e1 * factor` and `factor > 0`. */ /** Holds if `e2 = e1 * factor` and `factor > 0`. */
private predicate boundFlowStepMul(SemExpr e2, SemExpr e1, int factor) { private predicate boundFlowStepMul(SemExpr e2, SemExpr e1, float factor) {
exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() and k > 0 | exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() and k > 0 |
e2.(SemMulExpr).hasOperands(e1, c) and factor = k e2.(SemMulExpr).hasOperands(e1, c) and factor = k
or or
@@ -490,8 +526,8 @@ module RangeStage<RangeSig RangeParam> {
* This conflates division, right shift, and unsigned right shift and is * This conflates division, right shift, and unsigned right shift and is
* therefore only valid for non-negative numbers. * therefore only valid for non-negative numbers.
*/ */
private predicate boundFlowStepDiv(SemExpr e2, SemExpr e1, int factor) { private predicate boundFlowStepDiv(SemExpr e2, SemExpr e1, float factor) {
exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() and k > 0 | exists(SemConstantIntegerExpr c, float k | k = c.getIntValue() and k > 0 |
exists(SemDivExpr e | exists(SemDivExpr e |
e = e2 and e.getLeftOperand() = e1 and e.getRightOperand() = c and factor = k e = e2 and e.getLeftOperand() = e1 and e.getRightOperand() = c and factor = k
) )
@@ -512,10 +548,10 @@ module RangeStage<RangeSig RangeParam> {
* - `upper = false` : `v >= b + delta` * - `upper = false` : `v >= b + delta`
*/ */
private predicate boundedSsa( private predicate boundedSsa(
SemSsaVariable v, SemSsaReadPosition pos, SemBound b, int delta, boolean upper, SemSsaVariable v, SemSsaReadPosition pos, SemBound b, float delta, boolean upper,
boolean fromBackEdge, int origdelta, SemReason reason boolean fromBackEdge, float origdelta, SemReason reason
) { ) {
exists(SemExpr mid, int d1, int d2, SemReason r1, SemReason r2 | exists(SemExpr mid, float d1, float d2, SemReason r1, SemReason r2 |
boundFlowStepSsa(v, pos, mid, d1, upper, r1) and boundFlowStepSsa(v, pos, mid, d1, upper, r1) and
bounded(mid, b, d2, upper, fromBackEdge, origdelta, r2) and bounded(mid, b, d2, upper, fromBackEdge, origdelta, r2) and
// upper = true: v <= mid + d1 <= b + d1 + d2 = b + delta // upper = true: v <= mid + d1 <= b + d1 + d2 = b + delta
@@ -524,7 +560,7 @@ module RangeStage<RangeSig RangeParam> {
(if r1 instanceof SemNoReason then reason = r2 else reason = r1) (if r1 instanceof SemNoReason then reason = r2 else reason = r1)
) )
or or
exists(int d, SemReason r1, SemReason r2 | exists(float d, SemReason r1, SemReason r2 |
boundedSsa(v, pos, b, d, upper, fromBackEdge, origdelta, r2) or boundedSsa(v, pos, b, d, upper, fromBackEdge, origdelta, r2) or
boundedPhi(v, b, d, upper, fromBackEdge, origdelta, r2) boundedPhi(v, b, d, upper, fromBackEdge, origdelta, r2)
| |
@@ -546,9 +582,9 @@ module RangeStage<RangeSig RangeParam> {
* Holds if `v != b + delta` at `pos` and `v` is of integral type. * Holds if `v != b + delta` at `pos` and `v` is of integral type.
*/ */
private predicate unequalIntegralSsa( private predicate unequalIntegralSsa(
SemSsaVariable v, SemSsaReadPosition pos, SemBound b, int delta, SemReason reason SemSsaVariable v, SemSsaReadPosition pos, SemBound b, float delta, SemReason reason
) { ) {
exists(SemExpr e, int d1, int d2 | exists(SemExpr e, float d1, float d2 |
unequalFlowStepIntegralSsa(v, pos, e, d1, reason) and unequalFlowStepIntegralSsa(v, pos, e, d1, reason) and
boundedUpper(e, b, d1) and boundedUpper(e, b, d1) and
boundedLower(e, b, d2) and boundedLower(e, b, d2) and
@@ -562,7 +598,7 @@ module RangeStage<RangeSig RangeParam> {
* This predicate only exists to prevent a bad standard order in `unequalIntegralSsa`. * This predicate only exists to prevent a bad standard order in `unequalIntegralSsa`.
*/ */
pragma[nomagic] pragma[nomagic]
private predicate boundedUpper(SemExpr e, SemBound b, int delta) { private predicate boundedUpper(SemExpr e, SemBound b, float delta) {
bounded(e, b, delta, true, _, _, _) bounded(e, b, delta, true, _, _, _)
} }
@@ -572,13 +608,13 @@ module RangeStage<RangeSig RangeParam> {
* This predicate only exists to prevent a bad standard order in `unequalIntegralSsa`. * This predicate only exists to prevent a bad standard order in `unequalIntegralSsa`.
*/ */
pragma[nomagic] pragma[nomagic]
private predicate boundedLower(SemExpr e, SemBound b, int delta) { private predicate boundedLower(SemExpr e, SemBound b, float delta) {
bounded(e, b, delta, false, _, _, _) bounded(e, b, delta, false, _, _, _)
} }
/** Weakens a delta to lie in the range `[-1..1]`. */ /** Weakens a delta to lie in the range `[-1..1]`. */
bindingset[delta, upper] bindingset[delta, upper]
private int weakenDelta(boolean upper, int delta) { private float weakenDelta(boolean upper, float delta) {
delta in [-1 .. 1] and result = delta delta in [-1 .. 1] and result = delta
or or
upper = true and result = -1 and delta < -1 upper = true and result = -1 and delta < -1
@@ -594,10 +630,10 @@ module RangeStage<RangeSig RangeParam> {
*/ */
private predicate boundedPhiInp( private predicate boundedPhiInp(
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, SemBound b, SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, SemBound b,
int delta, boolean upper, boolean fromBackEdge, int origdelta, SemReason reason float delta, boolean upper, boolean fromBackEdge, float origdelta, SemReason reason
) { ) {
edge.phiInput(phi, inp) and edge.phiInput(phi, inp) and
exists(int d, boolean fromBackEdge0 | exists(float d, boolean fromBackEdge0 |
boundedSsa(inp, edge, b, d, upper, fromBackEdge0, origdelta, reason) boundedSsa(inp, edge, b, d, upper, fromBackEdge0, origdelta, reason)
or or
boundedPhi(inp, b, d, upper, fromBackEdge0, origdelta, reason) boundedPhi(inp, b, d, upper, fromBackEdge0, origdelta, reason)
@@ -634,7 +670,7 @@ module RangeStage<RangeSig RangeParam> {
pragma[noinline] pragma[noinline]
private predicate boundedPhiInp1( private predicate boundedPhiInp1(
SemSsaPhiNode phi, SemBound b, boolean upper, SemSsaVariable inp, SemSsaPhiNode phi, SemBound b, boolean upper, SemSsaVariable inp,
SemSsaReadPositionPhiInputEdge edge, int delta SemSsaReadPositionPhiInputEdge edge, float delta
) { ) {
boundedPhiInp(phi, inp, edge, b, delta, upper, _, _, _) boundedPhiInp(phi, inp, edge, b, delta, upper, _, _, _)
} }
@@ -648,7 +684,7 @@ module RangeStage<RangeSig RangeParam> {
private predicate selfBoundedPhiInp( private predicate selfBoundedPhiInp(
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, boolean upper SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, boolean upper
) { ) {
exists(int d, SemSsaBound phibound | exists(float d, SemSsaBound phibound |
phibound.getAVariable() = phi and phibound.getAVariable() = phi and
boundedPhiInp(phi, inp, edge, phibound, d, upper, _, _, _) and boundedPhiInp(phi, inp, edge, phibound, d, upper, _, _, _) and
( (
@@ -667,8 +703,8 @@ module RangeStage<RangeSig RangeParam> {
*/ */
pragma[noinline] pragma[noinline]
private predicate boundedPhiCand( private predicate boundedPhiCand(
SemSsaPhiNode phi, boolean upper, SemBound b, int delta, boolean fromBackEdge, int origdelta, SemSsaPhiNode phi, boolean upper, SemBound b, float delta, boolean fromBackEdge,
SemReason reason float origdelta, SemReason reason
) { ) {
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge |
boundedPhiInp(phi, inp, edge, b, delta, upper, fromBackEdge, origdelta, reason) boundedPhiInp(phi, inp, edge, b, delta, upper, fromBackEdge, origdelta, reason)
@@ -680,14 +716,14 @@ module RangeStage<RangeSig RangeParam> {
* `inp` along `edge`. * `inp` along `edge`.
*/ */
private predicate boundedPhiCandValidForEdge( private predicate boundedPhiCandValidForEdge(
SemSsaPhiNode phi, SemBound b, int delta, boolean upper, boolean fromBackEdge, int origdelta, SemSsaPhiNode phi, SemBound b, float delta, boolean upper, boolean fromBackEdge,
SemReason reason, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge float origdelta, SemReason reason, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge
) { ) {
boundedPhiCand(phi, upper, b, delta, fromBackEdge, origdelta, reason) and boundedPhiCand(phi, upper, b, delta, fromBackEdge, origdelta, reason) and
( (
exists(int d | boundedPhiInp1(phi, b, upper, inp, edge, d) | upper = true and d <= delta) exists(float d | boundedPhiInp1(phi, b, upper, inp, edge, d) | upper = true and d <= delta)
or or
exists(int d | boundedPhiInp1(phi, b, upper, inp, edge, d) | upper = false and d >= delta) exists(float d | boundedPhiInp1(phi, b, upper, inp, edge, d) | upper = false and d >= delta)
or or
selfBoundedPhiInp(phi, inp, edge, upper) selfBoundedPhiInp(phi, inp, edge, upper)
) )
@@ -699,8 +735,8 @@ module RangeStage<RangeSig RangeParam> {
* - `upper = false` : `phi >= b + delta` * - `upper = false` : `phi >= b + delta`
*/ */
private predicate boundedPhi( private predicate boundedPhi(
SemSsaPhiNode phi, SemBound b, int delta, boolean upper, boolean fromBackEdge, int origdelta, SemSsaPhiNode phi, SemBound b, float delta, boolean upper, boolean fromBackEdge,
SemReason reason float origdelta, SemReason reason
) { ) {
forex(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | edge.phiInput(phi, inp) | forex(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | edge.phiInput(phi, inp) |
boundedPhiCandValidForEdge(phi, b, delta, upper, fromBackEdge, origdelta, reason, inp, edge) boundedPhiCandValidForEdge(phi, b, delta, upper, fromBackEdge, origdelta, reason, inp, edge)
@@ -711,7 +747,7 @@ module RangeStage<RangeSig RangeParam> {
* Holds if `e` has an upper (for `upper = true`) or lower * Holds if `e` has an upper (for `upper = true`) or lower
* (for `upper = false`) bound of `b`. * (for `upper = false`) bound of `b`.
*/ */
private predicate baseBound(SemExpr e, int b, boolean upper) { private predicate baseBound(SemExpr e, float b, boolean upper) {
Specific::hasConstantBound(e, b, upper) Specific::hasConstantBound(e, b, upper)
or or
upper = false and upper = false and
@@ -728,7 +764,7 @@ module RangeStage<RangeSig RangeParam> {
* `upper = false` this means that the cast will not underflow. * `upper = false` this means that the cast will not underflow.
*/ */
private predicate safeNarrowingCast(NarrowingCastExpr cast, boolean upper) { private predicate safeNarrowingCast(NarrowingCastExpr cast, boolean upper) {
exists(int bound | bounded(cast.getOperand(), any(SemZeroBound zb), bound, upper, _, _, _) | exists(float bound | bounded(cast.getOperand(), any(SemZeroBound zb), bound, upper, _, _, _) |
upper = true and bound <= cast.getUpperBound() upper = true and bound <= cast.getUpperBound()
or or
upper = false and bound >= cast.getLowerBound() upper = false and bound >= cast.getLowerBound()
@@ -737,8 +773,8 @@ module RangeStage<RangeSig RangeParam> {
pragma[noinline] pragma[noinline]
private predicate boundedCastExpr( private predicate boundedCastExpr(
NarrowingCastExpr cast, SemBound b, int delta, boolean upper, boolean fromBackEdge, NarrowingCastExpr cast, SemBound b, float delta, boolean upper, boolean fromBackEdge,
int origdelta, SemReason reason float origdelta, SemReason reason
) { ) {
bounded(cast.getOperand(), b, delta, upper, fromBackEdge, origdelta, reason) bounded(cast.getOperand(), b, delta, upper, fromBackEdge, origdelta, reason)
} }
@@ -749,7 +785,7 @@ module RangeStage<RangeSig RangeParam> {
* - `upper = false` : `e >= b + delta` * - `upper = false` : `e >= b + delta`
*/ */
private predicate bounded( private predicate bounded(
SemExpr e, SemBound b, int delta, boolean upper, boolean fromBackEdge, int origdelta, SemExpr e, SemBound b, float delta, boolean upper, boolean fromBackEdge, float origdelta,
SemReason reason SemReason reason
) { ) {
not Specific::ignoreExprBound(e) and not Specific::ignoreExprBound(e) and
@@ -772,7 +808,7 @@ module RangeStage<RangeSig RangeParam> {
bb.getBlock() = e.getBasicBlock() bb.getBlock() = e.getBasicBlock()
) )
or or
exists(SemExpr mid, int d1, int d2 | exists(SemExpr mid, float d1, float d2 |
boundFlowStep(e, mid, d1, upper) and boundFlowStep(e, mid, d1, upper) and
// Constants have easy, base-case bounds, so let's not infer any recursive bounds. // Constants have easy, base-case bounds, so let's not infer any recursive bounds.
not e instanceof SemConstantIntegerExpr and not e instanceof SemConstantIntegerExpr and
@@ -787,7 +823,7 @@ module RangeStage<RangeSig RangeParam> {
e = phi.getAUse() e = phi.getAUse()
) )
or or
exists(SemExpr mid, int factor, int d | exists(SemExpr mid, float factor, float d |
boundFlowStepMul(e, mid, factor) and boundFlowStepMul(e, mid, factor) and
not e instanceof SemConstantIntegerExpr and not e instanceof SemConstantIntegerExpr and
bounded(mid, b, d, upper, fromBackEdge, origdelta, reason) and bounded(mid, b, d, upper, fromBackEdge, origdelta, reason) and
@@ -795,7 +831,7 @@ module RangeStage<RangeSig RangeParam> {
delta = d * factor delta = d * factor
) )
or or
exists(SemExpr mid, int factor, int d | exists(SemExpr mid, float factor, float d |
boundFlowStepDiv(e, mid, factor) and boundFlowStepDiv(e, mid, factor) and
not e instanceof SemConstantIntegerExpr and not e instanceof SemConstantIntegerExpr and
bounded(mid, b, d, upper, fromBackEdge, origdelta, reason) and bounded(mid, b, d, upper, fromBackEdge, origdelta, reason) and
@@ -811,8 +847,8 @@ module RangeStage<RangeSig RangeParam> {
) )
or or
exists( exists(
SemConditionalExpr cond, int d1, int d2, boolean fbe1, boolean fbe2, int od1, int od2, SemConditionalExpr cond, float d1, float d2, boolean fbe1, boolean fbe2, float od1,
SemReason r1, SemReason r2 float od2, SemReason r1, SemReason r2
| |
cond = e and cond = e and
boundedConditionalExpr(cond, b, upper, true, d1, fbe1, od1, r1) and boundedConditionalExpr(cond, b, upper, true, d1, fbe1, od1, r1) and
@@ -831,8 +867,8 @@ module RangeStage<RangeSig RangeParam> {
} }
private predicate boundedConditionalExpr( private predicate boundedConditionalExpr(
SemConditionalExpr cond, SemBound b, boolean upper, boolean branch, int delta, SemConditionalExpr cond, SemBound b, boolean upper, boolean branch, float delta,
boolean fromBackEdge, int origdelta, SemReason reason boolean fromBackEdge, float origdelta, SemReason reason
) { ) {
bounded(cond.getBranchExpr(branch), b, delta, upper, fromBackEdge, origdelta, reason) bounded(cond.getBranchExpr(branch), b, delta, upper, fromBackEdge, origdelta, reason)
} }