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);
127 static constexpr bool value{
false};
130 static constexpr bool value{
true};
138using MemberObjectListClauses =
139 std::tuple<OmpClause::Copyin, OmpClause::Copyprivate, OmpClause::Exclusive,
140 OmpClause::Firstprivate, OmpClause::HasDeviceAddr, OmpClause::Inclusive,
141 OmpClause::IsDevicePtr, OmpClause::Link, OmpClause::Private,
142 OmpClause::Shared, OmpClause::UseDeviceAddr, OmpClause::UseDevicePtr>;
146using TupleObjectListClauses = std::tuple<OmpClause::AdjustArgs,
147 OmpClause::Affinity, OmpClause::Aligned, OmpClause::Allocate,
148 OmpClause::Enter, OmpClause::From, OmpClause::InReduction,
149 OmpClause::Lastprivate, OmpClause::Linear, OmpClause::Map,
150 OmpClause::Reduction, OmpClause::TaskReduction, OmpClause::To>;
155 static constexpr bool value{
false};
159 static constexpr bool value{std::is_same_v<T,
decltype(U::v)>};
167 static constexpr bool value{
false};
170template <
typename T,
typename U,
typename... Us>
179 static constexpr bool value{
false};
181template <
typename T,
typename... Us>
185template <
typename T,
typename... Us>
189template <
typename T,
typename U>
190constexpr bool WrappedInTupleOrVariantV{WrappedInTupleOrVariant<T, U>::value};
193template <
typename T>
const OmpObjectList *GetOmpObjectList(
const T &clause) {
194 using namespace detail;
195 static_assert(std::is_class_v<T>,
"Unexpected argument type");
197 if constexpr (common::HasMember<T,
decltype(OmpClause::u)>) {
198 if constexpr (common::HasMember<T, MemberObjectListClauses>) {
200 }
else if constexpr (common::HasMember<T, TupleObjectListClauses>) {
201 return &std::get<OmpObjectList>(clause.v.t);
205 }
else if constexpr (WrappedInTupleOrVariantV<T, TupleObjectListClauses>) {
206 return &std::get<OmpObjectList>(clause.t);
207 }
else if constexpr (WrappedInTupleOrVariantV<T,
decltype(OmpClause::u)>) {
211 static_assert(
sizeof(T) < 0 &&
"Unexpected argument type");
215const OmpObjectList *GetOmpObjectList(
const OmpClause &clause);
216const OmpObjectList *GetOmpObjectList(
const OmpClause::Depend &clause);
217const OmpObjectList *GetOmpObjectList(
const OmpDependClause::TaskDep &x);
220const T *GetFirstArgument(
const OmpDirectiveSpecification &spec) {
221 for (
const OmpArgument &arg : spec.Arguments().v) {
222 if (
auto *t{std::get_if<T>(&arg.u)}) {
229const OmpClause *FindClause(
230 const OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId);
232const BlockConstruct *GetFortranBlockConstruct(
233 const ExecutionPartConstruct &epc);
234const Block &GetInnermostExecPart(
const Block &block);
235bool IsStrictlyStructuredBlock(
const Block &block);
237const OmpCombinerExpression *GetCombinerExpr(
const OmpReductionSpecifier &x);
238const OmpCombinerExpression *GetCombinerExpr(
const OmpClause &x);
239const OmpInitializerExpression *GetInitializerExpr(
const OmpClause &x);
242 std::vector<const OmpAllocateDirective *> dirs;
248template <
typename R,
typename =
void,
typename =
void>
struct is_range {
249 static constexpr bool value{
false};
254 std::void_t<decltype(std::declval<R>().begin())>,
255 std::void_t<decltype(std::declval<R>().end())>> {
256 static constexpr bool value{
true};
259template <
typename R>
constexpr bool is_range_v = is_range<R>::value;
289struct ExecutionPartIterator {
296 using IteratorType = Block::const_iterator;
297 using IteratorRange = llvm::iterator_range<IteratorType>;
301 struct IteratorGauge :
public IteratorRange {
302 IteratorGauge(IteratorType b, IteratorType e)
303 : IteratorRange(b, e), at(b) {}
304 IteratorGauge(IteratorRange r) : IteratorRange(r), at(r.begin()) {}
306 bool atEnd()
const {
return at == end(); }
312 : location(b, e), owner(c) {}
313 template <
typename R>
315 : location(r), owner(c) {}
316 Construct(
const Construct &c) =
default;
324 ExecutionPartIterator() =
default;
326 ExecutionPartIterator(IteratorType b, IteratorType e, Step s = Step::Default,
329 stack_.emplace_back(b, e, c);
332 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
347 bool valid()
const {
return !stack_.empty(); }
349 const std::vector<Construct> &stack()
const {
return stack_; }
350 decltype(
auto)
operator*()
const {
return *at(); }
351 bool operator==(
const ExecutionPartIterator &other)
const {
352 if (valid() != other.valid()) {
357 stack_.back().location.at == other.stack_.back().location.at;
359 bool operator!=(
const ExecutionPartIterator &other)
const {
360 return !(*
this == other);
363 ExecutionPartIterator &operator++() {
364 if (stepping_ == Step::Into) {
367 assert(stepping_ == Step::Over &&
"Unexpected stepping");
373 ExecutionPartIterator operator++(
int) {
374 ExecutionPartIterator copy{*
this};
379 using difference_type = IteratorType::difference_type;
380 using value_type = IteratorType::value_type;
381 using reference = IteratorType::reference;
382 using pointer = IteratorType::pointer;
383 using iterator_category = std::forward_iterator_tag;
386 IteratorType at()
const {
return stack_.back().location.at; };
392 const Step stepping_ = Step::Default;
393 std::vector<Construct> stack_;
396template <
typename Iterator = ExecutionPartIterator>
struct ExecutionPartRange {
397 using Step =
typename Iterator::Step;
399 ExecutionPartRange(Block::const_iterator begin, Block::const_iterator end,
400 Step stepping = Step::Default,
402 : begin_(begin, end, stepping, owner), end_() {}
403 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
404 ExecutionPartRange(
const R &range, Step stepping = Step::Default,
406 : ExecutionPartRange(range.begin(), range.end(), stepping, owner) {}
408 Iterator begin()
const {
return begin_; }
409 Iterator end()
const {
return end_; }
412 Iterator begin_, end_;
415struct LoopNestIterator :
public ExecutionPartIterator {
416 LoopNestIterator() =
default;
418 LoopNestIterator(IteratorType b, IteratorType e, Step s = Step::Default,
420 : ExecutionPartIterator(b, e, s, c) {
423 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
424 LoopNestIterator(
const R &range, Step stepping = Step::Default,
426 : LoopNestIterator(range.begin(), range.end(), stepping, construct) {}
428 LoopNestIterator &operator++() {
429 ExecutionPartIterator::operator++();
434 LoopNestIterator operator++(
int) {
435 LoopNestIterator copy{*
this};
444 while (valid() && !isLoop(**
this)) {
445 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:5260
Definition parse-tree.h:5397
Definition parse-tree.h:5125
Definition parse-tree.h:3474
Definition parse-tree.h:3519
Definition parse-tree.h:5432
Definition parse-tree.h:5264
Definition parse-tree.h:5406
Definition parse-tree.h:5139
Definition parse-tree.h:359
Definition openmp-utils.h:301
Definition openmp-utils.h:289
Definition openmp-utils.h:396
Definition openmp-utils.h:126
Definition openmp-utils.h:241
Definition openmp-utils.h:40
Definition openmp-utils.h:178
Definition openmp-utils.h:154
Definition openmp-utils.h:164
Definition openmp-utils.h:248