Skip to content

Commit a42e515

Browse files
authored
[OpenMP] OpenMP 5.1 "assume" directive parsing support (#92731)
This is a minimal patch to support parsing for "omp assume" directives. These are meant to be hints to a compiler's optimisers: as such, it is legitimate (if not very useful) to ignore them. The patch builds on top of the existing support for "omp assumes" directives (note spelling!). Unlike the "omp [begin/end] assumes" directives, "omp assume" is associated with a compound statement, i.e. it can appear within a function. The "holds" assumption could (theoretically) be mapped onto the existing builtin "__builtin_assume", though the latter applies to a single point in the program, and the former to a range (i.e. the whole of the associated compound statement). This patch fixes sollve's OpenMP 5.1 "omp assume"-based tests.
1 parent 8370ba4 commit a42e515

36 files changed

+1315
-2
lines changed

clang/docs/OpenMPSupport.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ implementation.
314314
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
315315
| misc | assumes directives | :part:`worked on` | |
316316
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
317-
| misc | assume directive | :part:`worked on` | |
317+
| misc | assume directive | :good:`done` | |
318318
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
319319
| misc | nothing directive | :good:`done` | D123286 |
320320
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ Python Binding Changes
323323

324324
OpenMP Support
325325
--------------
326+
- Added support for 'omp assume' directive.
326327

327328
Improvements
328329
^^^^^^^^^^^^

clang/include/clang-c/Index.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2154,6 +2154,10 @@ enum CXCursorKind {
21542154
*/
21552155
CXCursor_OMPInterchangeDirective = 308,
21562156

2157+
/** OpenMP assume directive.
2158+
*/
2159+
CXCursor_OMPAssumeDirective = 309,
2160+
21572161
/** OpenACC Compute Construct.
21582162
*/
21592163
CXCursor_OpenACCComputeConstruct = 320,

clang/include/clang/AST/OpenMPClause.h

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,66 @@ template <class T> class OMPVarListClause : public OMPClause {
342342
}
343343
};
344344

345+
/// Class that represents a list of directive kinds (parallel, target, etc.)
346+
/// as used in \c absent, \c contains clauses.
347+
template <class T> class OMPDirectiveListClause : public OMPClause {
348+
/// Location of '('.
349+
SourceLocation LParenLoc;
350+
351+
protected:
352+
/// Number of directive kinds listed in the clause
353+
unsigned NumKinds;
354+
355+
public:
356+
/// Build a clause with \a NumKinds directive kinds.
357+
///
358+
/// \param K The clause kind.
359+
/// \param StartLoc Starting location of the clause (the clause keyword).
360+
/// \param LParenLoc Location of '('.
361+
/// \param EndLoc Ending location of the clause.
362+
/// \param NumKinds Number of directive kinds listed in the clause.
363+
OMPDirectiveListClause(OpenMPClauseKind K, SourceLocation StartLoc,
364+
SourceLocation LParenLoc, SourceLocation EndLoc,
365+
unsigned NumKinds)
366+
: OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc),
367+
NumKinds(NumKinds) {}
368+
369+
child_range children() {
370+
return child_range(child_iterator(), child_iterator());
371+
}
372+
373+
const_child_range children() const {
374+
return const_child_range(const_child_iterator(), const_child_iterator());
375+
}
376+
377+
child_range used_children() {
378+
return child_range(child_iterator(), child_iterator());
379+
}
380+
const_child_range used_children() const {
381+
return const_child_range(const_child_iterator(), const_child_iterator());
382+
}
383+
384+
MutableArrayRef<OpenMPDirectiveKind> getDirectiveKinds() {
385+
return MutableArrayRef<OpenMPDirectiveKind>(
386+
static_cast<T *>(this)
387+
->template getTrailingObjects<OpenMPDirectiveKind>(),
388+
NumKinds);
389+
}
390+
391+
void setDirectiveKinds(ArrayRef<OpenMPDirectiveKind> DK) {
392+
assert(
393+
DK.size() == NumKinds &&
394+
"Number of directive kinds is not the same as the preallocated buffer");
395+
std::copy(DK.begin(), DK.end(),
396+
static_cast<T *>(this)
397+
->template getTrailingObjects<OpenMPDirectiveKind>());
398+
}
399+
400+
SourceLocation getLParenLoc() { return LParenLoc; }
401+
402+
void setLParenLoc(SourceLocation S) { LParenLoc = S; }
403+
};
404+
345405
/// This represents 'allocator' clause in the '#pragma omp ...'
346406
/// directive.
347407
///
@@ -2013,6 +2073,184 @@ class OMPMergeableClause : public OMPClause {
20132073
}
20142074
};
20152075

