13#ifndef FORTRAN_SEMANTICS_OPENMP_UTILS_H
14#define FORTRAN_SEMANTICS_OPENMP_UTILS_H
16#include "flang/Common/indirection.h"
17#include "flang/Evaluate/type.h"
18#include "flang/Parser/char-block.h"
19#include "flang/Parser/message.h"
20#include "flang/Parser/openmp-utils.h"
21#include "flang/Parser/parse-tree.h"
22#include "flang/Parser/tools.h"
23#include "flang/Semantics/tools.h"
25#include "llvm/ADT/ArrayRef.h"
35namespace Fortran::semantics {
42using Fortran::parser::omp::BlockRange;
43using Fortran::parser::omp::ExecutionPartIterator;
44using Fortran::parser::omp::is_range_v;
45using Fortran::parser::omp::LoopNestIterator;
46using Fortran::parser::omp::LoopRange;
48template <
typename T,
typename U = std::remove_const_t<T>> U AsRvalue(T &t) {
52template <
typename T> T &&AsRvalue(T &&t) {
return std::move(t); }
54const Scope &GetScopingUnit(
const Scope &scope);
55const Scope &GetProgramUnit(
const Scope &scope);
57template <
typename T>
struct WithSource {
59 typename U = std::remove_reference_t<T>,
60 typename = std::enable_if_t<std::is_default_constructible_v<U>>>
61 WithSource() : value(), source() {}
62 WithSource(
const WithSource<T> &) =
default;
63 WithSource(WithSource<T> &&) =
default;
66 WithSource &operator=(
const WithSource<T> &) =
default;
67 WithSource &operator=(WithSource<T> &&) =
default;
78 using WithSource<value_type>::WithSource;
79 value_type stmt()
const {
return value; }
80 operator bool()
const {
return stmt() !=
nullptr; }
86std::string ThisVersion(
unsigned version);
87std::string TryVersion(
unsigned version);
92bool IsCommonBlock(
const Symbol &sym);
93bool IsExtendedListItem(
const Symbol &sym);
94bool IsVariableListItem(
const Symbol &sym);
95bool IsTypeParamInquiry(
const Symbol &sym);
96bool IsStructureComponent(
const Symbol &sym);
97bool IsPrivatizable(
const Symbol &sym);
98bool IsVarOrFunctionRef(
const MaybeExpr &expr);
104bool IsMapEnteringType(parser::OmpMapType::Value type);
105bool IsMapExitingType(parser::OmpMapType::Value type);
107MaybeExpr GetEvaluateExpr(
const parser::Expr &parserExpr);
108template <
typename T> MaybeExpr GetEvaluateExpr(
const T &inp) {
109 return GetEvaluateExpr(parser::UnwrapRef<parser::Expr>(inp));
112std::optional<evaluate::DynamicType> GetDynamicType(
115std::optional<bool> GetLogicalValue(
const SomeExpr &expr);
116std::optional<int64_t> GetIntValueFromExpr(
120std::optional<int64_t> GetIntValueFromExpr(
122 if (
auto *parserExpr{parser::Unwrap<parser::Expr>(wrappedExpr)}) {
123 return GetIntValueFromExpr(*parserExpr, semaCtx);
128std::optional<bool> IsContiguous(
129 SemanticsContext &semaCtx,
const parser::OmpObject &
object);
131std::vector<SomeExpr> GetTopLevelDesignators(
const SomeExpr &expr);
132const SomeExpr *HasStorageOverlap(
133 const SomeExpr &base, llvm::ArrayRef<SomeExpr> exprs);
135bool IsAssignment(
const parser::ActionStmt *x);
136bool IsPointerAssignment(
const evaluate::Assignment &x);
138MaybeExpr MakeEvaluateExpr(
const parser::OmpStylizedInstance &inp);
140bool IsLoopTransforming(llvm::omp::Directive dir);
141bool IsFullUnroll(
const parser::OmpDirectiveSpecification &spec);
143inline bool IsDoConcurrentLegal(
unsigned version) {
146 return version >= 60;
150 LoopControl(LoopControl &&x) =
default;
151 LoopControl(
const LoopControl &x) =
default;
152 LoopControl(
const parser::LoopControl::Bounds &x);
167 Reason(Reason &&) =
default;
168 Reason(
const Reason &);
169 Reason &operator=(Reason &&) =
default;
170 Reason &operator=(
const Reason &);
174 template <
typename... Ts> Reason &Say(Ts &&...args) {
175 msgs.Say(std::forward<Ts>(args)...);
179 Reason &Append(
const Reason &other) {
183 operator bool()
const {
return !msgs.empty(); }
186 void CopyFrom(
const Reason &other);
191template <
typename T>
struct WithReason {
192 std::optional<T> value;
195 WithReason() =
default;
196 WithReason(std::optional<T> v,
const Reason &r =
Reason())
197 : value(v), reason(r) {}
198 operator bool()
const {
return value.has_value(); }
213std::pair<WithReason<int64_t>,
bool> GetAffectedNestDepthWithReason(
218std::pair<WithReason<int64_t>,
bool> GetGeneratedNestDepthWithReason(
235std::optional<int64_t> GetMinimumSequenceCount(
236 std::optional<int64_t> first, std::optional<int64_t> count);
237std::optional<int64_t> GetMinimumSequenceCount(
238 std::optional<std::pair<int64_t, int64_t>> range);
245std::optional<std::vector<const parser::DoConstruct *>> CollectAffectedDoLoops(
253 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
254 LoopSequence(
const R &range,
unsigned version,
bool allowAllLoops =
false,
256 : version_(version), allowAllLoops_(allowAllLoops), semaCtx_(semaCtx) {
257 entry_ = std::make_unique<Construct>(range,
nullptr);
258 createChildrenFromRange(entry_->location);
271 bool isNest()
const {
return length_.value == 1; }
274 const Depth &depth()
const {
return depth_; }
275 const std::vector<LoopSequence> &children()
const {
return children_; }
276 const parser::ExecutionPartConstruct *owner()
const {
return entry_->owner; }
278 WithReason<bool> isWellFormedSequence()
const;
279 WithReason<bool> isWellFormedNest()
const;
285 std::vector<LoopControl> getLoopControls()
const;
288 WithReason<bool> isRectangular(
289 const std::vector<const LoopSequence *> &outer)
const;
292 using Construct = ExecutionPartIterator::Construct;
294 LoopSequence(std::unique_ptr<Construct> entry,
unsigned version,
295 bool allowAllLoops, SemanticsContext *semaCtx =
nullptr);
297 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
298 void createChildrenFromRange(
const R &range) {
299 createChildrenFromRange(range.begin(), range.end());
302 std::unique_ptr<Construct> createConstructEntry(
303 const parser::ExecutionPartConstruct &code);
305 void createChildrenFromRange(
306 ExecutionPartIterator::IteratorType begin,
307 ExecutionPartIterator::IteratorType end);
312 WithReason<int64_t> calculateLength()
const;
313 WithReason<int64_t> getNestedLength()
const;
314 Depth calculateDepths()
const;
315 Depth getNestedDepths()
const;
316 WithReason<int64_t> calculateHeight()
const;
321 const parser::ExecutionPartConstruct *invalidIC_{
nullptr};
325 const parser::ExecutionPartConstruct *opaqueIC_{
nullptr};
331 WithReason<int64_t> length_;
340 WithReason<int64_t> height_;
345 std::unique_ptr<Construct> entry_;
346 std::vector<LoopSequence> children_;
347 SemanticsContext *semaCtx_{
nullptr};
Definition char-block.h:28
Definition semantics.h:67
Definition parse-tree.h:2238
Definition parse-tree.h:2325
Definition parse-tree.h:556
Definition parse-tree.h:1695
Definition parse-tree.h:589
Definition parse-tree.h:5085
Definition parse-tree.h:3562
Definition parse-tree.h:5459
Definition parse-tree.h:3693
Definition openmp-utils.h:262
const LoopSequence * getNestedDoConcurrent() const
Definition openmp-utils.cpp:1388
A representation of a "because" message.
Definition openmp-utils.h:165
Definition openmp-utils.h:77
Definition openmp-utils.h:191
Definition openmp-utils.h:57