Rangeanalysis: Prune range calculation.

This commit is contained in:
Anders Schack-Mulligen
2023-12-07 13:59:42 +01:00
parent 58d463dd33
commit c14d917a76

View File

@@ -1132,6 +1132,50 @@ module RangeStage<
bindingset[x, y] bindingset[x, y]
private float truncatingDiv(float x, float y) { result = (x - (x % y)) / y } private float truncatingDiv(float x, float y) { result = (x - (x % y)) / y }
/**
* Holds if `b + delta` is a valid bound for `e` that can be found using only
* simple forward-flowing steps and disregarding phi-nodes.
* - `upper = true` : `e <= b + delta`
* - `upper = false` : `e >= b + delta`
*
* This predicate is used as a fast approximation for `bounded` to avoid
* excessive computation in certain cases. In particular, this applies to
* loop-unrolled code like
* ```
* if (..) x+=1; else x+=100;
* x &= 7;
* if (..) x+=1; else x+=100;
* x &= 7;
* if (..) x+=1; else x+=100;
* x &= 7;
* ...
* ```
*/
private predicate preBounded(Sem::Expr e, SemBound b, D::Delta delta, boolean upper) {
baseBound(e, b, delta, upper)
or
exists(Sem::Expr mid, D::Delta d1, D::Delta d2 |
boundFlowStep(e, mid, d1, upper) and
preBounded(mid, b, d2, upper) and
delta = D::fromFloat(D::toFloat(d1) + D::toFloat(d2))
)
or
exists(Sem::SsaVariable v, SsaReadPositionBlock bb, Sem::Expr mid, D::Delta d1, D::Delta d2 |
boundFlowStepSsa(v, bb, mid, d1, upper, _) and
preBounded(mid, b, d2, upper) and
delta = D::fromFloat(D::toFloat(d1) + D::toFloat(d2)) and
bb.getAnSsaRead(v) = e
)
}
private predicate bestPreBound(Sem::Expr e, SemBound b, D::Delta delta, boolean upper) {
delta = min(D::Delta d | preBounded(e, b, d, upper) | d order by D::toFloat(d)) and
upper = true
or
delta = max(D::Delta d | preBounded(e, b, d, upper) | d order by D::toFloat(d)) and
upper = false
}
/** /**
* Holds if `b + delta` is a valid bound for `e`. * Holds if `b + delta` is a valid bound for `e`.
* - `upper = true` : `e <= b + delta` * - `upper = true` : `e <= b + delta`
@@ -1142,6 +1186,12 @@ module RangeStage<
D::Delta origdelta, SemReason reason D::Delta origdelta, SemReason reason
) { ) {
not ignoreExprBound(e) and not ignoreExprBound(e) and
// ignore poor bounds
not exists(D::Delta d | bestPreBound(e, b, d, upper) |
D::toFloat(delta) > D::toFloat(d) and upper = true
or
D::toFloat(delta) < D::toFloat(d) and upper = false
) and
( (
baseBound(e, b, delta, upper) and baseBound(e, b, delta, upper) and
fromBackEdge = false and fromBackEdge = false and