22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/Support/CommandLine.h"
24 #include "llvm/Support/Debug.h"
29 #define GEN_PASS_DEF_AFFINELOOPUNROLL
30 #include "mlir/Dialect/Affine/Passes.h.inc"
34 #define DEBUG_TYPE "affine-loop-unroll"
48 struct LoopUnroll :
public affine::impl::AffineLoopUnrollBase<LoopUnroll> {
51 const std::function<unsigned(AffineForOp)> getUnrollFactor;
53 LoopUnroll() : getUnrollFactor(
nullptr) {}
54 LoopUnroll(
const LoopUnroll &other)
58 std::optional<unsigned> unrollFactor = std::nullopt,
59 bool unrollUpToFactor =
false,
bool unrollFull =
false,
60 const std::function<
unsigned(AffineForOp)> &getUnrollFactor =
nullptr)
61 : getUnrollFactor(getUnrollFactor) {
63 this->unrollFactor = *unrollFactor;
64 this->unrollUpToFactor = unrollUpToFactor;
65 this->unrollFull = unrollFull;
68 void runOnOperation()
override;
71 LogicalResult runOnAffineForOp(AffineForOp forOp);
78 ->walk([&](AffineForOp nestedForOp) {
87 f.walk([&](AffineForOp forOp) {
89 loops.push_back(forOp);
93 void LoopUnroll::runOnOperation() {
94 func::FuncOp func = getOperation();
95 if (func.isExternal())
98 if (unrollFull && unrollFullThreshold.hasValue()) {
105 getOperation().walk([&](AffineForOp forOp) {
107 if (tripCount && *tripCount <= unrollFullThreshold)
108 loops.push_back(forOp);
110 for (
auto forOp : loops)
117 for (
unsigned i = 0; i < numRepetitions || getUnrollFactor; i++) {
122 bool unrolled =
false;
123 for (
auto forOp : loops)
124 unrolled |= succeeded(runOnAffineForOp(forOp));
133 LogicalResult LoopUnroll::runOnAffineForOp(AffineForOp forOp) {
137 nullptr, cleanUpUnroll);
142 if (unrollUpToFactor)
149 int unrollFactor,
bool unrollUpToFactor,
bool unrollFull,
150 const std::function<
unsigned(AffineForOp)> &getUnrollFactor) {
151 return std::make_unique<LoopUnroll>(
152 unrollFactor == -1 ? std::nullopt : std::optional<unsigned>(unrollFactor),
153 unrollUpToFactor, unrollFull, getUnrollFactor);
static bool isInnermostAffineForOp(AffineForOp op)
Returns true if no other affine.for ops are nested within op.
static void gatherInnermostLoops(func::FuncOp f, SmallVectorImpl< AffineForOp > &loops)
Gathers loops that have no affine.for's nested within.
static WalkResult interrupt()
std::optional< uint64_t > getConstantTripCount(AffineForOp forOp)
Returns the trip count of the loop if it's a constant, std::nullopt otherwise.
LogicalResult loopUnrollFull(AffineForOp forOp)
Unrolls this for operation completely if the trip count is known to be constant.
LogicalResult loopUnrollByFactor(AffineForOp forOp, uint64_t unrollFactor, function_ref< void(unsigned, Operation *, OpBuilder)> annotateFn=nullptr, bool cleanUpUnroll=false)
Unrolls this for operation by the specified unroll factor.
LogicalResult loopUnrollUpToFactor(AffineForOp forOp, uint64_t unrollFactor)
Unrolls this loop by the specified unroll factor or its trip count, whichever is lower.
std::unique_ptr< OperationPass< func::FuncOp > > createLoopUnrollPass(int unrollFactor=-1, bool unrollUpToFactor=false, bool unrollFull=false, const std::function< unsigned(AffineForOp)> &getUnrollFactor=nullptr)
Creates a loop unrolling pass with the provided parameters.
Include the generated interface declarations.