aboutsummaryrefslogtreecommitdiff
path: root/clang/include/clang/AST/StmtOpenMP.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include/clang/AST/StmtOpenMP.h')
-rw-r--r--clang/include/clang/AST/StmtOpenMP.h1090
1 files changed, 866 insertions, 224 deletions
diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index b7bbf15949a0..9c85df741f48 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -28,6 +28,238 @@ namespace clang {
// AST classes for directives.
//===----------------------------------------------------------------------===//
+/// Representation of an OpenMP canonical loop.
+///
+/// OpenMP 1.0 C/C++, section 2.4.1 for Construct; canonical-shape
+/// OpenMP 2.0 C/C++, section 2.4.1 for Construct; canonical-shape
+/// OpenMP 2.5, section 2.5.1 Loop Construct; canonical form
+/// OpenMP 3.1, section 2.5.1 Loop Construct; canonical form
+/// OpenMP 4.0, section 2.6 Canonical Loop Form
+/// OpenMP 4.5, section 2.6 Canonical Loop Form
+/// OpenMP 5.0, section 2.9.1 Canonical Loop Form
+/// OpenMP 5.1, section 2.11.1 Canonical Loop Nest Form
+///
+/// An OpenMP canonical loop is a for-statement or range-based for-statement
+/// with additional requirements that ensure that the number of iterations is
+/// known before entering the loop and allow skipping to an arbitrary iteration.
+/// The OMPCanonicalLoop AST node wraps a ForStmt or CXXForRangeStmt that is
+/// known to fulfill OpenMP's canonical loop requirements because of being
+/// associated to an OMPLoopBasedDirective. That is, the general structure is:
+///
+/// OMPLoopBasedDirective
+/// [`- CapturedStmt ]
+/// [ `- CapturedDecl]
+/// ` OMPCanonicalLoop
+/// `- ForStmt/CXXForRangeStmt
+/// `- Stmt
+///
+/// One or multiple CapturedStmt/CapturedDecl pairs may be inserted by some
+/// directives such as OMPParallelForDirective, but others do not need them
+/// (such as OMPTileDirective). In The OMPCanonicalLoop and
+/// ForStmt/CXXForRangeStmt pair is repeated for loop associated with the
+/// directive. A OMPCanonicalLoop must not appear in the AST unless associated
+/// with a OMPLoopBasedDirective. In an imperfectly nested loop nest, the
+/// OMPCanonicalLoop may also be wrapped in a CompoundStmt:
+///
+/// [...]
+/// ` OMPCanonicalLoop
+/// `- ForStmt/CXXForRangeStmt
+/// `- CompoundStmt
+/// |- Leading in-between code (if any)
+/// |- OMPCanonicalLoop
+/// | `- ForStmt/CXXForRangeStmt
+/// | `- ...
+/// `- Trailing in-between code (if any)
+///
+/// The leading/trailing in-between code must not itself be a OMPCanonicalLoop
+/// to avoid confusion which loop belongs to the nesting.
+///
+/// There are three different kinds of iteration variables for different
+/// purposes:
+/// * Loop user variable: The user-accessible variable with different value for
+/// each iteration.
+/// * Loop iteration variable: The variable used to identify a loop iteration;
+/// for range-based for-statement, this is the hidden iterator '__begin'. For
+/// other loops, it is identical to the loop user variable. Must be a
+/// random-access iterator, pointer or integer type.
+/// * Logical iteration counter: Normalized loop counter starting at 0 and
+/// incrementing by one at each iteration. Allows abstracting over the type
+/// of the loop iteration variable and is always an unsigned integer type
+/// appropriate to represent the range of the loop iteration variable. Its
+/// value corresponds to the logical iteration number in the OpenMP
+/// specification.
+///
+/// This AST node provides two captured statements:
+/// * The distance function which computes the number of iterations.
+/// * The loop user variable function that computes the loop user variable when
+/// given a logical iteration number.
+///
+/// These captured statements provide the link between C/C++ semantics and the
+/// logical iteration counters used by the OpenMPIRBuilder which is
+/// language-agnostic and therefore does not know e.g. how to advance a
+/// random-access iterator. The OpenMPIRBuilder will use this information to
+/// apply simd, workshare-loop, distribute, taskloop and loop directives to the
+/// loop. For compatibility with the non-OpenMPIRBuilder codegen path, an
+/// OMPCanonicalLoop can itself also be wrapped into the CapturedStmts of an
+/// OMPLoopDirective and skipped when searching for the associated syntactical
+/// loop.
+///
+/// Example:
+/// <code>
+/// std::vector<std::string> Container{1,2,3};
+/// for (std::string Str : Container)
+/// Body(Str);
+/// </code>
+/// which is syntactic sugar for approximately:
+/// <code>
+/// auto &&__range = Container;
+/// auto __begin = std::begin(__range);
+/// auto __end = std::end(__range);
+/// for (; __begin != __end; ++__begin) {
+/// std::String Str = *__begin;
+/// Body(Str);
+/// }
+/// </code>
+/// In this example, the loop user variable is `Str`, the loop iteration
+/// variable is `__begin` of type `std::vector<std::string>::iterator` and the
+/// logical iteration number type is `size_t` (unsigned version of
+/// `std::vector<std::string>::iterator::difference_type` aka `ptrdiff_t`).
+/// Therefore, the distance function will be
+/// <code>
+/// [&](size_t &Result) { Result = __end - __begin; }
+/// </code>
+/// and the loop variable function is
+/// <code>
+/// [&,__begin](std::vector<std::string>::iterator &Result, size_t Logical) {
+/// Result = __begin + Logical;
+/// }
+/// </code>
+/// The variable `__begin`, aka the loop iteration variable, is captured by
+/// value because it is modified in the loop body, but both functions require
+/// the initial value. The OpenMP specification explicitly leaves unspecified
+/// when the loop expressions are evaluated such that a capture by reference is
+/// sufficient.
+class OMPCanonicalLoop : public Stmt {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+ /// Children of this AST node.
+ enum {
+ LOOP_STMT,
+ DISTANCE_FUNC,
+ LOOPVAR_FUNC,
+ LOOPVAR_REF,
+ LastSubStmt = LOOPVAR_REF
+ };
+
+private:
+ /// This AST node's children.
+ Stmt *SubStmts[LastSubStmt + 1] = {};
+
+ OMPCanonicalLoop() : Stmt(StmtClass::OMPCanonicalLoopClass) {}
+
+public:
+ /// Create a new OMPCanonicalLoop.
+ static OMPCanonicalLoop *create(const ASTContext &Ctx, Stmt *LoopStmt,
+ CapturedStmt *DistanceFunc,
+ CapturedStmt *LoopVarFunc,
+ DeclRefExpr *LoopVarRef) {
+ OMPCanonicalLoop *S = new (Ctx) OMPCanonicalLoop();
+ S->setLoopStmt(LoopStmt);
+ S->setDistanceFunc(DistanceFunc);
+ S->setLoopVarFunc(LoopVarFunc);
+ S->setLoopVarRef(LoopVarRef);
+ return S;
+ }
+
+ /// Create an empty OMPCanonicalLoop for deserialization.
+ static OMPCanonicalLoop *createEmpty(const ASTContext &Ctx) {
+ return new (Ctx) OMPCanonicalLoop();
+ }
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() == StmtClass::OMPCanonicalLoopClass;
+ }
+
+ SourceLocation getBeginLoc() const { return getLoopStmt()->getBeginLoc(); }
+ SourceLocation getEndLoc() const { return getLoopStmt()->getEndLoc(); }
+
+ /// Return this AST node's children.
+ /// @{
+ child_range children() {
+ return child_range(&SubStmts[0], &SubStmts[0] + LastSubStmt + 1);
+ }
+ const_child_range children() const {
+ return const_child_range(&SubStmts[0], &SubStmts[0] + LastSubStmt + 1);
+ }
+ /// @}
+
+ /// The wrapped syntactic loop statement (ForStmt or CXXForRangeStmt).
+ /// @{
+ Stmt *getLoopStmt() { return SubStmts[LOOP_STMT]; }
+ const Stmt *getLoopStmt() const { return SubStmts[LOOP_STMT]; }
+ void setLoopStmt(Stmt *S) {
+ assert((isa<ForStmt>(S) || isa<CXXForRangeStmt>(S)) &&
+ "Canonical loop must be a for loop (range-based or otherwise)");
+ SubStmts[LOOP_STMT] = S;
+ }
+ /// @}
+
+ /// The function that computes the number of loop iterations. Can be evaluated
+ /// before entering the loop but after the syntactical loop's init
+ /// statement(s).
+ ///
+ /// Function signature: void(LogicalTy &Result)
+ /// Any values necessary to compute the distance are captures of the closure.
+ /// @{
+ CapturedStmt *getDistanceFunc() {
+ return cast<CapturedStmt>(SubStmts[DISTANCE_FUNC]);
+ }
+ const CapturedStmt *getDistanceFunc() const {
+ return cast<CapturedStmt>(SubStmts[DISTANCE_FUNC]);
+ }
+ void setDistanceFunc(CapturedStmt *S) {
+ assert(S && "Expected non-null captured statement");
+ SubStmts[DISTANCE_FUNC] = S;
+ }
+ /// @}
+
+ /// The function that computes the loop user variable from a logical iteration
+ /// counter. Can be evaluated as first statement in the loop.
+ ///
+ /// Function signature: void(LoopVarTy &Result, LogicalTy Number)
+ /// Any other values required to compute the loop user variable (such as start
+ /// value, step size) are captured by the closure. In particular, the initial
+ /// value of loop iteration variable is captured by value to be unaffected by
+ /// previous iterations.
+ /// @{
+ CapturedStmt *getLoopVarFunc() {
+ return cast<CapturedStmt>(SubStmts[LOOPVAR_FUNC]);
+ }
+ const CapturedStmt *getLoopVarFunc() const {
+ return cast<CapturedStmt>(SubStmts[LOOPVAR_FUNC]);
+ }
+ void setLoopVarFunc(CapturedStmt *S) {
+ assert(S && "Expected non-null captured statement");
+ SubStmts[LOOPVAR_FUNC] = S;
+ }
+ /// @}
+
+ /// Reference to the loop user variable as accessed in the loop body.
+ /// @{
+ DeclRefExpr *getLoopVarRef() {
+ return cast<DeclRefExpr>(SubStmts[LOOPVAR_REF]);
+ }
+ const DeclRefExpr *getLoopVarRef() const {
+ return cast<DeclRefExpr>(SubStmts[LOOPVAR_REF]);
+ }
+ void setLoopVarRef(DeclRefExpr *E) {
+ assert(E && "Expected non-null loop variable");
+ SubStmts[LOOPVAR_REF] = E;
+ }
+ /// @}
+};
+
/// This is a basic class for representing single OpenMP executable
/// directive.
///
@@ -228,17 +460,22 @@ public:
/// directive). Returns nullptr if no clause of this kind is associated with
/// the directive.
template <typename SpecificClause>
- const SpecificClause *getSingleClause() const {
- auto Clauses = getClausesOfKind<SpecificClause>();
+ static const SpecificClause *getSingleClause(ArrayRef<OMPClause *> Clauses) {
+ auto ClausesOfKind = getClausesOfKind<SpecificClause>(Clauses);
- if (Clauses.begin() != Clauses.end()) {
- assert(std::next(Clauses.begin()) == Clauses.end() &&
+ if (ClausesOfKind.begin() != ClausesOfKind.end()) {
+ assert(std::next(ClausesOfKind.begin()) == ClausesOfKind.end() &&
"There are at least 2 clauses of the specified kind");
- return *Clauses.begin();
+ return *ClausesOfKind.begin();
}
return nullptr;
}
+ template <typename SpecificClause>
+ const SpecificClause *getSingleClause() const {
+ return getSingleClause<SpecificClause>(clauses());
+ }
+
/// Returns true if the current directive has one or more clauses of a
/// specific kind.
template <typename SpecificClause>
@@ -440,13 +677,288 @@ public:
}
};
+/// The base class for all loop-based directives, including loop transformation
+/// directives.
+class OMPLoopBasedDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+
+protected:
+ /// Number of collapsed loops as specified by 'collapse' clause.
+ unsigned NumAssociatedLoops = 0;
+
+ /// Build instance of loop directive of class \a Kind.
+ ///
+ /// \param SC Statement class.
+ /// \param Kind Kind of OpenMP directive.
+ /// \param StartLoc Starting location of the directive (directive keyword).
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumAssociatedLoops Number of loops associated with the construct.
+ ///
+ OMPLoopBasedDirective(StmtClass SC, OpenMPDirectiveKind Kind,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumAssociatedLoops)
+ : OMPExecutableDirective(SC, Kind, StartLoc, EndLoc),
+ NumAssociatedLoops(NumAssociatedLoops) {}
+
+public:
+ /// The expressions built to support OpenMP loops in combined/composite
+ /// pragmas (e.g. pragma omp distribute parallel for)
+ struct DistCombinedHelperExprs {
+ /// DistributeLowerBound - used when composing 'omp distribute' with
+ /// 'omp for' in a same construct.
+ Expr *LB;
+ /// DistributeUpperBound - used when composing 'omp distribute' with
+ /// 'omp for' in a same construct.
+ Expr *UB;
+ /// DistributeEnsureUpperBound - used when composing 'omp distribute'
+ /// with 'omp for' in a same construct, EUB depends on DistUB
+ Expr *EUB;
+ /// Distribute loop iteration variable init used when composing 'omp
+ /// distribute'
+ /// with 'omp for' in a same construct
+ Expr *Init;
+ /// Distribute Loop condition used when composing 'omp distribute'
+ /// with 'omp for' in a same construct
+ Expr *Cond;
+ /// Update of LowerBound for statically scheduled omp loops for
+ /// outer loop in combined constructs (e.g. 'distribute parallel for')
+ Expr *NLB;
+ /// Update of UpperBound for statically scheduled omp loops for
+ /// outer loop in combined constructs (e.g. 'distribute parallel for')
+ Expr *NUB;
+ /// Distribute Loop condition used when composing 'omp distribute'
+ /// with 'omp for' in a same construct when schedule is chunked.
+ Expr *DistCond;
+ /// 'omp parallel for' loop condition used when composed with
+ /// 'omp distribute' in the same construct and when schedule is
+ /// chunked and the chunk size is 1.
+ Expr *ParForInDistCond;
+ };
+
+ /// The expressions built for the OpenMP loop CodeGen for the
+ /// whole collapsed loop nest.
+ struct HelperExprs {
+ /// Loop iteration variable.
+ Expr *IterationVarRef;
+ /// Loop last iteration number.
+ Expr *LastIteration;
+ /// Loop number of iterations.
+ Expr *NumIterations;
+ /// Calculation of last iteration.
+ Expr *CalcLastIteration;
+ /// Loop pre-condition.
+ Expr *PreCond;
+ /// Loop condition.
+ Expr *Cond;
+ /// Loop iteration variable init.
+ Expr *Init;
+ /// Loop increment.
+ Expr *Inc;
+ /// IsLastIteration - local flag variable passed to runtime.
+ Expr *IL;
+ /// LowerBound - local variable passed to runtime.
+ Expr *LB;
+ /// UpperBound - local variable passed to runtime.
+ Expr *UB;
+ /// Stride - local variable passed to runtime.
+ Expr *ST;
+ /// EnsureUpperBound -- expression UB = min(UB, NumIterations).
+ Expr *EUB;
+ /// Update of LowerBound for statically scheduled 'omp for' loops.
+ Expr *NLB;
+ /// Update of UpperBound for statically scheduled 'omp for' loops.
+ Expr *NUB;
+ /// PreviousLowerBound - local variable passed to runtime in the
+ /// enclosing schedule or null if that does not apply.
+ Expr *PrevLB;
+ /// PreviousUpperBound - local variable passed to runtime in the
+ /// enclosing schedule or null if that does not apply.
+ Expr *PrevUB;
+ /// DistInc - increment expression for distribute loop when found
+ /// combined with a further loop level (e.g. in 'distribute parallel for')
+ /// expression IV = IV + ST
+ Expr *DistInc;
+ /// PrevEUB - expression similar to EUB but to be used when loop
+ /// scheduling uses PrevLB and PrevUB (e.g. in 'distribute parallel for'
+ /// when ensuring that the UB is either the calculated UB by the runtime or
+ /// the end of the assigned distribute chunk)
+ /// expression UB = min (UB, PrevUB)
+ Expr *PrevEUB;
+ /// Counters Loop counters.
+ SmallVector<Expr *, 4> Counters;
+ /// PrivateCounters Loop counters.
+ SmallVector<Expr *, 4> PrivateCounters;
+ /// Expressions for loop counters inits for CodeGen.
+ SmallVector<Expr *, 4> Inits;
+ /// Expressions for loop counters update for CodeGen.
+ SmallVector<Expr *, 4> Updates;
+ /// Final loop counter values for GodeGen.
+ SmallVector<Expr *, 4> Finals;
+ /// List of counters required for the generation of the non-rectangular
+ /// loops.
+ SmallVector<Expr *, 4> DependentCounters;
+ /// List of initializers required for the generation of the non-rectangular
+ /// loops.
+ SmallVector<Expr *, 4> DependentInits;
+ /// List of final conditions required for the generation of the
+ /// non-rectangular loops.
+ SmallVector<Expr *, 4> FinalsConditions;
+ /// Init statement for all captured expressions.
+ Stmt *PreInits;
+
+ /// Expressions used when combining OpenMP loop pragmas
+ DistCombinedHelperExprs DistCombinedFields;
+
+ /// Check if all the expressions are built (does not check the
+ /// worksharing ones).
+ bool builtAll() {
+ return IterationVarRef != nullptr && LastIteration != nullptr &&
+ NumIterations != nullptr && PreCond != nullptr &&
+ Cond != nullptr && Init != nullptr && Inc != nullptr;
+ }
+
+ /// Initialize all the fields to null.
+ /// \param Size Number of elements in the
+ /// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions
+ /// arrays.
+ void clear(unsigned Size) {
+ IterationVarRef = nullptr;
+ LastIteration = nullptr;
+ CalcLastIteration = nullptr;
+ PreCond = nullptr;
+ Cond = nullptr;
+ Init = nullptr;
+ Inc = nullptr;
+ IL = nullptr;
+ LB = nullptr;
+ UB = nullptr;
+ ST = nullptr;
+ EUB = nullptr;
+ NLB = nullptr;
+ NUB = nullptr;
+ NumIterations = nullptr;
+ PrevLB = nullptr;
+ PrevUB = nullptr;
+ DistInc = nullptr;
+ PrevEUB = nullptr;
+ Counters.resize(Size);
+ PrivateCounters.resize(Size);
+ Inits.resize(Size);
+ Updates.resize(Size);
+ Finals.resize(Size);
+ DependentCounters.resize(Size);
+ DependentInits.resize(Size);
+ FinalsConditions.resize(Size);
+ for (unsigned I = 0; I < Size; ++I) {
+ Counters[I] = nullptr;
+ PrivateCounters[I] = nullptr;
+ Inits[I] = nullptr;
+ Updates[I] = nullptr;
+ Finals[I] = nullptr;
+ DependentCounters[I] = nullptr;
+ DependentInits[I] = nullptr;
+ FinalsConditions[I] = nullptr;
+ }
+ PreInits = nullptr;
+ DistCombinedFields.LB = nullptr;
+ DistCombinedFields.UB = nullptr;
+ DistCombinedFields.EUB = nullptr;
+ DistCombinedFields.Init = nullptr;
+ DistCombinedFields.Cond = nullptr;
+ DistCombinedFields.NLB = nullptr;
+ DistCombinedFields.NUB = nullptr;
+ DistCombinedFields.DistCond = nullptr;
+ DistCombinedFields.ParForInDistCond = nullptr;
+ }
+ };
+
+ /// Get number of collapsed loops.
+ unsigned getLoopsNumber() const { return NumAssociatedLoops; }
+
+ /// Try to find the next loop sub-statement in the specified statement \p
+ /// CurStmt.
+ /// \param TryImperfectlyNestedLoops true, if we need to try to look for the
+ /// imperfectly nested loop.
+ static Stmt *tryToFindNextInnerLoop(Stmt *CurStmt,
+ bool TryImperfectlyNestedLoops);
+ static const Stmt *tryToFindNextInnerLoop(const Stmt *CurStmt,
+ bool TryImperfectlyNestedLoops) {
+ return tryToFindNextInnerLoop(const_cast<Stmt *>(CurStmt),
+ TryImperfectlyNestedLoops);
+ }
+
+ /// Calls the specified callback function for all the loops in \p CurStmt,
+ /// from the outermost to the innermost.
+ static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops,
+ unsigned NumLoops,
+ llvm::function_ref<bool(unsigned, Stmt *)> Callback,
+ llvm::function_ref<void(OMPLoopBasedDirective *)>
+ OnTransformationCallback);
+ static bool
+ doForAllLoops(const Stmt *CurStmt, bool TryImperfectlyNestedLoops,
+ unsigned NumLoops,
+ llvm::function_ref<bool(unsigned, const Stmt *)> Callback,
+ llvm::function_ref<void(const OMPLoopBasedDirective *)>
+ OnTransformationCallback) {
+ auto &&NewCallback = [Callback](unsigned Cnt, Stmt *CurStmt) {
+ return Callback(Cnt, CurStmt);
+ };
+ auto &&NewTransformCb =
+ [OnTransformationCallback](OMPLoopBasedDirective *A) {
+ OnTransformationCallback(A);
+ };
+ return doForAllLoops(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
+ NumLoops, NewCallback, NewTransformCb);
+ }
+
+ /// Calls the specified callback function for all the loops in \p CurStmt,
+ /// from the outermost to the innermost.
+ static bool
+ doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops,
+ unsigned NumLoops,
+ llvm::function_ref<bool(unsigned, Stmt *)> Callback) {
+ auto &&TransformCb = [](OMPLoopBasedDirective *) {};
+ return doForAllLoops(CurStmt, TryImperfectlyNestedLoops, NumLoops, Callback,
+ TransformCb);
+ }
+ static bool
+ doForAllLoops(const Stmt *CurStmt, bool TryImperfectlyNestedLoops,
+ unsigned NumLoops,
+ llvm::function_ref<bool(unsigned, const Stmt *)> Callback) {
+ auto &&NewCallback = [Callback](unsigned Cnt, const Stmt *CurStmt) {
+ return Callback(Cnt, CurStmt);
+ };
+ return doForAllLoops(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
+ NumLoops, NewCallback);
+ }
+
+ /// Calls the specified callback function for all the loop bodies in \p
+ /// CurStmt, from the outermost loop to the innermost.
+ static void doForAllLoopsBodies(
+ Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
+ llvm::function_ref<void(unsigned, Stmt *, Stmt *)> Callback);
+ static void doForAllLoopsBodies(
+ const Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
+ llvm::function_ref<void(unsigned, const Stmt *, const Stmt *)> Callback) {
+ auto &&NewCallback = [Callback](unsigned Cnt, Stmt *Loop, Stmt *Body) {
+ Callback(Cnt, Loop, Body);
+ };
+ doForAllLoopsBodies(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
+ NumLoops, NewCallback);
+ }
+
+ static bool classof(const Stmt *T) {
+ if (auto *D = dyn_cast<OMPExecutableDirective>(T))
+ return isOpenMPLoopDirective(D->getDirectiveKind());
+ return false;
+ }
+};
+
/// This is a common base class for loop directives ('omp simd', 'omp
/// for', 'omp for simd' etc.). It is responsible for the loop code generation.
///
-class OMPLoopDirective : public OMPExecutableDirective {
+class OMPLoopDirective : public OMPLoopBasedDirective {
friend class ASTStmtReader;
- /// Number of collapsed loops as specified by 'collapse' clause.
- unsigned CollapsedNum = 0;
/// Offsets to the stored exprs.
/// This enumeration contains offsets to all the pointers to children
@@ -454,7 +966,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
/// The first 9 children are necessary for all the loop directives,
/// the next 8 are specific to the worksharing ones, and the next 11 are
/// used for combined constructs containing two pragmas associated to loops.
- /// After the fixed children, three arrays of length CollapsedNum are
+ /// After the fixed children, three arrays of length NumAssociatedLoops are
/// allocated: loop counters, their updates and final values.
/// PrevLowerBound and PrevUpperBound are used to communicate blocking
/// information in composite constructs which require loop blocking
@@ -512,63 +1024,63 @@ class OMPLoopDirective : public OMPExecutableDirective {
MutableArrayRef<Expr *> getCounters() {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind())]);
- return llvm::makeMutableArrayRef(Storage, CollapsedNum);
+ return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
}
/// Get the private counters storage.
MutableArrayRef<Expr *> getPrivateCounters() {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
- CollapsedNum]);
- return llvm::makeMutableArrayRef(Storage, CollapsedNum);
+ getLoopsNumber()]);
+ return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
}
/// Get the updates storage.
MutableArrayRef<Expr *> getInits() {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
- 2 * CollapsedNum]);
- return llvm::makeMutableArrayRef(Storage, CollapsedNum);
+ 2 * getLoopsNumber()]);
+ return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
}
/// Get the updates storage.
MutableArrayRef<Expr *> getUpdates() {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
- 3 * CollapsedNum]);
- return llvm::makeMutableArrayRef(Storage, CollapsedNum);
+ 3 * getLoopsNumber()]);
+ return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
}
/// Get the final counter updates storage.
MutableArrayRef<Expr *> getFinals() {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
- 4 * CollapsedNum]);
- return llvm::makeMutableArrayRef(Storage, CollapsedNum);
+ 4 * getLoopsNumber()]);
+ return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
}
/// Get the dependent counters storage.
MutableArrayRef<Expr *> getDependentCounters() {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
- 5 * CollapsedNum]);
- return llvm::makeMutableArrayRef(Storage, CollapsedNum);
+ 5 * getLoopsNumber()]);
+ return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
}
/// Get the dependent inits storage.
MutableArrayRef<Expr *> getDependentInits() {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
- 6 * CollapsedNum]);
- return llvm::makeMutableArrayRef(Storage, CollapsedNum);
+ 6 * getLoopsNumber()]);
+ return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
}
/// Get the finals conditions storage.
MutableArrayRef<Expr *> getFinalsConditions() {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
- 7 * CollapsedNum]);
- return llvm::makeMutableArrayRef(Storage, CollapsedNum);
+ 7 * getLoopsNumber()]);
+ return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
}
protected:
@@ -583,8 +1095,7 @@ protected:
OMPLoopDirective(StmtClass SC, OpenMPDirectiveKind Kind,
SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum)
- : OMPExecutableDirective(SC, Kind, StartLoc, EndLoc),
- CollapsedNum(CollapsedNum) {}
+ : OMPLoopBasedDirective(SC, Kind, StartLoc, EndLoc, CollapsedNum) {}
/// Offset to the start of children expression arrays.
static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
@@ -753,180 +1264,6 @@ protected:
void setFinalsConditions(ArrayRef<Expr *> A);
public:
- /// The expressions built to support OpenMP loops in combined/composite
- /// pragmas (e.g. pragma omp distribute parallel for)
- struct DistCombinedHelperExprs {
- /// DistributeLowerBound - used when composing 'omp distribute' with
- /// 'omp for' in a same construct.
- Expr *LB;
- /// DistributeUpperBound - used when composing 'omp distribute' with
- /// 'omp for' in a same construct.
- Expr *UB;
- /// DistributeEnsureUpperBound - used when composing 'omp distribute'
- /// with 'omp for' in a same construct, EUB depends on DistUB
- Expr *EUB;
- /// Distribute loop iteration variable init used when composing 'omp
- /// distribute'
- /// with 'omp for' in a same construct
- Expr *Init;
- /// Distribute Loop condition used when composing 'omp distribute'
- /// with 'omp for' in a same construct
- Expr *Cond;
- /// Update of LowerBound for statically scheduled omp loops for
- /// outer loop in combined constructs (e.g. 'distribute parallel for')
- Expr *NLB;
- /// Update of UpperBound for statically scheduled omp loops for
- /// outer loop in combined constructs (e.g. 'distribute parallel for')
- Expr *NUB;
- /// Distribute Loop condition used when composing 'omp distribute'
- /// with 'omp for' in a same construct when schedule is chunked.
- Expr *DistCond;
- /// 'omp parallel for' loop condition used when composed with
- /// 'omp distribute' in the same construct and when schedule is
- /// chunked and the chunk size is 1.
- Expr *ParForInDistCond;
- };
-
- /// The expressions built for the OpenMP loop CodeGen for the
- /// whole collapsed loop nest.
- struct HelperExprs {
- /// Loop iteration variable.
- Expr *IterationVarRef;
- /// Loop last iteration number.
- Expr *LastIteration;
- /// Loop number of iterations.
- Expr *NumIterations;
- /// Calculation of last iteration.
- Expr *CalcLastIteration;
- /// Loop pre-condition.
- Expr *PreCond;
- /// Loop condition.
- Expr *Cond;
- /// Loop iteration variable init.
- Expr *Init;
- /// Loop increment.
- Expr *Inc;
- /// IsLastIteration - local flag variable passed to runtime.
- Expr *IL;
- /// LowerBound - local variable passed to runtime.
- Expr *LB;
- /// UpperBound - local variable passed to runtime.
- Expr *UB;
- /// Stride - local variable passed to runtime.
- Expr *ST;
- /// EnsureUpperBound -- expression UB = min(UB, NumIterations).
- Expr *EUB;
- /// Update of LowerBound for statically scheduled 'omp for' loops.
- Expr *NLB;
- /// Update of UpperBound for statically scheduled 'omp for' loops.
- Expr *NUB;
- /// PreviousLowerBound - local variable passed to runtime in the
- /// enclosing schedule or null if that does not apply.
- Expr *PrevLB;
- /// PreviousUpperBound - local variable passed to runtime in the
- /// enclosing schedule or null if that does not apply.
- Expr *PrevUB;
- /// DistInc - increment expression for distribute loop when found
- /// combined with a further loop level (e.g. in 'distribute parallel for')
- /// expression IV = IV + ST
- Expr *DistInc;
- /// PrevEUB - expression similar to EUB but to be used when loop
- /// scheduling uses PrevLB and PrevUB (e.g. in 'distribute parallel for'
- /// when ensuring that the UB is either the calculated UB by the runtime or
- /// the end of the assigned distribute chunk)
- /// expression UB = min (UB, PrevUB)
- Expr *PrevEUB;
- /// Counters Loop counters.
- SmallVector<Expr *, 4> Counters;
- /// PrivateCounters Loop counters.
- SmallVector<Expr *, 4> PrivateCounters;
- /// Expressions for loop counters inits for CodeGen.
- SmallVector<Expr *, 4> Inits;
- /// Expressions for loop counters update for CodeGen.
- SmallVector<Expr *, 4> Updates;
- /// Final loop counter values for GodeGen.
- SmallVector<Expr *, 4> Finals;
- /// List of counters required for the generation of the non-rectangular
- /// loops.
- SmallVector<Expr *, 4> DependentCounters;
- /// List of initializers required for the generation of the non-rectangular
- /// loops.
- SmallVector<Expr *, 4> DependentInits;
- /// List of final conditions required for the generation of the
- /// non-rectangular loops.
- SmallVector<Expr *, 4> FinalsConditions;
- /// Init statement for all captured expressions.
- Stmt *PreInits;
-
- /// Expressions used when combining OpenMP loop pragmas
- DistCombinedHelperExprs DistCombinedFields;
-
- /// Check if all the expressions are built (does not check the
- /// worksharing ones).
- bool builtAll() {
- return IterationVarRef != nullptr && LastIteration != nullptr &&
- NumIterations != nullptr && PreCond != nullptr &&
- Cond != nullptr && Init != nullptr && Inc != nullptr;
- }
-
- /// Initialize all the fields to null.
- /// \param Size Number of elements in the
- /// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions
- /// arrays.
- void clear(unsigned Size) {
- IterationVarRef = nullptr;
- LastIteration = nullptr;
- CalcLastIteration = nullptr;
- PreCond = nullptr;
- Cond = nullptr;
- Init = nullptr;
- Inc = nullptr;
- IL = nullptr;
- LB = nullptr;
- UB = nullptr;
- ST = nullptr;
- EUB = nullptr;
- NLB = nullptr;
- NUB = nullptr;
- NumIterations = nullptr;
- PrevLB = nullptr;
- PrevUB = nullptr;
- DistInc = nullptr;
- PrevEUB = nullptr;
- Counters.resize(Size);
- PrivateCounters.resize(Size);
- Inits.resize(Size);
- Updates.resize(Size);
- Finals.resize(Size);
- DependentCounters.resize(Size);
- DependentInits.resize(Size);
- FinalsConditions.resize(Size);
- for (unsigned i = 0; i < Size; ++i) {
- Counters[i] = nullptr;
- PrivateCounters[i] = nullptr;
- Inits[i] = nullptr;
- Updates[i] = nullptr;
- Finals[i] = nullptr;
- DependentCounters[i] = nullptr;
- DependentInits[i] = nullptr;
- FinalsConditions[i] = nullptr;
- }
- PreInits = nullptr;
- DistCombinedFields.LB = nullptr;
- DistCombinedFields.UB = nullptr;
- DistCombinedFields.EUB = nullptr;
- DistCombinedFields.Init = nullptr;
- DistCombinedFields.Cond = nullptr;
- DistCombinedFields.NLB = nullptr;
- DistCombinedFields.NUB = nullptr;
- DistCombinedFields.DistCond = nullptr;
- DistCombinedFields.ParForInDistCond = nullptr;
- }
- };
-
- /// Get number of collapsed loops.
- unsigned getCollapsedNumber() const { return CollapsedNum; }
-
Expr *getIterationVariable() const {
return cast<Expr>(Data->getChildren()[IterationVariableOffset]);
}
@@ -1067,17 +1404,6 @@ public:
"expected loop bound distribute sharing directive");
return cast<Expr>(Data->getChildren()[CombinedParForInDistConditionOffset]);
}
- /// Try to find the next loop sub-statement in the specified statement \p
- /// CurStmt.
- /// \param TryImperfectlyNestedLoops true, if we need to try to look for the
- /// imperfectly nested loop.
- static Stmt *tryToFindNextInnerLoop(Stmt *CurStmt,
- bool TryImperfectlyNestedLoops);
- static const Stmt *tryToFindNextInnerLoop(const Stmt *CurStmt,
- bool TryImperfectlyNestedLoops) {
- return tryToFindNextInnerLoop(const_cast<Stmt *>(CurStmt),
- TryImperfectlyNestedLoops);
- }
Stmt *getBody();
const Stmt *getBody() const {
return const_cast<OMPLoopDirective *>(this)->getBody();
@@ -1263,7 +1589,7 @@ class OMPForDirective : public OMPLoopDirective {
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) {
- Data->getChildren()[numLoopChildren(getCollapsedNumber(),
+ Data->getChildren()[numLoopChildren(getLoopsNumber(),
llvm::omp::OMPD_for)] = E;
}
@@ -1303,7 +1629,7 @@ public:
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() {
return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
- getCollapsedNumber(), llvm::omp::OMPD_for)]);
+ getLoopsNumber(), llvm::omp::OMPD_for)]);
}
const Expr *getTaskReductionRefExpr() const {
return const_cast<OMPForDirective *>(this)->getTaskReductionRefExpr();
@@ -1728,7 +2054,7 @@ class OMPParallelForDirective : public OMPLoopDirective {
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) {
- Data->getChildren()[numLoopChildren(getCollapsedNumber(),
+ Data->getChildren()[numLoopChildren(getLoopsNumber(),
llvm::omp::OMPD_parallel_for)] = E;
}
@@ -1770,7 +2096,7 @@ public:
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() {
return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
- getCollapsedNumber(), llvm::omp::OMPD_parallel_for)]);
+ getLoopsNumber(), llvm::omp::OMPD_parallel_for)]);
}
const Expr *getTaskReductionRefExpr() const {
return const_cast<OMPParallelForDirective *>(this)
@@ -2884,7 +3210,7 @@ class OMPTargetParallelForDirective : public OMPLoopDirective {
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) {
Data->getChildren()[numLoopChildren(
- getCollapsedNumber(), llvm::omp::OMPD_target_parallel_for)] = E;
+ getLoopsNumber(), llvm::omp::OMPD_target_parallel_for)] = E;
}
/// Set cancel state.
@@ -2925,7 +3251,7 @@ public:
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() {
return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
- getCollapsedNumber(), llvm::omp::OMPD_target_parallel_for)]);
+ getLoopsNumber(), llvm::omp::OMPD_target_parallel_for)]);
}
const Expr *getTaskReductionRefExpr() const {
return const_cast<OMPTargetParallelForDirective *>(this)
@@ -3696,7 +4022,7 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective {
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) {
Data->getChildren()[numLoopChildren(
- getCollapsedNumber(), llvm::omp::OMPD_distribute_parallel_for)] = E;
+ getLoopsNumber(), llvm::omp::OMPD_distribute_parallel_for)] = E;
}
/// Set cancel state.
@@ -3737,7 +4063,7 @@ public:
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() {
return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
- getCollapsedNumber(), llvm::omp::OMPD_distribute_parallel_for)]);
+ getLoopsNumber(), llvm::omp::OMPD_distribute_parallel_for)]);
}
const Expr *getTaskReductionRefExpr() const {
return const_cast<OMPDistributeParallelForDirective *>(this)
@@ -4255,8 +4581,7 @@ class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) {
Data->getChildren()[numLoopChildren(
- getCollapsedNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)] =
- E;
+ getLoopsNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)] = E;
}
/// Set cancel state.
@@ -4295,7 +4620,7 @@ public:
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() {
return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
- getCollapsedNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)]);
+ getLoopsNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)]);
}
const Expr *getTaskReductionRefExpr() const {
return const_cast<OMPTeamsDistributeParallelForDirective *>(this)
@@ -4472,7 +4797,7 @@ class OMPTargetTeamsDistributeParallelForDirective final
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) {
Data->getChildren()[numLoopChildren(
- getCollapsedNumber(),
+ getLoopsNumber(),
llvm::omp::OMPD_target_teams_distribute_parallel_for)] = E;
}
@@ -4512,7 +4837,7 @@ public:
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() {
return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
- getCollapsedNumber(),
+ getLoopsNumber(),
llvm::omp::OMPD_target_teams_distribute_parallel_for)]);
}
const Expr *getTaskReductionRefExpr() const {
@@ -4666,6 +4991,154 @@ public:
}
};
+/// This represents the '#pragma omp tile' loop transformation directive.
+class OMPTileDirective final : public OMPLoopBasedDirective {
+ friend class ASTStmtReader;
+ friend class OMPExecutableDirective;
+
+ /// Default list of offsets.
+ enum {
+ PreInitsOffset = 0,
+ TransformedStmtOffset,
+ };
+
+ explicit OMPTileDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumLoops)
+ : OMPLoopBasedDirective(OMPTileDirectiveClass, llvm::omp::OMPD_tile,
+ StartLoc, EndLoc, NumLoops) {}
+
+ void setPreInits(Stmt *PreInits) {
+ Data->getChildren()[PreInitsOffset] = PreInits;
+ }
+
+ void setTransformedStmt(Stmt *S) {
+ Data->getChildren()[TransformedStmtOffset] = S;
+ }
+
+public:
+ /// Create a new AST node representation for '#pragma omp tile'.
+ ///
+ /// \param C Context of the AST.
+ /// \param StartLoc Location of the introducer (e.g. the 'omp' token).
+ /// \param EndLoc Location of the directive's end (e.g. the tok::eod).
+ /// \param Clauses The directive's clauses.
+ /// \param NumLoops Number of associated loops (number of items in the
+ /// 'sizes' clause).
+ /// \param AssociatedStmt The outermost associated loop.
+ /// \param TransformedStmt The loop nest after tiling, or nullptr in
+ /// dependent contexts.
+ /// \param PreInits Helper preinits statements for the loop nest.
+ static OMPTileDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ unsigned NumLoops, Stmt *AssociatedStmt,
+ Stmt *TransformedStmt, Stmt *PreInits);
+
+ /// Build an empty '#pragma omp tile' AST node for deserialization.
+ ///
+ /// \param C Context of the AST.
+ /// \param NumClauses Number of clauses to allocate.
+ /// \param NumLoops Number of associated loops to allocate.
+ static OMPTileDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ unsigned NumLoops);
+
+ unsigned getNumAssociatedLoops() const { return getLoopsNumber(); }
+
+ /// Gets/sets the associated loops after tiling.
+ ///
+ /// This is in de-sugared format stored as a CompoundStmt.
+ ///
+ /// \code
+ /// for (...)
+ /// ...
+ /// \endcode
+ ///
+ /// Note that if the generated loops a become associated loops of another
+ /// directive, they may need to be hoisted before them.
+ Stmt *getTransformedStmt() const {
+ return Data->getChildren()[TransformedStmtOffset];
+ }
+
+ /// Return preinits statement.
+ Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTileDirectiveClass;
+ }
+};
+
+/// This represents the '#pragma omp unroll' loop transformation directive.
+///
+/// \code
+/// #pragma omp unroll
+/// for (int i = 0; i < 64; ++i)
+/// \endcode
+class OMPUnrollDirective final : public OMPLoopBasedDirective {
+ friend class ASTStmtReader;
+ friend class OMPExecutableDirective;
+
+ /// Default list of offsets.
+ enum {
+ PreInitsOffset = 0,
+ TransformedStmtOffset,
+ };
+
+ explicit OMPUnrollDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPLoopBasedDirective(OMPUnrollDirectiveClass, llvm::omp::OMPD_unroll,
+ StartLoc, EndLoc, 1) {}
+
+ /// Set the pre-init statements.
+ void setPreInits(Stmt *PreInits) {
+ Data->getChildren()[PreInitsOffset] = PreInits;
+ }
+
+ /// Set the de-sugared statement.
+ void setTransformedStmt(Stmt *S) {
+ Data->getChildren()[TransformedStmtOffset] = S;
+ }
+
+public:
+ /// Create a new AST node representation for '#pragma omp unroll'.
+ ///
+ /// \param C Context of the AST.
+ /// \param StartLoc Location of the introducer (e.g. the 'omp' token).
+ /// \param EndLoc Location of the directive's end (e.g. the tok::eod).
+ /// \param Clauses The directive's clauses.
+ /// \param AssociatedStmt The outermost associated loop.
+ /// \param TransformedStmt The loop nest after tiling, or nullptr in
+ /// dependent contexts.
+ /// \param PreInits Helper preinits statements for the loop nest.
+ static OMPUnrollDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ Stmt *TransformedStmt, Stmt *PreInits);
+
+ /// Build an empty '#pragma omp unroll' AST node for deserialization.
+ ///
+ /// \param C Context of the AST.
+ /// \param NumClauses Number of clauses to allocate.
+ static OMPUnrollDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses);
+
+ /// Get the de-sugared associated loops after unrolling.
+ ///
+ /// This is only used if the unrolled loop becomes an associated loop of
+ /// another directive, otherwise the loop is emitted directly using loop
+ /// transformation metadata. When the unrolled loop cannot be used by another
+ /// directive (e.g. because of the full clause), the transformed stmt can also
+ /// be nullptr.
+ Stmt *getTransformedStmt() const {
+ return Data->getChildren()[TransformedStmtOffset];
+ }
+
+ /// Return the pre-init statements.
+ Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPUnrollDirectiveClass;
+ }
+};
+
/// This represents '#pragma omp scan' directive.
///
/// \code
@@ -4718,6 +5191,175 @@ public:
}
};
+/// This represents '#pragma omp interop' directive.
+///
+/// \code
+/// #pragma omp interop init(target:obj) device(x) depend(inout:y) nowait
+/// \endcode
+/// In this example directive '#pragma omp interop' has
+/// clauses 'init', 'device', 'depend' and 'nowait'.
+///
+class OMPInteropDirective final : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ friend class OMPExecutableDirective;
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPInteropDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(OMPInteropDirectiveClass,
+ llvm::omp::OMPD_interop, StartLoc, EndLoc) {}
+
+ /// Build an empty directive.
+ ///
+ explicit OMPInteropDirective()
+ : OMPExecutableDirective(OMPInteropDirectiveClass,
+ llvm::omp::OMPD_interop, SourceLocation(),
+ SourceLocation()) {}
+
+public:
+ /// Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses The directive's clauses.
+ ///
+ static OMPInteropDirective *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses);
+
+ /// Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPInteropDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPInteropDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp dispatch' directive.
+///
+/// \code
+/// #pragma omp dispatch device(dnum)
+/// \endcode
+/// This example shows a directive '#pragma omp dispatch' with a
+/// device clause with variable 'dnum'.
+///
+class OMPDispatchDirective final : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ friend class OMPExecutableDirective;
+
+ /// The location of the target-call.
+ SourceLocation TargetCallLoc;
+
+ /// Set the location of the target-call.
+ void setTargetCallLoc(SourceLocation Loc) { TargetCallLoc = Loc; }
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPDispatchDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(OMPDispatchDirectiveClass,
+ llvm::omp::OMPD_dispatch, StartLoc, EndLoc) {}
+
+ /// Build an empty directive.
+ ///
+ explicit OMPDispatchDirective()
+ : OMPExecutableDirective(OMPDispatchDirectiveClass,
+ llvm::omp::OMPD_dispatch, SourceLocation(),
+ SourceLocation()) {}
+
+public:
+ /// Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param TargetCallLoc Location of the target-call.
+ ///
+ static OMPDispatchDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ SourceLocation TargetCallLoc);
+
+ /// Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPDispatchDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ /// Return location of target-call.
+ SourceLocation getTargetCallLoc() const { return TargetCallLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPDispatchDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp masked' directive.
+/// \code
+/// #pragma omp masked filter(tid)
+/// \endcode
+/// This example shows a directive '#pragma omp masked' with a filter clause
+/// with variable 'tid'.
+///
+class OMPMaskedDirective final : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ friend class OMPExecutableDirective;
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
+ StartLoc, EndLoc) {}
+
+ /// Build an empty directive.
+ ///
+ explicit OMPMaskedDirective()
+ : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
+ SourceLocation(), SourceLocation()) {}
+
+public:
+ /// Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPMaskedDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+
+ /// Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPMaskedDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPMaskedDirectiveClass;
+ }
+};
+
} // end namespace clang
#endif