@@ -163,12 +163,77 @@ namespace looputils {
163
163
// / Stores info needed about the induction/iteration variable for each `do
164
164
// / concurrent` in a loop nest.
165
165
struct InductionVariableInfo {
166
+ InductionVariableInfo (fir::DoLoopOp doLoop) { populateInfo (doLoop); }
167
+
166
168
// / The operation allocating memory for iteration variable.
167
169
mlir::Operation *iterVarMemDef;
168
170
169
171
// / the operation(s) updating the iteration variable with the current
170
172
// / iteration number.
171
- llvm::SetVector<mlir::Operation *> indVarUpdateOps;
173
+ llvm::SmallVector<mlir::Operation *> indVarUpdateOps;
174
+
175
+ private:
176
+ // / For the \p doLoop parameter, find the following:
177
+ // /
178
+ // / 1. The operation that declares its iteration variable or allocates memory
179
+ // / for it. For example, give the following loop:
180
+ // / ```
181
+ // / ...
182
+ // / %i:2 = hlfir.declare %0 {uniq_name = "_QFEi"} : ...
183
+ // / ...
184
+ // / fir.do_loop %ind_var = %lb to %ub step %s unordered {
185
+ // / %ind_var_conv = fir.convert %ind_var : (index) -> i32
186
+ // / fir.store %ind_var_conv to %i#1 : !fir.ref<i32>
187
+ // / ...
188
+ // / }
189
+ // / ```
190
+ // /
191
+ // / This function sets the `iterVarMemDef` member to the `hlfir.declare` op
192
+ // / for `%i`.
193
+ // /
194
+ // / 2. The operation(s) that update the loop's iteration variable from its
195
+ // / induction variable. For the above example, the `indVarUpdateOps` is
196
+ // / populated with the first 2 ops in the loop's body.
197
+ // /
198
+ // / Note: The current implementation is dependent on how flang emits loop
199
+ // / bodies; which is sufficient for the current simple test/use cases. If this
200
+ // / proves to be insufficient, this should be made more generic.
201
+ void populateInfo (fir::DoLoopOp doLoop) {
202
+ mlir::Value result = nullptr ;
203
+
204
+ // Checks if a StoreOp is updating the memref of the loop's iteration
205
+ // variable.
206
+ auto isStoringIV = [&](fir::StoreOp storeOp) {
207
+ // Direct store into the IV memref.
208
+ if (storeOp.getValue () == doLoop.getInductionVar ()) {
209
+ indVarUpdateOps.push_back (storeOp);
210
+ return true ;
211
+ }
212
+
213
+ // Indirect store into the IV memref.
214
+ if (auto convertOp = mlir::dyn_cast<fir::ConvertOp>(
215
+ storeOp.getValue ().getDefiningOp ())) {
216
+ if (convertOp.getOperand () == doLoop.getInductionVar ()) {
217
+ indVarUpdateOps.push_back (convertOp);
218
+ indVarUpdateOps.push_back (storeOp);
219
+ return true ;
220
+ }
221
+ }
222
+
223
+ return false ;
224
+ };
225
+
226
+ for (mlir::Operation &op : doLoop) {
227
+ if (auto storeOp = mlir::dyn_cast<fir::StoreOp>(op))
228
+ if (isStoringIV (storeOp)) {
229
+ result = storeOp.getMemref ();
230
+ break ;
231
+ }
232
+ }
233
+
234
+ assert (result != nullptr && result.getDefiningOp () != nullptr );
235
+ iterVarMemDef = result.getDefiningOp ();
236
+ }
172
237
};
173
238
174
239
using LoopNestToIndVarMap =
@@ -462,11 +527,7 @@ mlir::LogicalResult collectLoopNest(fir::DoLoopOp currentLoop,
462
527
assert (currentLoop.getUnordered ());
463
528
464
529
while (true ) {
465
- loopNest.insert (
466
- {currentLoop,
467
- InductionVariableInfo{
468
- findLoopIterationVarMemDecl (currentLoop),
469
- std::move (looputils::extractIndVarUpdateOps (currentLoop))}});
530
+ loopNest.insert ({currentLoop, InductionVariableInfo (currentLoop)});
470
531
llvm::SmallVector<fir::DoLoopOp> unorderedLoops;
471
532
472
533
for (auto nestedLoop : currentLoop.getRegion ().getOps <fir::DoLoopOp>())
0 commit comments