Skip to content

Commit f6addc4

Browse files
committed
[OpenMP] OpenMP 5.1 "assume" directive parsing support
This patch supports parsing of "omp assume" directives. These are meant to be hints to a compiler' optimisers: as such, it is legitimate (if not very useful) to ignore them. This version of the patch implements new AST nodes for the "assume" directive and the various clauses it accepts as arguments, and adds new (C++ module) tests for serialization/deserialization of said nodes. 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). The "assume" directive appears to be distinct from the [[omp::assume]] annotation. This patch fixes sollve's OpenMP 5.1 "omp assume"-based tests.
1 parent cc2fb58 commit f6addc4

32 files changed

+1079
-2
lines changed

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: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/ADT/ArrayRef.h"
3030
#include "llvm/ADT/MapVector.h"
3131
#include "llvm/ADT/PointerIntPair.h"
32+
#include "llvm/ADT/SmallSet.h"
3233
#include "llvm/ADT/SmallVector.h"
3334
#include "llvm/ADT/iterator.h"
3435
#include "llvm/ADT/iterator_range.h"
@@ -2013,6 +2014,179 @@ class OMPMergeableClause : public OMPClause {
20132014
}
20142015
};
20152016

2017+
/// This represents the 'absent' clause in the '#pragma omp assume'
2018+
/// directive.
2019+
///
2020+
/// \code
2021+
/// #pragma omp assume absent(<directive-name list>)
2022+
/// \endcode
2023+
/// In this example directive '#pragma omp assume' has an 'absent' clause.
2024+
class OMPAbsentClause final : public OMPNoChildClause<llvm::omp::OMPC_absent> {
2025+
llvm::SmallSet<OpenMPDirectiveKind, 4> DirectiveKinds;
2026+
2027+
/// Location of '('.
2028+
SourceLocation LParenLoc;
2029+
2030+
public:
2031+
/// Build 'absent' clause.
2032+
///
2033+
/// \param StartLoc Starting location of the clause.
2034+
/// \param EndLoc Ending location of the clause.
2035+
OMPAbsentClause(llvm::SmallSet<OpenMPDirectiveKind, 4> &DKSet,
2036+
SourceLocation StartLoc, SourceLocation LParenLoc,
2037+
SourceLocation EndLoc)
2038+
: OMPNoChildClause(StartLoc, EndLoc), DirectiveKinds(DKSet),
2039+
LParenLoc(LParenLoc) {}
2040+
2041+
/// Build an empty clause.
2042+
OMPAbsentClause() : OMPNoChildClause() {}
2043+
2044+
SourceLocation getLParenLoc() { return LParenLoc; }
2045+
2046+
void setLParenLoc(SourceLocation S) { LParenLoc = S; }
2047+
2048+
llvm::SmallSet<OpenMPDirectiveKind, 4> &getDirectiveKinds() {
2049+
return DirectiveKinds;
2050+
}
2051+
2052+
void setDirectiveKinds(llvm::SmallSet<OpenMPDirectiveKind, 4> &DKS) {
2053+
DirectiveKinds = DKS;
2054+
}
2055+
};
2056+
2057+
/// This represents the 'contains' clause in the '#pragma omp assume'
2058+
/// directive.
2059+
///
2060+
/// \code
2061+
/// #pragma omp assume contains(<directive-name list>)
2062+
/// \endcode
2063+
/// In this example directive '#pragma omp assume' has a 'contains' clause.
2064+
class OMPContainsClause final
2065+
: public OMPNoChildClause<llvm::omp::OMPC_contains> {
2066+
llvm::SmallSet<OpenMPDirectiveKind, 4> DirectiveKinds;
2067+
2068+
/// Location of '('.
2069+
SourceLocation LParenLoc;
2070+
2071+
public:
2072+
/// Build 'contains' clause.
2073+
///
2074+
/// \param StartLoc Starting location of the clause.
2075+
/// \param EndLoc Ending location of the clause.
2076+
OMPContainsClause(llvm::SmallSet<OpenMPDirectiveKind, 4> &DKSet,
2077+
SourceLocation StartLoc, SourceLocation LParenLoc,
2078+
SourceLocation EndLoc)
2079+
: OMPNoChildClause(StartLoc, EndLoc), DirectiveKinds(DKSet),
2080+
LParenLoc(LParenLoc) {}
2081+
2082+
/// Build an empty clause.
2083+
OMPContainsClause() : OMPNoChildClause() {}
2084+
2085+
SourceLocation getLParenLoc() { return LParenLoc; }
2086+
2087+
void setLParenLoc(SourceLocation S) { LParenLoc = S; }
2088+
2089+
llvm::SmallSet<OpenMPDirectiveKind, 4> &getDirectiveKinds() {
2090+
return DirectiveKinds;
2091+
}
2092+
2093+
void setDirectiveKinds(llvm::SmallSet<OpenMPDirectiveKind, 4> &DKS) {
2094+
DirectiveKinds = DKS;
2095+
}
2096+
};
2097+
2098+
/// This represents the 'holds' clause in the '#pragma omp assume'
2099+
/// directive.
2100+
///
2101+
/// \code
2102+
/// #pragma omp assume holds(<expr>)
2103+
/// \endcode
2104+
/// In this example directive '#pragma omp assume' has a 'holds' clause.
2105+
class OMPHoldsClause final
2106+
: public OMPOneStmtClause<llvm::omp::OMPC_holds, OMPClause> {
2107+
friend class OMPClauseReader;
2108+
2109+
public:
2110+
/// Build 'holds' clause.
2111+
///
2112+
/// \param StartLoc Starting location of the clause.
2113+
/// \param EndLoc Ending location of the clause.
2114+
OMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
2115+
SourceLocation EndLoc)
2116+
: OMPOneStmtClause(E, StartLoc, LParenLoc, EndLoc) {}
2117+
2118+
/// Build an empty clause.
2119+
OMPHoldsClause() : OMPOneStmtClause() {}
2120+
2121+
Expr *getExpr() const { return getStmtAs<Expr>(); }
2122+
void setExpr(Expr *E) { setStmt(E); }
2123+
};
2124+
2125+
/// This represents the 'no_openmp' clause in the '#pragma omp assume'
2126+
/// directive.
2127+
///
2128+
/// \code
2129+
/// #pragma omp assume no_openmp
2130+
/// \endcode
2131+
/// In this example directive '#pragma omp assume' has a 'no_openmp' clause.
2132+
class OMPNoOpenMPClause final
2133+
: public OMPNoChildClause<llvm::omp::OMPC_no_openmp> {
2134+
public:
2135+
/// Build 'no_openmp' clause.
2136+
///
2137+
/// \param StartLoc Starting location of the clause.
2138+
/// \param EndLoc Ending location of the clause.
2139+
OMPNoOpenMPClause(SourceLocation StartLoc, SourceLocation EndLoc)
2140+
: OMPNoChildClause(StartLoc, EndLoc) {}
2141+
2142+
/// Build an empty clause.
2143+
OMPNoOpenMPClause() : OMPNoChildClause() {}
2144+
};
2145+
2146+
/// This represents the 'no_openmp_routines' clause in the '#pragma omp assume'
2147+
/// directive.
2148+
///
2149+
/// \code
2150+
/// #pragma omp assume no_openmp_routines
2151+
/// \endcode
2152+
/// In this example directive '#pragma omp assume' has a 'no_openmp_routines'
2153+
/// clause.
2154+
class OMPNoOpenMPRoutinesClause final
2155+
: public OMPNoChildClause<llvm::omp::OMPC_no_openmp_routines> {
2156+
public:
2157+
/// Build 'no_openmp_routines' clause.
2158+
///
2159+
/// \param StartLoc Starting location of the clause.
2160+
/// \param EndLoc Ending location of the clause.
2161+
OMPNoOpenMPRoutinesClause(SourceLocation StartLoc, SourceLocation EndLoc)
2162+
: OMPNoChildClause(StartLoc, EndLoc) {}
2163+
2164+
/// Build an empty clause.
2165+
OMPNoOpenMPRoutinesClause() : OMPNoChildClause() {}
2166+
};
2167+
2168+
/// This represents the 'no_parallelism' clause in the '#pragma omp assume'
2169+
/// directive.
2170+
///
2171+
/// \code
2172+
/// #pragma omp assume no_parallelism
2173+
/// \endcode
2174+
/// In this example directive '#pragma omp assume' has a 'no_parallelism'
2175+
/// clause.
2176+
class OMPNoParallelismClause final
2177+
: public OMPNoChildClause<llvm::omp::OMPC_no_parallelism> {
2178+
public:
2179+
/// Build 'no_parallelism' clause.
2180+
///
2181+
/// \param StartLoc Starting location of the clause.
2182+
/// \param EndLoc Ending location of the clause.
2183+
OMPNoParallelismClause(SourceLocation StartLoc, SourceLocation EndLoc)
2184+
: OMPNoChildClause(StartLoc, EndLoc) {}
2185+
2186+
/// Build an empty clause.
2187+
OMPNoParallelismClause() : OMPNoChildClause() {}
2188+
};
2189+
20162190
/// This represents 'read' clause in the '#pragma omp atomic' directive.
20172191
///
20182192
/// \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
@@ -6486,6 +6486,36 @@ class OMPErrorDirective final : public OMPExecutableDirective {
64866486
return T->getStmtClass() == OMPErrorDirectiveClass;
64876487
}
64886488
};
6489+
6490+
// It's not really an executable directive, but it seems convenient to use
6491+
// that as the parent class.
6492+
class OMPAssumeDirective : public OMPExecutableDirective {
6493+
friend class ASTStmtReader;
6494+
friend class OMPExecutableDirective;
6495+
6496+
private:
6497+
OMPAssumeDirective(SourceLocation StartLoc, SourceLocation EndLoc)
6498+
: OMPExecutableDirective(OMPAssumeDirectiveClass, llvm::omp::OMPD_assume,
6499+
StartLoc, EndLoc) {}
6500+
6501+
explicit OMPAssumeDirective()
6502+
: OMPExecutableDirective(OMPAssumeDirectiveClass, llvm::omp::OMPD_assume,
6503+
SourceLocation(), SourceLocation()) {}
6504+
6505+
public:
6506+
static OMPAssumeDirective *Create(const ASTContext &Ctx,
6507+
SourceLocation StartLoc,
6508+
SourceLocation EndLoc,
6509+
ArrayRef<OMPClause *> Clauses, Stmt *AStmt);
6510+
6511+
static OMPAssumeDirective *CreateEmpty(const ASTContext &C,
6512+
unsigned NumClauses, EmptyShell);
6513+
6514+
static bool classof(const Stmt *T) {
6515+
return T->getStmtClass() == OMPAssumeDirectiveClass;
6516+
}
6517+
};
6518+
64896519
} // end namespace clang
64906520

