[flang-commits] [flang] [flang][PFT] record every target of an assigned GO TO (PR #210065)
via flang-commits
flang-commits at lists.llvm.org
Thu Jul 16 07:02:47 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Kareem Ergawy (ergawy)
<details>
<summary>Changes</summary>
Assigned GO TO (`go to v [, (l1, l2, ...)]`) is the third multiway branch in the language, alongside the computed GO TO and arithmetic IF that were addressed in PR #<!-- -->210012. Its PFTBuilder handler previously did:
[&](const parser::AssignedGotoStmt &) {
eval.isUnstructured = true;
markSuccessorAsNewBlock(eval);
},
i.e. it recorded no branch targets at all -- neither `controlSuccessor` nor `extraControlSuccessors` was populated.
Handle the assigned GO TO the same way PR #<!-- -->210012 handles the computed GO TO and arithmetic IF: iterate every possible target and call `markBranchTarget(eval, label)` for each, so that `controlSuccessor` receives the first and `extraControlSuccessors` receives the rest.
---
Full diff: https://github.com/llvm/llvm-project/pull/210065.diff
2 Files Affected:
- (modified) flang/lib/Lower/PFTBuilder.cpp (+23-4)
- (added) flang/test/Lower/pre-fir-tree-assigned-goto.f90 (+47)
``````````diff
diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index 3a0c0c3d71075..ef86897a2bcc1 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -1039,10 +1039,29 @@ class PFTBuilder {
iter->second.insert(label);
}
},
- [&](const parser::AssignedGotoStmt &) {
- // Although this statement is a branch, it doesn't have any
- // explicit control successors. So the code at the end of the
- // loop won't mark the successor. Do that here.
+ [&](const parser::AssignedGotoStmt &s) {
+ // Mark every possible target of the assigned GO TO so that
+ // wrappability analyses (branchesAreInternal, hasIncomingBranch)
+ // can see any escape from an enclosing construct.
+ const auto &labelList = std::get<std::list<parser::Label>>(s.t);
+ if (!labelList.empty()) {
+ // Explicit target list: `go to v, (l1, l2, ...)`.
+ for (const auto &label : labelList)
+ markBranchTarget(eval, label);
+ } else {
+ // No explicit list (`go to v`): fall back to the set of labels
+ // that have been previously ASSIGN'd to v.
+ // TODO: This may miss assignments that appear later in program
+ // order, but it matches the information available at this point
+ // in the walk.
+ const auto *sym = std::get<parser::Name>(s.t).symbol;
+ if (sym) {
+ auto iter = assignSymbolLabelMap->find(*sym);
+ if (iter != assignSymbolLabelMap->end())
+ for (auto label : iter->second)
+ markBranchTarget(eval, label);
+ }
+ }
eval.isUnstructured = true;
markSuccessorAsNewBlock(eval);
},
diff --git a/flang/test/Lower/pre-fir-tree-assigned-goto.f90 b/flang/test/Lower/pre-fir-tree-assigned-goto.f90
new file mode 100644
index 0000000000000..757a838d592b8
--- /dev/null
+++ b/flang/test/Lower/pre-fir-tree-assigned-goto.f90
@@ -0,0 +1,47 @@
+! RUN: bbc -pft-test -o %t %s | FileCheck %s
+
+! Verify that assigned GO TO records every reachable branch target on the
+! source evaluation, so wrappability analyses see any escape from an
+! enclosing DO/IF construct. The dumper prints the first target after
+! "->" and any additional targets after commas -- same convention as the
+! computed GO TO and arithmetic IF coverage in
+! pre-fir-tree-multiway-branch.f90.
+!
+! Two source forms are exercised:
+! 1. `go to v, (l1, l2, ...)` -- targets come from the explicit label list.
+! 2. `go to v` -- targets come from labels previously
+! ASSIGN'd to `v` (assignSymbolLabelMap).
+
+! CHECK-LABEL: Subroutine assigned_goto_with_list
+subroutine assigned_goto_with_list(j)
+ integer :: j
+ assign 10 to j
+ ! CHECK: AssignedGotoStmt{{.*}} -> {{[0-9]+}}, {{[0-9]+}}:
+ go to j, (10, 20)
+10 print *, "ten"
+20 print *, "twenty"
+end subroutine
+
+! CHECK-LABEL: Subroutine assigned_goto_no_list
+subroutine assigned_goto_no_list(j)
+ integer :: j
+ assign 10 to j
+ assign 20 to j
+ ! CHECK: AssignedGotoStmt{{.*}} -> {{[0-9]+}}, {{[0-9]+}}:
+ go to j
+10 print *, "ten"
+20 print *, "twenty"
+end subroutine
+
+! CHECK-LABEL: Subroutine assigned_goto_repeated_label
+subroutine assigned_goto_repeated_label(j)
+ integer :: j
+ assign 10 to j
+ ! The label list repeats 10. Dedup means the source lists exactly two
+ ! distinct successors, not three -- the trailing ':' anchors the check so
+ ! a third comma-separated target would fail the match.
+ ! CHECK: AssignedGotoStmt{{.*}} -> {{[0-9]+}}, {{[0-9]+}}:
+ go to j, (10, 10, 20)
+10 print *, "ten"
+20 print *, "twenty"
+end subroutine
``````````
</details>
https://github.com/llvm/llvm-project/pull/210065
More information about the flang-commits
mailing list