Skip to content

Commit 350e0bd

Browse files
authored
Merge pull request #484 from Xilinx/corentin.mod_bounds
Ensure 0 <= x mod N < N semantics
2 parents cce9117 + 3e3f092 commit 350e0bd

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

mlir/lib/Analysis/AffineExprBounds.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313
#include "mlir/Analysis/AffineExprBounds.h"
1414

15+
#include "mlir/IR/AffineExpr.h"
1516
#include "mlir/IR/AffineExprVisitor.h"
1617
#include "mlir/IR/AffineMap.h"
1718
#include "mlir/IR/BuiltinAttributes.h"
@@ -158,13 +159,24 @@ AffineExprBoundsVisitor::visitFloorDivExpr(AffineBinaryOpExpr expr) {
158159
return failure();
159160
}
160161
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+
});
168180
return success();
169181
}
170182
LogicalResult AffineExprBoundsVisitor::visitDimExpr(AffineDimExpr expr) {

mlir/test/Analysis/test-affine-expr-bounds.mlir

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ func.func @test_compute_affine_expr_bounds() {
5252
// CHECK-SAME: expr_ub = 3
5353
"test.mod_not_wrapping_around"() {affine_map = affine_map<(d0) -> (((d0 + 12) mod 11) mod 5)>, lbs = [0], ubs = [2]} : () -> ()
5454

55+
// CHECK: "test.mod_neg"()
56+
// CHECK-SAME: expr_lb = 1
57+
// CHECK-SAME: expr_ub = 3
58+
"test.mod_neg"() {affine_map = affine_map<(d0) -> (d0 mod 5)>, lbs = [-4], ubs = [-2]} : () -> ()
59+
60+
// CHECK: "test.mod_wrapping_by_zero"()
61+
// CHECK-SAME: expr_lb = 0
62+
// CHECK-SAME: expr_ub = 4
63+
"test.mod_wrapping_by_zero"() {affine_map = affine_map<(d0) -> (d0 mod 5)>, lbs = [-2], ubs = [1]} : () -> ()
64+
5565
// FloorDiv
5666

5767
// CHECK: "test.floordiv_basic"()

0 commit comments

Comments
 (0)