64916521
#endif

clang/include/clang/Basic/OpenMPKinds.h

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

380+
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind);
381+
380382
/// Checks if the specified directive can capture variables.
381383
/// \param DKind Specified directive.
382384
/// \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.

clang/include/clang/Parse/Parser.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3530,6 +3530,10 @@ class Parser : public CodeCompletionHandler {
35303530
OpenMPDirectiveKind DKind, SourceLocation Loc,
35313531
bool ReadDirectiveWithinMetadirective);
35323532

3533+
StmtResult ParseOpenMPInformationalDirective(
3534+
ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
3535+
bool ReadDirectiveWithinMetadirective);
3536+
35333537
/// Parses clause of kind \a CKind for directive of a kind \a Kind.
35343538
///
35353539
/// \param DKind Kind of current directive.

clang/include/clang/Sema/SemaOpenMP.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,14 @@ class SemaOpenMP : public SemaBase {
400400
OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
401401
Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc,
402402
OpenMPDirectiveKind PrevMappedDirective = llvm::omp::OMPD_unknown);
403+
StmtResult ActOnOpenMPInformationalDirective(
404+
OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
405+
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
406+
SourceLocation EndLoc);
407+
StmtResult ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
408+
Stmt *AStmt, SourceLocation StartLoc,
409+
SourceLocation EndLoc);
410+
403411
/// Called on well-formed '\#pragma omp parallel' after parsing
404412
/// of the associated statement.
405413
StmtResult ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
@@ -941,6 +949,17 @@ class SemaOpenMP : public SemaBase {
941949
SourceLocation StartLoc,
942950
SourceLocation LParenLoc,
943951
SourceLocation EndLoc);
952+
/// Called on well-formed 'holds' clause.
953+
OMPClause *ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
954+
SourceLocation LParenLoc,
955+
SourceLocation EndLoc);
956+
/// Called on well-formed 'absent' or 'contains' clauses.
957+
OMPClause *ActOnOpenMPDirectivePresenceClause(
958+
OpenMPClauseKind CK, llvm::SmallSet<OpenMPDirectiveKind, 4> &DKSet,
959+
SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc);
960+
OMPClause *ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
961+
SourceLocation Loc,
962+
SourceLocation RLoc);
944963

945964
OMPClause *ActOnOpenMPSingleExprWithArgClause(
946965
OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,6 +1964,7 @@ enum StmtCode {
19641964
STMT_OMP_TARGET_TEAMS_GENERIC_LOOP_DIRECTIVE,
19651965
STMT_OMP_PARALLEL_GENERIC_LOOP_DIRECTIVE,
19661966
STMT_OMP_TARGET_PARALLEL_GENERIC_LOOP_DIRECTIVE,
1967+
STMT_OMP_ASSUME_DIRECTIVE,
19671968
EXPR_ARRAY_SECTION,
19681969
EXPR_OMP_ARRAY_SHAPING,
19691970
EXPR_OMP_ITERATOR,

0 commit comments

Comments
 (0)