FLANG
openmp-utils.h
1//===-- flang/Parser/openmp-utils.h ---------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Common OpenMP utilities.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef FORTRAN_PARSER_OPENMP_UTILS_H
14#define FORTRAN_PARSER_OPENMP_UTILS_H
15
16#include "flang/Common/indirection.h"
17#include "flang/Parser/parse-tree.h"
18#include "llvm/Frontend/OpenMP/OMP.h"
19
20#include <cassert>
21#include <tuple>
22#include <type_traits>
23#include <utility>
24#include <variant>
25#include <vector>
26
27namespace Fortran::parser::omp {
28
29template <typename T> constexpr auto addr_if(std::optional<T> &x) {
30 return x ? &*x : nullptr;
31}
32template <typename T> constexpr auto addr_if(const std::optional<T> &x) {
33 return x ? &*x : nullptr;
34}
35
36namespace detail {
38 static OmpDirectiveName MakeName(CharBlock source = {},
39 llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown) {
41 name.source = source;
42 name.v = id;
43 return name;
44 }
45
46 static OmpDirectiveName GetOmpDirectiveName(const OmpDirectiveName &x) {
47 return x;
48 }
49
50 static OmpDirectiveName GetOmpDirectiveName(const OmpBeginLoopDirective &x) {
51 return x.DirName();
52 }
53
54 static OmpDirectiveName GetOmpDirectiveName(const OpenMPSectionConstruct &x) {
55 if (auto &spec{std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
56 return spec->DirName();
57 } else {
58 return MakeName({}, llvm::omp::Directive::OMPD_section);
59 }
60 }
61
62 static OmpDirectiveName GetOmpDirectiveName(
64 return x.DirName();
65 }
66
67 template <typename T>
68 static OmpDirectiveName GetOmpDirectiveName(const T &x) {
69 if constexpr (WrapperTrait<T>) {
70 if constexpr (std::is_same_v<T, OpenMPCancelConstruct> ||
71 std::is_same_v<T, OpenMPCancellationPointConstruct> ||
72 std::is_same_v<T, OpenMPDepobjConstruct> ||
73 std::is_same_v<T, OpenMPFlushConstruct> ||
74 std::is_same_v<T, OpenMPInteropConstruct> ||
75 std::is_same_v<T, OpenMPSimpleStandaloneConstruct> ||
76 std::is_same_v<T, OpenMPGroupprivate>) {
77 return x.v.DirName();
78 } else {
79 return GetOmpDirectiveName(x.v);
80 }
81 } else if constexpr (TupleTrait<T>) {
82 if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
83 return std::get<OmpBeginDirective>(x.t).DirName();
84 } else {
85 return GetFromTuple(
86 x.t, std::make_index_sequence<std::tuple_size_v<decltype(x.t)>>{});
87 }
88 } else if constexpr (UnionTrait<T>) {
89 return common::visit(
90 [](auto &&s) { return GetOmpDirectiveName(s); }, x.u);
91 } else {
92 return MakeName();
93 }
94 }
95
96 template <typename... Ts, size_t... Is>
97 static OmpDirectiveName GetFromTuple(
98 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
99 OmpDirectiveName name = MakeName();
100 auto accumulate = [&](const OmpDirectiveName &n) {
101 if (name.v == llvm::omp::Directive::OMPD_unknown) {
102 name = n;
103 } else {
104 assert(
105 n.v == llvm::omp::Directive::OMPD_unknown && "Conflicting names");
106 }
107 };
108 (accumulate(GetOmpDirectiveName(std::get<Is>(t))), ...);
109 return name;
110 }
111
112 template <typename T>
113 static OmpDirectiveName GetOmpDirectiveName(const common::Indirection<T> &x) {
114 return GetOmpDirectiveName(x.value());
115 }
116};
117} // namespace detail
118
119template <typename T> OmpDirectiveName GetOmpDirectiveName(const T &x) {
120 return detail::DirectiveNameScope::GetOmpDirectiveName(x);
121}
122
124const OpenMPConstruct *GetOmp(const ExecutionPartConstruct &x);
125
126const OpenMPLoopConstruct *GetOmpLoop(const ExecutionPartConstruct &x);
127const DoConstruct *GetDoConstruct(const ExecutionPartConstruct &x);
128
129// Is the template argument "Statement<T>" for some T?
130template <typename T> struct IsStatement {
131 static constexpr bool value{false};
132};
133template <typename T> struct IsStatement<Statement<T>> {
134 static constexpr bool value{true};
135};
136
137std::optional<Label> GetStatementLabel(const ExecutionPartConstruct &x);
138std::optional<Label> GetFinalLabel(const OpenMPConstruct &x);
139
140const OmpObjectList *GetOmpObjectList(const OmpClause &clause);
141
142template <typename T>
143const T *GetFirstArgument(const OmpDirectiveSpecification &spec) {
144 for (const OmpArgument &arg : spec.Arguments().v) {
145 if (auto *t{std::get_if<T>(&arg.u)}) {
146 return t;
147 }
148 }
149 return nullptr;
150}
151
152const BlockConstruct *GetFortranBlockConstruct(
153 const ExecutionPartConstruct &epc);
154const Block &GetInnermostExecPart(const Block &block);
155bool IsStrictlyStructuredBlock(const Block &block);
156
157const OmpCombinerExpression *GetCombinerExpr(
158 const OmpReductionSpecifier &rspec);
159const OmpInitializerExpression *GetInitializerExpr(const OmpClause &init);
160
162 std::vector<const OmpAllocateDirective *> dirs;
163 const ExecutionPartConstruct *body{nullptr};
164};
165
166OmpAllocateInfo SplitOmpAllocate(const OmpAllocateDirective &x);
167
168} // namespace Fortran::parser::omp
169
170#endif // FORTRAN_PARSER_OPENMP_UTILS_H
Definition indirection.h:31
Definition char-block.h:28
Definition parse-tree.h:433
Definition parse-tree.h:2342
Definition parse-tree.h:548
Definition parse-tree.h:5200
Definition parse-tree.h:5337
Definition parse-tree.h:5065
Definition parse-tree.h:4949
Definition parse-tree.h:3504
Definition parse-tree.h:4972
Definition parse-tree.h:3549
Definition parse-tree.h:5372
Definition parse-tree.h:5346
Definition parse-tree.h:5079
Definition parse-tree.h:357
Definition parse-tree.h:3668
Definition openmp-utils.h:130
Definition openmp-utils.h:161