Skip to content

Commit e1fb9d5

Browse files
committed
[MLIR][NFC] modernize affine.for unroll test pass
The walk code here was written before any of the support was available in IR/. Replace/cleanup. Differential Revision: https://reviews.llvm.org/D77166
1 parent cc3fddb commit e1fb9d5

File tree

1 file changed

+29
-37
lines changed

1 file changed

+29
-37
lines changed

mlir/lib/Dialect/Affine/Transforms/LoopUnroll.cpp

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ static llvm::cl::opt<unsigned> clUnrollFullThreshold(
5050
llvm::cl::cat(clOptionsCategory));
5151

5252
namespace {
53+
54+
// TODO: this is really a test pass and should be moved out of dialect
55+
// transforms.
56+
5357
/// Loop unrolling pass. Unrolls all innermost loops unless full unrolling and a
5458
/// full unroll threshold was specified, in which case, fully unrolls all loops
5559
/// with trip count less than the specified threshold. The latter is for testing
@@ -76,44 +80,32 @@ struct LoopUnroll : public FunctionPass<LoopUnroll> {
7680
};
7781
} // end anonymous namespace
7882

79-
void LoopUnroll::runOnFunction() {
80-
// Gathers all innermost loops through a post order pruned walk.
81-
struct InnermostLoopGatherer {
82-
// Store innermost loops as we walk.
83-
std::vector<AffineForOp> loops;
84-
85-
void walkPostOrder(FuncOp f) {
86-
for (auto &b : f)
87-
walkPostOrder(b.begin(), b.end());
88-
}
89-
90-
bool walkPostOrder(Block::iterator Start, Block::iterator End) {
91-
bool hasInnerLoops = false;
92-
// We need to walk all elements since all innermost loops need to be
93-
// gathered as opposed to determining whether this list has any inner
94-
// loops or not.
95-
while (Start != End)
96-
hasInnerLoops |= walkPostOrder(&(*Start++));
97-
return hasInnerLoops;
98-
}
99-
bool walkPostOrder(Operation *opInst) {
100-
bool hasInnerLoops = false;
101-
for (auto &region : opInst->getRegions())
102-
for (auto &block : region)
103-
hasInnerLoops |= walkPostOrder(block.begin(), block.end());
104-
if (isa<AffineForOp>(opInst)) {
105-
if (!hasInnerLoops)
106-
loops.push_back(cast<AffineForOp>(opInst));
107-
return true;
108-
}
109-
return hasInnerLoops;
110-
}
111-
};
83+
/// Returns true if no other affine.for ops are nested within.
84+
static bool isInnermostAffineForOp(AffineForOp forOp) {
85+
// Only for the innermost affine.for op's.
86+
bool isInnermost = true;
87+
forOp.walk([&](AffineForOp thisForOp) {
88+
// Since this is a post order walk, we are able to conclude here.
89+
isInnermost = (thisForOp == forOp);
90+
return WalkResult::interrupt();
91+
});
92+
return isInnermost;
93+
}
11294

95+
/// Gathers loops that have no affine.for's nested within.
96+
static void gatherInnermostLoops(FuncOp f,
97+
SmallVectorImpl<AffineForOp> &loops) {
98+
f.walk([&](AffineForOp forOp) {
99+
if (isInnermostAffineForOp(forOp))
100+
loops.push_back(forOp);
101+
});
102+
}
103+
104+
void LoopUnroll::runOnFunction() {
113105
if (clUnrollFull.getNumOccurrences() > 0 &&
114106
clUnrollFullThreshold.getNumOccurrences() > 0) {
115107
// Store short loops as we walk.
116-
std::vector<AffineForOp> loops;
108+
SmallVector<AffineForOp, 4> loops;
117109

118110
// Gathers all loops with trip count <= minTripCount. Do a post order walk
119111
// so that loops are gathered from innermost to outermost (or else unrolling
@@ -133,10 +125,10 @@ void LoopUnroll::runOnFunction() {
133125
: 1;
134126
// If the call back is provided, we will recurse until no loops are found.
135127
FuncOp func = getFunction();
128+
SmallVector<AffineForOp, 4> loops;
136129
for (unsigned i = 0; i < numRepetitions || getUnrollFactor; i++) {
137-
InnermostLoopGatherer ilg;
138-
ilg.walkPostOrder(func);
139-
auto &loops = ilg.loops;
130+
loops.clear();
131+
gatherInnermostLoops(func, loops);
140132
if (loops.empty())
141133
break;
142134
bool unrolled = false;

0 commit comments

Comments
 (0)