2076+
/// This represents the 'absent' clause in the '#pragma omp assume'
2077+
/// directive.
2078+
///
2079+
/// \code
2080+
/// #pragma omp assume absent(<directive-name list>)
2081+
/// \endcode
2082+
/// In this example directive '#pragma omp assume' has an 'absent' clause.
2083+
class OMPAbsentClause final
2084+
: public OMPDirectiveListClause<OMPAbsentClause>,
2085+
private llvm::TrailingObjects<OMPAbsentClause, OpenMPDirectiveKind> {
2086+
friend OMPDirectiveListClause;
2087+
friend TrailingObjects;
2088+
2089+
/// Build 'absent' clause.
2090+
///
2091+
/// \param StartLoc Starting location of the clause.
2092+
/// \param LParenLoc Location of '('.
2093+
/// \param EndLoc Ending location of the clause.
2094+
/// \param NumKinds Number of directive kinds listed in the clause.
2095+
OMPAbsentClause(SourceLocation StartLoc, SourceLocation LParenLoc,
2096+
SourceLocation EndLoc, unsigned NumKinds)
2097+
: OMPDirectiveListClause<OMPAbsentClause>(
2098+
llvm::omp::OMPC_absent, StartLoc, LParenLoc, EndLoc, NumKinds) {}
2099+
2100+
/// Build an empty clause.
2101+
OMPAbsentClause(unsigned NumKinds)
2102+
: OMPDirectiveListClause<OMPAbsentClause>(
2103+
llvm::omp::OMPC_absent, SourceLocation(), SourceLocation(),
2104+
SourceLocation(), NumKinds) {}
2105+
2106+
public:
2107+
static OMPAbsentClause *Create(const ASTContext &C,
2108+
ArrayRef<OpenMPDirectiveKind> DKVec,
2109+
SourceLocation Loc, SourceLocation LLoc,
2110+
SourceLocation RLoc);
2111+
2112+
static OMPAbsentClause *CreateEmpty(const ASTContext &C, unsigned NumKinds);
2113+
2114+
static bool classof(const OMPClause *C) {
2115+
return C->getClauseKind() == llvm::omp::OMPC_absent;
2116+
}
2117+
};
2118+
2119+
/// This represents the 'contains' clause in the '#pragma omp assume'
2120+
/// directive.
2121+
///
2122+
/// \code
2123+
/// #pragma omp assume contains(<directive-name list>)
2124+
/// \endcode
2125+
/// In this example directive '#pragma omp assume' has a 'contains' clause.
2126+
class OMPContainsClause final
2127+
: public OMPDirectiveListClause<OMPContainsClause>,
2128+
private llvm::TrailingObjects<OMPContainsClause, OpenMPDirectiveKind> {
2129+
friend OMPDirectiveListClause;
2130+
friend TrailingObjects;
2131+
2132+
/// Build 'contains' clause.
2133+
///
2134+
/// \param StartLoc Starting location of the clause.
2135+
/// \param LParenLoc Location of '('.
2136+
/// \param EndLoc Ending location of the clause.
2137+
/// \param NumKinds Number of directive kinds listed in the clause.
2138+
OMPContainsClause(SourceLocation StartLoc, SourceLocation LParenLoc,
2139+
SourceLocation EndLoc, unsigned NumKinds)
2140+
: OMPDirectiveListClause<OMPContainsClause>(
2141+
llvm::omp::OMPC_contains, StartLoc, LParenLoc, EndLoc, NumKinds) {}
2142+
2143+
/// Build an empty clause.
2144+
OMPContainsClause(unsigned NumKinds)
2145+
: OMPDirectiveListClause<OMPContainsClause>(
2146+
llvm::omp::OMPC_contains, SourceLocation(), SourceLocation(),
2147+
SourceLocation(), NumKinds) {}
2148+
2149+
public:
2150+
static OMPContainsClause *Create(const ASTContext &C,
2151+
ArrayRef<OpenMPDirectiveKind> DKVec,
2152+
SourceLocation Loc, SourceLocation LLoc,
2153+
SourceLocation RLoc);
2154+
2155+
static OMPContainsClause *CreateEmpty(const ASTContext &C, unsigned NumKinds);
2156+
2157+
static bool classof(const OMPClause *C) {
2158+
return C->getClauseKind() == llvm::omp::OMPC_contains;
2159+
}
2160+
};
2161+
2162+
/// This represents the 'holds' clause in the '#pragma omp assume'
2163+
/// directive.
2164+
///
2165+
/// \code
2166+
/// #pragma omp assume holds(<expr>)
2167+
/// \endcode
2168+
/// In this example directive '#pragma omp assume' has a 'holds' clause.
2169+
class OMPHoldsClause final
2170+
: public OMPOneStmtClause<llvm::omp::OMPC_holds, OMPClause> {
2171+
friend class OMPClauseReader;
2172+
2173+
public:
2174+
/// Build 'holds' clause.
2175+
///
2176+
/// \param StartLoc Starting location of the clause.
2177+
/// \param EndLoc Ending location of the clause.
2178+
OMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
2179+
SourceLocation EndLoc)
2180+
: OMPOneStmtClause(E, StartLoc, LParenLoc, EndLoc) {}
2181+
2182+
/// Build an empty clause.
2183+
OMPHoldsClause() : OMPOneStmtClause() {}
2184+
2185+
Expr *getExpr() const { return getStmtAs<Expr>(); }
2186+
void setExpr(Expr *E) { setStmt(E); }
2187+
};
2188+
2189+
/// This represents the 'no_openmp' clause in the '#pragma omp assume'
2190+
/// directive.
2191+
///
2192+
/// \code
2193+
/// #pragma omp assume no_openmp
2194+
/// \endcode
2195+
/// In this example directive '#pragma omp assume' has a 'no_openmp' clause.
2196+
class OMPNoOpenMPClause final
2197+
: public OMPNoChildClause<llvm::omp::OMPC_no_openmp> {
2198+
public:
2199+
/// Build 'no_openmp' clause.
2200+
///
2201+
/// \param StartLoc Starting location of the clause.
2202+
/// \param EndLoc Ending location of the clause.
2203+
OMPNoOpenMPClause(SourceLocation StartLoc, SourceLocation EndLoc)
2204+
: OMPNoChildClause(StartLoc, EndLoc) {}
2205+
2206+
/// Build an empty clause.
2207+
OMPNoOpenMPClause() : OMPNoChildClause() {}
2208+
};
2209+
2210+
/// This represents the 'no_openmp_routines' clause in the '#pragma omp assume'
2211+
/// directive.
2212+
///
2213+
/// \code
2214+
/// #pragma omp assume no_openmp_routines
2215+
/// \endcode
2216+
/// In this example directive '#pragma omp assume' has a 'no_openmp_routines'
2217+
/// clause.
2218+
class OMPNoOpenMPRoutinesClause final
2219+
: public OMPNoChildClause<llvm::omp::OMPC_no_openmp_routines> {
2220+
public:
2221+
/// Build 'no_openmp_routines' clause.
2222+
///
2223+
/// \param StartLoc Starting location of the clause.
2224+
/// \param EndLoc Ending location of the clause.
2225+
OMPNoOpenMPRoutinesClause(SourceLocation StartLoc, SourceLocation EndLoc)
2226+
: OMPNoChildClause(StartLoc, EndLoc) {}
2227+
2228+
/// Build an empty clause.
2229+
OMPNoOpenMPRoutinesClause() : OMPNoChildClause() {}
2230+
};
2231+
2232+
/// This represents the 'no_parallelism' clause in the '#pragma omp assume'
2233+
/// directive.
2234+
///
2235+
/// \code
2236+
/// #pragma omp assume no_parallelism
2237+
/// \endcode
2238+
/// In this example directive '#pragma omp assume' has a 'no_parallelism'
2239+
/// clause.
2240+
class OMPNoParallelismClause final
2241+
: public OMPNoChildClause<llvm::omp::OMPC_no_parallelism> {
2242+
public:
2243+
/// Build 'no_parallelism' clause.
2244+
///
2245+
/// \param StartLoc Starting location of the clause.
2246+
/// \param EndLoc Ending location of the clause.
2247+
OMPNoParallelismClause(SourceLocation StartLoc, SourceLocation EndLoc)
2248+
: OMPNoChildClause(StartLoc, EndLoc) {}
2249+
2250+
/// Build an empty clause.
2251+
OMPNoParallelismClause() : OMPNoChildClause() {}
2252+
};
2253+
20162254
/// This represents 'read' clause in the '#pragma omp atomic' directive.
20172255
///
20182256
/// \code

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3238,6 +3238,9 @@ DEF_TRAVERSE_STMT(OMPParallelGenericLoopDirective,
32383238
DEF_TRAVERSE_STMT(OMPTargetParallelGenericLoopDirective,
32393239
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
32403240

3241+
DEF_TRAVERSE_STMT(OMPAssumeDirective,
3242+
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
3243+
32413244
DEF_TRAVERSE_STMT(OMPErrorDirective,
32423245
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
32433246

@@ -3480,6 +3483,38 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAcqRelClause(OMPAcqRelClause *) {
34803483
return true;
34813484
}
34823485

3486+
template <typename Derived>
3487+
bool RecursiveASTVisitor<Derived>::VisitOMPAbsentClause(OMPAbsentClause *) {
3488+
return true;
3489+
}
3490+
3491+
template <typename Derived>
3492+
bool RecursiveASTVisitor<Derived>::VisitOMPHoldsClause(OMPHoldsClause *) {
3493+
return true;
3494+
}
3495+
3496+
template <typename Derived>
3497+
bool RecursiveASTVisitor<Derived>::VisitOMPContainsClause(OMPContainsClause *) {
3498+
return true;
3499+
}
3500+
3501+
template <typename Derived>
3502+
bool RecursiveASTVisitor<Derived>::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {
3503+
return true;
3504+
}
3505+
3506+
template <typename Derived>
3507+
bool RecursiveASTVisitor<Derived>::VisitOMPNoOpenMPRoutinesClause(
3508+
OMPNoOpenMPRoutinesClause *) {
3509+
return true;
3510+
}
3511+
3512+
template <typename Derived>
3513+
bool RecursiveASTVisitor<Derived>::VisitOMPNoParallelismClause(
3514+
OMPNoParallelismClause *) {
3515+
return true;
3516+
}
3517+
34833518
template <typename Derived>
34843519
bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) {
34853520
return true;

clang/include/clang/AST/StmtOpenMP.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6468,6 +6468,36 @@ class OMPErrorDirective final : public OMPExecutableDirective {
64686468
return T->getStmtClass() == OMPErrorDirectiveClass;
64696469
}
64706470
};
6471+
6472+
// It's not really an executable directive, but it seems convenient to use
6473+
// that as the parent class.
6474+
class OMPAssumeDirective final : public OMPExecutableDirective {
6475+
friend class ASTStmtReader;
6476+
friend class OMPExecutableDirective;
6477+
6478+
private:
6479+
OMPAssumeDirective(SourceLocation StartLoc, SourceLocation EndLoc)
6480+
: OMPExecutableDirective(OMPAssumeDirectiveClass, llvm::omp::OMPD_assume,
6481+
StartLoc, EndLoc) {}
6482+
6483+
explicit OMPAssumeDirective()
6484+
: OMPExecutableDirective(OMPAssumeDirectiveClass, llvm::omp::OMPD_assume,
6485+
SourceLocation(), SourceLocation()) {}
6486+
6487+
public:
6488+
static OMPAssumeDirective *Create(const ASTContext &Ctx,
6489+
SourceLocation StartLoc,
6490+
SourceLocation EndLoc,
6491+
ArrayRef<OMPClause *> Clauses, Stmt *AStmt);
6492+
6493+
static OMPAssumeDirective *CreateEmpty(const ASTContext &C,
6494+
unsigned NumClauses, EmptyShell);
6495+
6496+
static bool classof(const Stmt *T) {
6497+
return T->getStmtClass() == OMPAssumeDirectiveClass;
6498+
}
6499+
};
6500+
64716501
} // end namespace clang
64726502

64736503
#endif

clang/include/clang/Basic/OpenMPKinds.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,11 @@ bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter);
377377
/// otherwise - false.
378378
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind);
379379

380+
/// Checks if the specified directive is considered as "informational".
381+
/// \param DKind Specified directive.
382+
/// \return true if it is an informational directive, false otherwise.
383+
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind);
384+
380385
/// Checks if the specified directive can capture variables.
381386
/// \param DKind Specified directive.
382387
/// \return true - if the above condition is met for this directive

clang/include/clang/Basic/StmtNodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ def OMPTeamsGenericLoopDirective : StmtNode<OMPLoopDirective>;
298298
def OMPTargetTeamsGenericLoopDirective : StmtNode<OMPLoopDirective>;
299299
def OMPParallelGenericLoopDirective : StmtNode<OMPLoopDirective>;
300300
def OMPTargetParallelGenericLoopDirective : StmtNode<OMPLoopDirective>;
301+
def OMPAssumeDirective : StmtNode<OMPExecutableDirective>;
301302
def OMPErrorDirective : StmtNode<OMPExecutableDirective>;
302303

303304
// OpenACC Constructs.

0 commit comments

Comments
 (0)