@@ -163,12 +163,77 @@ namespace looputils {
163163// / Stores info needed about the induction/iteration variable for each `do
164164// / concurrent` in a loop nest.
165165struct InductionVariableInfo {
166+ InductionVariableInfo (fir::DoLoopOp doLoop) { populateInfo (doLoop); }
167+
166168 // / The operation allocating memory for iteration variable.
167169 mlir::Operation *iterVarMemDef;
168170
169171 // / the operation(s) updating the iteration variable with the current
170172 // / 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+ }
172237};
173238
174239using LoopNestToIndVarMap =
@@ -462,11 +527,7 @@ mlir::LogicalResult collectLoopNest(fir::DoLoopOp currentLoop,
462527 assert (currentLoop.getUnordered ());
463528
464529 while (true ) {
465- loopNest.insert (
466- {currentLoop,
467- InductionVariableInfo{
468- findLoopIterationVarMemDecl (currentLoop),
469- std::move (looputils::extractIndVarUpdateOps (currentLoop))}});
530+ loopNest.insert ({currentLoop, InductionVariableInfo (currentLoop)});
470531 llvm::SmallVector<fir::DoLoopOp> unorderedLoops;
471532
472533 for (auto nestedLoop : currentLoop.getRegion ().getOps <fir::DoLoopOp>())
0 commit comments