@@ -3240,58 +3240,58 @@ class FirConverter : public Fortran::lower::AbstractConverter {
32403240 }
32413241 }
32423242
3243- // Collect prologue and tail (after-inner) statements if force
3244- llvm::SmallVector<Fortran::lower::pft::Evaluation *> prologue, tail;
3245- if (collapseForce && loopCount > 1 && getEval ().lowerAsStructured ()) {
3246- auto hasKids = [](Fortran::lower::pft::Evaluation *ev) -> bool {
3247- return ev && ev->hasNestedEvaluations ();
3248- };
3243+ const bool isStructured = curEval && curEval->lowerAsStructured ();
3244+ if (isStructured && collapseForce && collapseDepth > 1 ) {
3245+ // force: collect prologue/epilogue for the first collapseDepth nested loops
3246+ // and sink them into the innermost loop body at that depth
3247+ llvm::SmallVector<Fortran::lower::pft::Evaluation *> prologue, epilogue;
32493248 Fortran::lower::pft::Evaluation *parent = &getEval ();
3250- uint64_t levelsToProcess = std::min<uint64_t >(collapseDepth, loopCount);
3251- for (uint64_t lvl = 0 ; lvl + 1 < levelsToProcess; ++lvl) {
3252- if (!hasKids (parent)) break ;
3253- Fortran::lower::pft::Evaluation *childLoop = nullptr ;
3254- tail.clear ();
3249+ Fortran::lower::pft::Evaluation *innermostLoopEval = nullptr ;
3250+ for (uint64_t lvl = 0 ; lvl + 1 < collapseDepth; ++lvl) {
3251+ epilogue.clear ();
32553252 auto &kids = parent->getNestedEvaluations ();
3253+ // Collect all non-loop statements before the next inner loop as prologue,
3254+ // then mark remaining siblings as epilogue and descend into the inner loop.
3255+ Fortran::lower::pft::Evaluation *childLoop = nullptr ;
32563256 for (auto it = kids.begin (); it != kids.end (); ++it) {
32573257 if (it->getIf <Fortran::parser::DoConstruct>()) {
32583258 childLoop = &*it;
32593259 for (auto it2 = std::next (it); it2 != kids.end (); ++it2)
3260- tail .push_back (&*it2);
3260+ epilogue .push_back (&*it2);
32613261 break ;
32623262 }
32633263 prologue.push_back (&*it);
32643264 }
3265- if (!childLoop) break ;
3265+ // Semantics guarantees collapseDepth does not exceed nest depth
3266+ // so childLoop must be found here.
3267+ assert (childLoop && " Expected inner DoConstruct for collapse" );
32663268 parent = childLoop;
3269+ innermostLoopEval = childLoop;
32673270 }
3268- }
32693271
3270- // Track sunk evaluations to avoid double-lowering
3271- llvm::SmallPtrSet<const Fortran::lower::pft::Evaluation *, 16 > sunk;
3272- for (auto *e : prologue) sunk.insert (e);
3273- for (auto *e : tail) sunk.insert (e);
3272+ // Track sunk evaluations ( avoid double-lowering)
3273+ llvm::SmallPtrSet<const Fortran::lower::pft::Evaluation *, 16 > sunk;
3274+ for (auto *e : prologue) sunk.insert (e);
3275+ for (auto *e : epilogue) sunk.insert (e);
32743276
3275- // Prologue sink
3276- for (auto *e : prologue)
3277- genFIR (*e) ;
3277+ auto emit = [&](llvm::SmallVector<Fortran::lower::pft::Evaluation *> &lst) {
3278+ for (auto *e : lst) genFIR (*e);
3279+ } ;
32783280
3279- // Lower the loop body as usual, skipping already-sunk evals
3280- if (curEval && curEval->hasNestedEvaluations ()) {
3281- for (Fortran::lower::pft::Evaluation &e : curEval->getNestedEvaluations ()) {
3282- if (sunk.contains (&e)) continue ;
3283- genFIR (e);
3284- }
3285- } else if (getEval ().hasNestedEvaluations ()) {
3286- for (Fortran::lower::pft::Evaluation &e : getEval ().getNestedEvaluations ()) {
3287- if (sunk.contains (&e)) continue ;
3281+ // Sink prologue
3282+ emit (prologue);
3283+
3284+ // Lower innermost loop body, skipping sunk
3285+ for (Fortran::lower::pft::Evaluation &e : innermostLoopEval->getNestedEvaluations ())
3286+ if (!sunk.contains (&e)) genFIR (e);
3287+
3288+ // Sink epilogue
3289+ emit (epilogue);
3290+ } else {
3291+ // Normal lowering
3292+ for (Fortran::lower::pft::Evaluation &e : curEval->getNestedEvaluations ())
32883293 genFIR (e);
3289- }
32903294 }
3291-
3292- // Epilogue sink
3293- for (auto *e : tail)
3294- genFIR (*e);
32953295 localSymbols.popScope ();
32963296 builder->restoreInsertionPoint (insertPt);
32973297
0 commit comments