forked from OSchip/llvm-project
[MLIR] Fix AffineExpr getLargestKnownDivisor for ceildiv and floordiv
Fix AffineExpr `getLargestKnownDivisor` for ceil/floor div cases. In these cases, nothing can be inferred on the divisor of the result. Add test case for `mod` as well. Differential Revision: https://reviews.llvm.org/D112523
This commit is contained in:
parent
f279e50fd0
commit
41a8b46007
|
@ -216,9 +216,11 @@ bool AffineExpr::isPureAffine() const {
|
||||||
int64_t AffineExpr::getLargestKnownDivisor() const {
|
int64_t AffineExpr::getLargestKnownDivisor() const {
|
||||||
AffineBinaryOpExpr binExpr(nullptr);
|
AffineBinaryOpExpr binExpr(nullptr);
|
||||||
switch (getKind()) {
|
switch (getKind()) {
|
||||||
case AffineExprKind::SymbolId:
|
case AffineExprKind::CeilDiv:
|
||||||
LLVM_FALLTHROUGH;
|
LLVM_FALLTHROUGH;
|
||||||
case AffineExprKind::DimId:
|
case AffineExprKind::DimId:
|
||||||
|
case AffineExprKind::FloorDiv:
|
||||||
|
case AffineExprKind::SymbolId:
|
||||||
return 1;
|
return 1;
|
||||||
case AffineExprKind::Constant:
|
case AffineExprKind::Constant:
|
||||||
return std::abs(this->cast<AffineConstantExpr>().getValue());
|
return std::abs(this->cast<AffineConstantExpr>().getValue());
|
||||||
|
@ -229,8 +231,6 @@ int64_t AffineExpr::getLargestKnownDivisor() const {
|
||||||
}
|
}
|
||||||
case AffineExprKind::Add:
|
case AffineExprKind::Add:
|
||||||
LLVM_FALLTHROUGH;
|
LLVM_FALLTHROUGH;
|
||||||
case AffineExprKind::FloorDiv:
|
|
||||||
case AffineExprKind::CeilDiv:
|
|
||||||
case AffineExprKind::Mod: {
|
case AffineExprKind::Mod: {
|
||||||
binExpr = cast<AffineBinaryOpExpr>();
|
binExpr = cast<AffineBinaryOpExpr>();
|
||||||
return llvm::GreatestCommonDivisor64(
|
return llvm::GreatestCommonDivisor64(
|
||||||
|
|
|
@ -468,6 +468,30 @@ func @loop_nest_operand2() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UNROLL-BY-4-LABEL: func @floordiv_mod_ub
|
||||||
|
func @floordiv_mod_ub(%M : index, %N : index) {
|
||||||
|
affine.for %i = 0 to %N step 4 {
|
||||||
|
// A cleanup should be generated here.
|
||||||
|
affine.for %j = 0 to min affine_map<(d0)[s0] -> ((16 * d0) floordiv (4 * s0))>(%i)[%N] {
|
||||||
|
"test.foo"() : () -> ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// UNROLL-BY-4-NEXT: affine.for
|
||||||
|
// UNROLL-BY-4-NEXT: affine.for %{{.*}} = 0 to {{.*}} step 4
|
||||||
|
// UNROLL-BY-4: affine.for
|
||||||
|
affine.for %i = 0 to %N step 4 {
|
||||||
|
// No cleanup needed here.
|
||||||
|
affine.for %j = 0 to min affine_map<(d0)[s0] -> ((16 * d0) mod (4 * s0))>(%i)[%N] {
|
||||||
|
"test.foo"() : () -> ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// UNROLL-BY-4: affine.for
|
||||||
|
// UNROLL-BY-4-NEXT: affine.for %{{.*}} = 0 to {{.*}} step 4
|
||||||
|
// UNROLL-BY-4-NOT: affine.for
|
||||||
|
// UNROLL-BY-4: return
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Difference between loop bounds is constant, but not a multiple of unroll
|
// Difference between loop bounds is constant, but not a multiple of unroll
|
||||||
// factor. The cleanup loop happens to be a single iteration one and is promoted.
|
// factor. The cleanup loop happens to be a single iteration one and is promoted.
|
||||||
// UNROLL-BY-4-LABEL: func @loop_nest_operand3() {
|
// UNROLL-BY-4-LABEL: func @loop_nest_operand3() {
|
||||||
|
|
Loading…
Reference in New Issue