[flang-commits] [flang] [flang] Delete a trailing CYCLE that is the last statement of its DO (PR #223399)

Kareem Ergawy via flang-commits flang-commits at lists.llvm.org
Tue Sep 15 03:03:30 PDT 2026


================
@@ -677,6 +678,58 @@ class PFTBuilder {
     evaluationListStack.pop_back();
   }
 
+  /// Delete a CycleStmt that is the last statement of the body of its own
+  /// DoConstruct, where it is a no-op. The pre-branch-analysis code:
+  ///
+  ///       <<DoConstruct>>
+  ///         1 NonLabelDoStmt: do n = 1, nb
+  ///         2 Statement: ...
+  ///         3 CycleStmt: cycle
+  ///         4 EndDoStmt
+  ///       <<End DoConstruct>>
+  ///
+  /// becomes:
+  ///
+  ///       <<DoConstruct>>
+  ///         1 NonLabelDoStmt: do n = 1, nb
+  ///         2 Statement: ...
+  ///         4 EndDoStmt
+  ///       <<End DoConstruct>>
+  ///
+  /// Branching to the EndDoStmt and falling through to it are the same thing,
+  /// so the CycleStmt has no effect. Deleting it matters because branch
+  /// analysis otherwise marks the DoConstruct unstructured, which costs the
+  /// structured form of the loop -- and with it the induction variable
+  /// semantics that later passes rely on.
+  void rewriteTrailingCycle() {
+    auto &evaluationList = *evaluationListStack.back();
+    if (evaluationList.size() < 3)
+      return;
+    const auto *doStmt =
+        evaluationList.begin()->getIf<parser::NonLabelDoStmt>();
+    if (!doStmt)
+      return;
+    lower::pft::EvaluationList::iterator endDoStmtIt =
+        std::prev(evaluationList.end());
+    if (!endDoStmtIt->isA<parser::EndDoStmt>())
+      return;
+    lower::pft::EvaluationList::iterator cycleStmtIt = std::prev(endDoStmtIt);
+    const auto *cycleStmt = cycleStmtIt->getIf<parser::CycleStmt>();
+    if (!cycleStmt || cycleStmtIt->label)
+      return;
+    std::string cycleName = getConstructName(*cycleStmt);
+    if (!cycleName.empty() && cycleName != getConstructName(*doStmt))
+      return; // cycle for an outer construct
+    // Relink the lexical predecessor of the CycleStmt to the EndDoStmt. That
+    // predecessor is the last statement reachable from the preceding
+    // evaluation, so descend through nested evaluation lists to find it.
+    lower::pft::Evaluation *predecessor = &*std::prev(cycleStmtIt);
+    while (predecessor->evaluationList && !predecessor->evaluationList->empty())
+      predecessor = &predecessor->evaluationList->back();
+    predecessor->lexicalSuccessor = cycleStmtIt->lexicalSuccessor;
----------------
ergawy wrote:

Done in 8756ee115ca429c2d5dc209d1615f2daf30ea723.

https://github.com/llvm/llvm-project/pull/223399


More information about the flang-commits mailing list