13#ifndef FORTRAN_PARSER_OPENMP_UTILS_H
14#define FORTRAN_PARSER_OPENMP_UTILS_H
16#include "flang/Common/indirection.h"
17#include "flang/Common/template.h"
18#include "flang/Parser/parse-tree.h"
19#include "llvm/ADT/iterator_range.h"
20#include "llvm/Frontend/OpenMP/OMP.h"
30namespace Fortran::parser::omp {
32template <
typename T>
constexpr auto addr_if(std::optional<T> &x) {
33 return x ? &*x :
nullptr;
35template <
typename T>
constexpr auto addr_if(
const std::optional<T> &x) {
36 return x ? &*x :
nullptr;
42 llvm::omp::Directive
id = llvm::omp::Directive::OMPD_unknown) {
58 if (
auto &spec{std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
59 return spec->DirName();
61 return MakeName({}, llvm::omp::Directive::OMPD_section);
72 if constexpr (WrapperTrait<T>) {
73 return GetOmpDirectiveName(x.v);
74 }
else if constexpr (TupleTrait<T>) {
75 if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
76 return std::get<OmpBeginDirective>(x.t).DirName();
79 x.t, std::make_index_sequence<std::tuple_size_v<
decltype(x.t)>>{});
81 }
else if constexpr (UnionTrait<T>) {
83 [](
auto &&s) {
return GetOmpDirectiveName(s); }, x.u);
89 template <
typename... Ts,
size_t... Is>
91 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
94 if (name.v == llvm::omp::Directive::OMPD_unknown) {
98 n.v == llvm::omp::Directive::OMPD_unknown &&
"Conflicting names");
101 (accumulate(GetOmpDirectiveName(std::get<Is>(t))), ...);
105 template <
typename T>
107 return GetOmpDirectiveName(x.value());
113 return detail::DirectiveNameScope::GetOmpDirectiveName(x);
116std::string GetUpperName(llvm::omp::Clause
id,
unsigned version);
117std::string GetUpperName(llvm::omp::Directive
id,
unsigned version);
127using MemberObjectListClauses =
128 std::tuple<OmpClause::Copyin, OmpClause::Copyprivate, OmpClause::Exclusive,
129 OmpClause::Firstprivate, OmpClause::HasDeviceAddr, OmpClause::Inclusive,
130 OmpClause::IsDevicePtr, OmpClause::Link, OmpClause::Private,
131 OmpClause::Shared, OmpClause::UseDeviceAddr, OmpClause::UseDevicePtr>;
135using TupleObjectListClauses = std::tuple<OmpClause::AdjustArgs,
136 OmpClause::Affinity, OmpClause::Aligned, OmpClause::Allocate,
137 OmpClause::Enter, OmpClause::From, OmpClause::InReduction,
138 OmpClause::Lastprivate, OmpClause::Linear, OmpClause::Map,
139 OmpClause::Reduction, OmpClause::TaskReduction, OmpClause::To>;
144 static constexpr bool value{
false};
148 static constexpr bool value{std::is_same_v<T,
decltype(U::v)>};
156 static constexpr bool value{
false};
159template <
typename T,
typename U,
typename... Us>
168 static constexpr bool value{
false};
170template <
typename T,
typename... Us>
174template <
typename T,
typename... Us>
178template <
typename T,
typename U>
179constexpr bool WrappedInTupleOrVariantV{WrappedInTupleOrVariant<T, U>::value};
182template <
typename T>
const OmpObjectList *GetOmpObjectList(
const T &clause) {
183 using namespace detail;
184 static_assert(std::is_class_v<T>,
"Unexpected argument type");
186 if constexpr (common::HasMember<T,
decltype(OmpClause::u)>) {
187 if constexpr (common::HasMember<T, MemberObjectListClauses>) {
189 }
else if constexpr (common::HasMember<T, TupleObjectListClauses>) {
190 return &std::get<OmpObjectList>(clause.v.t);
194 }
else if constexpr (WrappedInTupleOrVariantV<T, TupleObjectListClauses>) {
195 return &std::get<OmpObjectList>(clause.t);
196 }
else if constexpr (WrappedInTupleOrVariantV<T,
decltype(OmpClause::u)>) {
200 static_assert(
sizeof(T) < 0 &&
"Unexpected argument type");
204const OmpObjectList *GetOmpObjectList(
const OmpClause &clause);
205const OmpObjectList *GetOmpObjectList(
const OmpClause::Depend &clause);
206const OmpObjectList *GetOmpObjectList(
const OmpDependClause::TaskDep &x);
209const T *GetFirstArgument(
const OmpDirectiveSpecification &spec) {
210 for (
const OmpArgument &arg : spec.Arguments().v) {
211 if (
auto *t{std::get_if<T>(&arg.u)}) {
218const OmpClause *FindClause(
219 const OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId);
221const BlockConstruct *GetFortranBlockConstruct(
222 const ExecutionPartConstruct &epc);
223const Block &GetInnermostExecPart(
const Block &block);
224bool IsStrictlyStructuredBlock(
const Block &block);
226const OmpCombinerExpression *GetCombinerExpr(
const OmpReductionSpecifier &x);
227const OmpCombinerExpression *GetCombinerExpr(
const OmpClause &x);
228const OmpInitializerExpression *GetInitializerExpr(
const OmpClause &x);
231 std::vector<const OmpAllocateDirective *> dirs;
237template <
typename R,
typename =
void,
typename =
void>
struct is_range {
238 static constexpr bool value{
false};
243 std::void_t<decltype(std::declval<R>().begin())>,
244 std::void_t<decltype(std::declval<R>().end())>> {
245 static constexpr bool value{
true};
248template <
typename R>
constexpr bool is_range_v = is_range<R>::value;
278struct ExecutionPartIterator {
285 using IteratorType = Block::const_iterator;
286 using IteratorRange = llvm::iterator_range<IteratorType>;
290 struct IteratorGauge :
public IteratorRange {
291 IteratorGauge(IteratorType b, IteratorType e)
292 : IteratorRange(b, e), at(b) {}
293 IteratorGauge(IteratorRange r) : IteratorRange(r), at(r.begin()) {}
295 bool atEnd()
const {
return at == end(); }
301 : location(b, e), owner(c) {}
302 template <
typename R>
304 : location(r), owner(c) {}
305 Construct(
const Construct &c) =
default;
313 ExecutionPartIterator() =
default;
315 ExecutionPartIterator(IteratorType b, IteratorType e, Step s = Step::Default,
318 stack_.emplace_back(b, e, c);
321 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
336 bool valid()
const {
return !stack_.empty(); }
338 const std::vector<Construct> &stack()
const {
return stack_; }
339 decltype(
auto)
operator*()
const {
return *at(); }
340 bool operator==(
const ExecutionPartIterator &other)
const {
341 if (valid() != other.valid()) {
346 stack_.back().location.at == other.stack_.back().location.at;
348 bool operator!=(
const ExecutionPartIterator &other)
const {
349 return !(*
this == other);
352 ExecutionPartIterator &operator++() {
353 if (stepping_ == Step::Into) {
356 assert(stepping_ == Step::Over &&
"Unexpected stepping");
362 ExecutionPartIterator operator++(
int) {
363 ExecutionPartIterator copy{*
this};
368 using difference_type = IteratorType::difference_type;
369 using value_type = IteratorType::value_type;
370 using reference = IteratorType::reference;
371 using pointer = IteratorType::pointer;
372 using iterator_category = std::forward_iterator_tag;
375 IteratorType at()
const {
return stack_.back().location.at; };
381 const Step stepping_ = Step::Default;
382 std::vector<Construct> stack_;
385template <
typename Iterator = ExecutionPartIterator>
struct ExecutionPartRange {
386 using Step =
typename Iterator::Step;
388 ExecutionPartRange(Block::const_iterator begin, Block::const_iterator end,
389 Step stepping = Step::Default,
391 : begin_(begin, end, stepping, owner), end_() {}
392 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
393 ExecutionPartRange(
const R &range, Step stepping = Step::Default,
395 : ExecutionPartRange(range.begin(), range.end(), stepping, owner) {}
397 Iterator begin()
const {
return begin_; }
398 Iterator end()
const {
return end_; }
401 Iterator begin_, end_;
404struct LoopNestIterator :
public ExecutionPartIterator {
405 LoopNestIterator() =
default;
407 LoopNestIterator(IteratorType b, IteratorType e, Step s = Step::Default,
409 : ExecutionPartIterator(b, e, s, c) {
412 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
413 LoopNestIterator(
const R &range, Step stepping = Step::Default,
415 : LoopNestIterator(range.begin(), range.end(), stepping, construct) {}
417 LoopNestIterator &operator++() {
418 ExecutionPartIterator::operator++();
423 LoopNestIterator operator++(
int) {
424 LoopNestIterator copy{*
this};
433 while (valid() && !isLoop(**
this)) {
434 ExecutionPartIterator::operator++();
Definition indirection.h:31
Definition char-block.h:28
Definition parse-tree.h:437
Definition parse-tree.h:2311
Definition parse-tree.h:554
Definition parse-tree.h:5266
Definition parse-tree.h:5403
Definition parse-tree.h:5131
Definition parse-tree.h:3480
Definition parse-tree.h:3525
Definition parse-tree.h:5438
Definition parse-tree.h:5270
Definition parse-tree.h:5412
Definition parse-tree.h:5145
Definition openmp-utils.h:290
Definition openmp-utils.h:278
Definition openmp-utils.h:385
Definition openmp-utils.h:230
Definition openmp-utils.h:40
Definition openmp-utils.h:167
Definition openmp-utils.h:143
Definition openmp-utils.h:153
Definition openmp-utils.h:237