diff options
| author | Krzysztof Parzyszek <Krzysztof.Parzyszek@amd.com> | 2025-11-22 16:51:00 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-22 16:51:00 -0600 |
| commit | c81a189c5083b72c128ec33cda8d39367c2e2f1f (patch) | |
| tree | 5dacc28fad57733c764f67752084db7515d7a3d5 /flang/lib/Parser/openmp-utils.cpp | |
| parent | a2231af5ddafbc82c9d6ecc994690639958c6661 (diff) | |
[flang][OpenMP] Canonicalize loops with intervening OpenMP constructs (#169191)
Example based on the gfortran test a.6.1.f90
```
do 100 i = 1,10
!$omp do
do 100 j = 1,10
call work(i,j)
100 continue
```
During canonicalization of label-DO loops, if the body of an OpenMP
construct ends with a label, treat the label as ending the construct
itself.
This will also allow handling of cases like
```
do 100 i = 1, 10
!$omp atomic write
100 x = i
```
which we were unable to before.
Diffstat (limited to 'flang/lib/Parser/openmp-utils.cpp')
| -rw-r--r-- | flang/lib/Parser/openmp-utils.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp index 3201e5149e27..ab2ed0641f4c 100644 --- a/flang/lib/Parser/openmp-utils.cpp +++ b/flang/lib/Parser/openmp-utils.cpp @@ -15,6 +15,7 @@ #include "flang/Common/indirection.h" #include "flang/Common/template.h" #include "flang/Common/visit.h" +#include "flang/Parser/tools.h" #include <tuple> #include <type_traits> @@ -77,6 +78,44 @@ std::optional<Label> GetStatementLabel(const ExecutionPartConstruct &x) { return GetStatementLabelHelper(x); } +static std::optional<Label> GetFinalLabel(const Block &x) { + if (!x.empty()) { + const ExecutionPartConstruct &last{x.back()}; + if (auto *omp{Unwrap<OpenMPConstruct>(last)}) { + return GetFinalLabel(*omp); + } else if (auto *doLoop{Unwrap<DoConstruct>(last)}) { + return GetFinalLabel(std::get<Block>(doLoop->t)); + } else { + return GetStatementLabel(x.back()); + } + } else { + return std::nullopt; + } +} + +std::optional<Label> GetFinalLabel(const OpenMPConstruct &x) { + return common::visit( + [](auto &&s) -> std::optional<Label> { + using TypeS = llvm::remove_cvref_t<decltype(s)>; + if constexpr (std::is_same_v<TypeS, OpenMPSectionsConstruct>) { + auto &list{std::get<std::list<OpenMPConstruct>>(s.t)}; + if (!list.empty()) { + return GetFinalLabel(list.back()); + } else { + return std::nullopt; + } + } else if constexpr ( // + std::is_same_v<TypeS, OpenMPLoopConstruct> || + std::is_same_v<TypeS, OpenMPSectionConstruct> || + std::is_base_of_v<OmpBlockConstruct, TypeS>) { + return GetFinalLabel(std::get<Block>(s.t)); + } else { + return std::nullopt; + } + }, + x.u); +} + const OmpObjectList *GetOmpObjectList(const OmpClause &clause) { // Clauses with OmpObjectList as its data member using MemberObjectListClauses = std::tuple<OmpClause::Copyin, |
