|
12 | 12 | //===----------------------------------------------------------------------===// |
13 | 13 | #include "mlir/Analysis/AffineExprBounds.h" |
14 | 14 |
|
| 15 | +#include "mlir/IR/AffineExpr.h" |
15 | 16 | #include "mlir/IR/AffineExprVisitor.h" |
16 | 17 | #include "mlir/IR/AffineMap.h" |
17 | 18 | #include "mlir/IR/BuiltinAttributes.h" |
@@ -158,13 +159,24 @@ AffineExprBoundsVisitor::visitFloorDivExpr(AffineBinaryOpExpr expr) { |
158 | 159 | return failure(); |
159 | 160 | } |
160 | 161 | LogicalResult AffineExprBoundsVisitor::visitModExpr(AffineBinaryOpExpr expr) { |
161 | | - inferBinOpRange( |
162 | | - expr, [boundsSigned = boundsSigned](ArrayRef<ConstantIntRanges> ranges) { |
163 | | - if (boundsSigned) { |
164 | | - return intrange::inferRemS(ranges); |
165 | | - } |
166 | | - return intrange::inferRemU(ranges); |
167 | | - }); |
| 162 | + // Only support integers >= 1 as RHS. |
| 163 | + auto rhsConst = dyn_cast<AffineConstantExpr>(expr.getRHS()); |
| 164 | + if (!rhsConst || rhsConst.getValue() < 1) |
| 165 | + return failure(); |
| 166 | + |
| 167 | + inferBinOpRange(expr, [boundsSigned = |
| 168 | + boundsSigned](ArrayRef<ConstantIntRanges> ranges) { |
| 169 | + // Mod must return a value between 0 and N-1. |
| 170 | + // Computing (N + (expr mod N)) mod N is guaranteed to yield a result in |
| 171 | + // this range. |
| 172 | + if (boundsSigned) { |
| 173 | + auto rhs = ranges[1]; |
| 174 | + auto lhs = ranges[0]; |
| 175 | + return intrange::inferRemS( |
| 176 | + {intrange::inferAdd({intrange::inferRemS({lhs, rhs}), rhs}), rhs}); |
| 177 | + } |
| 178 | + return intrange::inferRemU(ranges); |
| 179 | + }); |
168 | 180 | return success(); |
169 | 181 | } |
170 | 182 | LogicalResult AffineExprBoundsVisitor::visitDimExpr(AffineDimExpr expr) { |
|
0 commit comments