Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions mlir/lib/Dialect/Affine/IR/AffineOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2610,6 +2610,21 @@ static std::optional<uint64_t> getTrivialConstantTripCount(AffineForOp forOp) {
return ub - lb <= 0 ? 0 : (ub - lb + step - 1) / step;
}

/// Calculate the constant value of the loop's induction variable for its last
/// trip.
static std::optional<int64_t>
getConstantInductionVarForLastTrip(AffineForOp forOp) {
std::optional<uint64_t> tripCount = getTrivialConstantTripCount(forOp);
if (!tripCount.has_value())
return std::nullopt;
if (tripCount.value() == 0)
return std::nullopt;
int64_t lb = forOp.getConstantLowerBound();
int64_t step = forOp.getStepAsInt();
int64_t lastTripIv = lb + (tripCount.value() - 1) * step;
return lastTripIv;
}

/// Fold the empty loop.
static SmallVector<OpFoldResult> AffineForEmptyLoopFolder(AffineForOp forOp) {
if (!llvm::hasSingleElement(*forOp.getBody()))
Expand All @@ -2622,18 +2637,22 @@ static SmallVector<OpFoldResult> AffineForEmptyLoopFolder(AffineForOp forOp) {
// results.
return forOp.getInits();
}
SmallVector<Value, 4> replacements;
SmallVector<OpFoldResult, 4> replacements;
auto yieldOp = cast<AffineYieldOp>(forOp.getBody()->getTerminator());
auto iterArgs = forOp.getRegionIterArgs();
bool hasValDefinedOutsideLoop = false;
bool iterArgsNotInOrder = false;
for (unsigned i = 0, e = yieldOp->getNumOperands(); i < e; ++i) {
Value val = yieldOp.getOperand(i);
BlockArgument *iterArgIt = llvm::find(iterArgs, val);
// TODO: It should be possible to perform a replacement by computing the
// last value of the IV based on the bounds and the step.
if (val == forOp.getInductionVar())
if (val == forOp.getInductionVar()) {
if (auto lastTripIv = getConstantInductionVarForLastTrip(forOp)) {
replacements.push_back(IntegerAttr::get(
IndexType::get(forOp.getContext()), lastTripIv.value()));
continue;
}
return {};
}
if (iterArgIt == iterArgs.end()) {
// `val` is defined outside of the loop.
assert(forOp.isDefinedOutsideOfLoop(val) &&
Expand All @@ -2656,7 +2675,7 @@ static SmallVector<OpFoldResult> AffineForEmptyLoopFolder(AffineForOp forOp) {
// out of order.
if (tripCount.has_value() && tripCount.value() >= 2 && iterArgsNotInOrder)
return {};
return llvm::to_vector_of<OpFoldResult>(replacements);
return llvm::to_vector(replacements);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the previous error? Can you share the link to the buildbot that complained? I don't understand why this would fix anything.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://lab.llvm.org/buildbot/#/builders/117/builds/14631 you can see it in the build-unified-tree.

71.321 [1324/4/3756] Building CXX object tools/mlir/lib/Dialect/Ptr/IR/CMakeFiles/obj.MLIRPtrDialect.dir/PtrDialect.cpp.o
71.352 [1323/4/3757] Building CXX object tools/mlir/lib/Dialect/PDL/IR/CMakeFiles/obj.MLIRPDLDialect.dir/PDLTypes.cpp.o
71.394 [1322/4/3758] Building CXX object tools/mlir/lib/Dialect/PDLInterp/IR/CMakeFiles/obj.MLIRPDLInterpDialect.dir/PDLInterp.cpp.o
71.435 [1321/4/3759] Building CXX object tools/mlir/lib/Dialect/Ptr/IR/CMakeFiles/obj.MLIRPtrMemorySpaceInterfaces.dir/MemorySpaceInterfaces.cpp.o
71.448 [1320/4/3760] Linking CXX static library lib/libMLIRPDLDialect.a
71.518 [1319/4/3761] Linking CXX static library lib/libMLIRPtrMemorySpaceInterfaces.a
71.551 [1318/4/3762] Linking CXX static library lib/libMLIRPDLInterpDialect.a
71.597 [1317/4/3763] Building CXX object tools/mlir/lib/Dialect/Affine/IR/CMakeFiles/obj.MLIRAffineDialect.dir/AffineOps.cpp.o
FAILED: tools/mlir/lib/Dialect/Affine/IR/CMakeFiles/obj.MLIRAffineDialect.dir/AffineOps.cpp.o 
CCACHE_CPP2=yes CCACHE_HASHDIR=yes CCACHE_SLOPPINESS=pch_defines,time_macros /usr/bin/ccache /usr/bin/c++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/uweigand/sandbox/buildbot/mlir-s390x-linux/build/tools/mlir/lib/Dialect/Affine/IR -I/home/uweigand/sandbox/buildbot/mlir-s390x-linux/llvm-project/mlir/lib/Dialect/Affine/IR -I/home/uweigand/sandbox/buildbot/mlir-s390x-linux/build/tools/mlir/include -I/home/uweigand/sandbox/buildbot/mlir-s390x-linux/llvm-project/mlir/include -I/home/uweigand/sandbox/buildbot/mlir-s390x-linux/build/include -I/home/uweigand/sandbox/buildbot/mlir-s390x-linux/llvm-project/llvm/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-array-bounds -Wno-stringop-overread -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -Wno-misleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wundef -Wno-unused-but-set-parameter -Wno-deprecated-copy -O3 -DNDEBUG  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -std=c++17 -MD -MT tools/mlir/lib/Dialect/Affine/IR/CMakeFiles/obj.MLIRAffineDialect.dir/AffineOps.cpp.o -MF tools/mlir/lib/Dialect/Affine/IR/CMakeFiles/obj.MLIRAffineDialect.dir/AffineOps.cpp.o.d -o tools/mlir/lib/Dialect/Affine/IR/CMakeFiles/obj.MLIRAffineDialect.dir/AffineOps.cpp.o -c /home/uweigand/sandbox/buildbot/mlir-s390x-linux/llvm-project/mlir/lib/Dialect/Affine/IR/AffineOps.cpp
/home/uweigand/sandbox/buildbot/mlir-s390x-linux/llvm-project/mlir/lib/Dialect/Affine/IR/AffineOps.cpp: In function ‘llvm::SmallVector<mlir::OpFoldResult> AffineForEmptyLoopFolder(mlir::affine::AffineForOp)’:
/home/uweigand/sandbox/buildbot/mlir-s390x-linux/llvm-project/mlir/lib/Dialect/Affine/IR/AffineOps.cpp:2678:10: error: could not convert ‘replacements’ from ‘SmallVector<[...],4>’ to ‘SmallVector<[...],6>’
 2678 |   return replacements;
      |          ^~~~~~~~~~~~
      |          |

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My apologies, I misunderstood your earlier point. I thought you wanted me to use to_vector_of<T>.

}

/// Canonicalize the bounds of the given loop.
Expand Down
13 changes: 13 additions & 0 deletions mlir/test/Dialect/Affine/canonicalize.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,19 @@ func.func @fold_zero_iter_loops(%in : index) -> index {

// -----

// CHECK-LABEL: func @fold_empty_loop_iv
// CHECK-SAME: %[[INIT:.*]]: index
func.func @fold_empty_loop_iv(%init: index) -> (index, index) {
%res:2 = affine.for %i = 0 to 10 step 1 iter_args(%arg0 = %init, %arg1 = %init) -> (index, index) {
affine.yield %i, %arg1 : index, index
}
// CHECK: %[[C9:.*]] = arith.constant 9 : index
// CHECK: return %[[C9]], %[[INIT]] : index, index
return %res#0, %res#1 : index, index
}

// -----

// CHECK-DAG: #[[$SET:.*]] = affine_set<(d0, d1)[s0] : (d0 >= 0, -d0 + 1022 >= 0, d1 >= 0, -d1 + s0 - 2 >= 0)>

// CHECK-LABEL: func @canonicalize_affine_if
Expand Down