@@ -50,6 +50,10 @@ static llvm::cl::opt<unsigned> clUnrollFullThreshold(
50
50
llvm::cl::cat(clOptionsCategory));
51
51
52
52
namespace {
53
+
54
+ // TODO: this is really a test pass and should be moved out of dialect
55
+ // transforms.
56
+
53
57
// / Loop unrolling pass. Unrolls all innermost loops unless full unrolling and a
54
58
// / full unroll threshold was specified, in which case, fully unrolls all loops
55
59
// / with trip count less than the specified threshold. The latter is for testing
@@ -76,44 +80,32 @@ struct LoopUnroll : public FunctionPass<LoopUnroll> {
76
80
};
77
81
} // end anonymous namespace
78
82
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 ®ion : 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
+ }
112
94
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 () {
113
105
if (clUnrollFull.getNumOccurrences () > 0 &&
114
106
clUnrollFullThreshold.getNumOccurrences () > 0 ) {
115
107
// Store short loops as we walk.
116
- std::vector <AffineForOp> loops;
108
+ SmallVector <AffineForOp, 4 > loops;
117
109
118
110
// Gathers all loops with trip count <= minTripCount. Do a post order walk
119
111
// so that loops are gathered from innermost to outermost (or else unrolling
@@ -133,10 +125,10 @@ void LoopUnroll::runOnFunction() {
133
125
: 1 ;
134
126
// If the call back is provided, we will recurse until no loops are found.
135
127
FuncOp func = getFunction ();
128
+ SmallVector<AffineForOp, 4 > loops;
136
129
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);
140
132
if (loops.empty ())
141
133
break ;
142
134
bool unrolled = false ;
0 commit comments