[OpenMP 5.1] Parsing and Sema support for scope directive

structured-block

where clause is one of the following:

private(list)
reduction([reduction-modifier ,] reduction-identifier : list)
nowait

Differential Revision: https://reviews.llvm.org/D157933
This commit is contained in:
Fazlay Rabbi 2023-08-09 15:28:09 -07:00
parent e4cb692526
commit e4c7298bea
25 changed files with 1082 additions and 27 deletions

View File

@ -321,7 +321,7 @@ implementation.
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | error directive | :none:`unclaimed` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | scope construct | :none:`unclaimed` | |
| misc | scope construct | :none:`worked on` | D157933 |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | routines for controlling and querying team regions | :none:`unclaimed` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+

View File

@ -2136,7 +2136,11 @@ enum CXCursorKind {
*/
CXCursor_OMPErrorDirective = 305,
CXCursor_LastStmt = CXCursor_OMPErrorDirective,
/** OpenMP scope directive.
*/
CXCursor_OMPScopeDirective = 306,
CXCursor_LastStmt = CXCursor_OMPScopeDirective,
/**
* Cursor that represents the translation unit itself.

View File

@ -2980,6 +2980,9 @@ DEF_TRAVERSE_STMT(OMPSectionsDirective,
DEF_TRAVERSE_STMT(OMPSectionDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPScopeDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPSingleDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })

View File

@ -1931,6 +1931,57 @@ public:
}
};
/// This represents '#pragma omp scope' directive.
/// \code
/// #pragma omp scope private(a,b) nowait
/// \endcode
/// In this example directive '#pragma omp scope' has clauses 'private' with
/// the variables 'a' and 'b' and nowait.
///
class OMPScopeDirective 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.
///
OMPScopeDirective(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPExecutableDirective(OMPScopeDirectiveClass, llvm::omp::OMPD_scope,
StartLoc, EndLoc) {}
/// Build an empty directive.
///
explicit OMPScopeDirective()
: OMPExecutableDirective(OMPScopeDirectiveClass, llvm::omp::OMPD_scope,
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 OMPScopeDirective *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt);
/// Creates an empty directive.
///
/// \param C AST context.
///
static OMPScopeDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPScopeDirectiveClass;
}
};
/// This represents '#pragma omp single' directive.
///
/// \code

View File

@ -259,6 +259,7 @@ def OMPTargetUpdateDirective : StmtNode<OMPExecutableDirective>;
def OMPTeamsDirective : StmtNode<OMPExecutableDirective>;
def OMPCancellationPointDirective : StmtNode<OMPExecutableDirective>;
def OMPCancelDirective : StmtNode<OMPExecutableDirective>;
def OMPScopeDirective : StmtNode<OMPExecutableDirective>;
def OMPTaskLoopDirective : StmtNode<OMPLoopDirective>;
def OMPTaskLoopSimdDirective : StmtNode<OMPLoopDirective>;
def OMPMasterTaskLoopDirective : StmtNode<OMPLoopDirective>;

View File

@ -11554,6 +11554,11 @@ public:
/// associated statement.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
/// Called on well-formed '\#pragma omp scope' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
/// Called on well-formed '\#pragma omp single' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,

View File

@ -1995,6 +1995,7 @@ enum StmtCode {
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
STMT_OMP_SCOPE_DIRECTIVE,
STMT_OMP_INTEROP_DIRECTIVE,
STMT_OMP_DISPATCH_DIRECTIVE,
STMT_OMP_MASKED_DIRECTIVE,

View File

@ -531,6 +531,23 @@ OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C,
/*HasAssociatedStmt=*/true);
}
OMPScopeDirective *OMPScopeDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
return createDirective<OMPScopeDirective>(C, Clauses, AssociatedStmt,
/*NumChildren=*/0, StartLoc,
EndLoc);
}
OMPScopeDirective *OMPScopeDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
return createEmptyDirective<OMPScopeDirective>(C, NumClauses,
/*HasAssociatedStmt=*/true);
}
OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,

View File

@ -777,6 +777,11 @@ void StmtPrinter::VisitOMPSectionDirective(OMPSectionDirective *Node) {
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPScopeDirective(OMPScopeDirective *Node) {
Indent() << "#pragma omp scope";
PrintOMPExecutableDirective(Node);
}
void StmtPrinter::VisitOMPSingleDirective(OMPSingleDirective *Node) {
Indent() << "#pragma omp single";
PrintOMPExecutableDirective(Node);

View File

@ -996,6 +996,10 @@ void StmtProfiler::VisitOMPSectionDirective(const OMPSectionDirective *S) {
VisitOMPExecutableDirective(S);
}
void StmtProfiler::VisitOMPScopeDirective(const OMPScopeDirective *S) {
VisitOMPExecutableDirective(S);
}
void StmtProfiler::VisitOMPSingleDirective(const OMPSingleDirective *S) {
VisitOMPExecutableDirective(S);
}

View File

@ -848,6 +848,7 @@ void clang::getOpenMPCaptureRegions(
case OMPD_atomic:
case OMPD_target_data:
case OMPD_distribute_simd:
case OMPD_scope:
case OMPD_dispatch:
CaptureRegions.push_back(OMPD_unknown);
break;

View File

@ -409,6 +409,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
case Stmt::OMPDispatchDirectiveClass:
llvm_unreachable("Dispatch directive not supported yet.");
break;
case Stmt::OMPScopeDirectiveClass:
llvm_unreachable("scope not supported with FE outlining");
case Stmt::OMPMaskedDirectiveClass:
EmitOMPMaskedDirective(cast<OMPMaskedDirective>(*S));
break;

View File

@ -2418,6 +2418,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_distribute_simd:
case OMPD_target_parallel_for_simd:
case OMPD_target_simd:
case OMPD_scope:
case OMPD_teams_distribute:
case OMPD_teams_distribute_simd:
case OMPD_teams_distribute_parallel_for_simd:
@ -2810,6 +2811,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
case OMPD_target_teams_loop:
case OMPD_parallel_loop:
case OMPD_target_parallel_loop:
case OMPD_scope:
case OMPD_taskloop:
case OMPD_taskloop_simd:
case OMPD_master_taskloop:

View File

@ -1496,6 +1496,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
case Stmt::OMPTargetUpdateDirectiveClass:
case Stmt::OMPScopeDirectiveClass:
case Stmt::OMPTaskDirectiveClass:
case Stmt::OMPTaskgroupDirectiveClass:
case Stmt::OMPTaskLoopDirectiveClass:

View File

@ -3709,6 +3709,7 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
S->getDirectiveKind() == OMPD_section ||
S->getDirectiveKind() == OMPD_master ||
S->getDirectiveKind() == OMPD_masked ||
S->getDirectiveKind() == OMPD_scope ||
isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
Visit(S->getAssociatedStmt());
return;
@ -4319,6 +4320,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_distribute:
case OMPD_distribute_simd:
case OMPD_ordered:
case OMPD_scope:
case OMPD_target_data:
case OMPD_dispatch: {
Sema::CapturedParamNameType Params[] = {
@ -5130,7 +5132,10 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
diag::note_omp_previous_critical_region);
return true;
}
} else if (CurrentRegion == OMPD_barrier) {
} else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
// OpenMP 5.1 [2.22, Nesting of Regions]
// A scope region may not be closely nested inside a worksharing, loop,
// task, taskloop, critical, ordered, atomic, or masked region.
// OpenMP 5.1 [2.22, Nesting of Regions]
// A barrier region may not be closely nested inside a worksharing, loop,
// task, taskloop, critical, ordered, atomic, or masked region.
@ -6449,6 +6454,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
if (LangOpts.OpenMP >= 50)
AllowedNameModifiers.push_back(OMPD_simd);
break;
case OMPD_scope:
Res =
ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
break;
case OMPD_parallel_master:
Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
StartLoc, EndLoc);
@ -23904,6 +23913,17 @@ OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
Vars);
}
StmtResult Sema::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
if (!AStmt)
return StmtError();
setFunctionHasBranchProtectedScope();
return OMPScopeDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,

View File

@ -8925,6 +8925,17 @@ TreeTransform<Derived>::TransformOMPSectionDirective(OMPSectionDirective *D) {
return Res;
}
template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPScopeDirective(OMPScopeDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_scope, DirName, nullptr,
D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
}
template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective *D) {

View File

@ -2391,6 +2391,11 @@ void ASTStmtReader::VisitOMPSectionDirective(OMPSectionDirective *D) {
D->setHasCancel(Record.readBool());
}
void ASTStmtReader::VisitOMPScopeDirective(OMPScopeDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
}
void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
@ -3352,6 +3357,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = OMPSectionDirective::CreateEmpty(Context, Empty);
break;
case STMT_OMP_SCOPE_DIRECTIVE:
S = OMPScopeDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
case STMT_OMP_SINGLE_DIRECTIVE:
S = OMPSingleDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);

View File

@ -2308,6 +2308,12 @@ void ASTStmtWriter::VisitOMPSectionDirective(OMPSectionDirective *D) {
Code = serialization::STMT_OMP_SECTION_DIRECTIVE;
}
void ASTStmtWriter::VisitOMPScopeDirective(OMPScopeDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
Code = serialization::STMT_OMP_SCOPE_DIRECTIVE;
}
void ASTStmtWriter::VisitOMPSingleDirective(OMPSingleDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);

View File

@ -1746,6 +1746,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OMPForSimdDirectiveClass:
case Stmt::OMPSectionsDirectiveClass:
case Stmt::OMPSectionDirectiveClass:
case Stmt::OMPScopeDirectiveClass:
case Stmt::OMPSingleDirectiveClass:
case Stmt::OMPMasterDirectiveClass:
case Stmt::OMPCriticalDirectiveClass:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu\
//RUN: -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -ast-print %s | FileCheck %s --check-prefix=PRINT
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu\
//RUN: -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -ast-dump %s | FileCheck %s --check-prefix=DUMP
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu\
//RUN: -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -emit-pch -o %t %s
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu\
//RUN: -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -include-pch %t -ast-print %s | FileCheck %s --check-prefix=PRINT
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu\
//RUN: -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP
#ifndef HEADER
#define HEADER
int foo1() {
int a;
int i = 1;
#pragma omp scope private(a) reduction(+:i) nowait
{
a = 123;
++i;
}
return i;
}
//DUMP: FunctionDecl {{.*}}foo1 'int ()'
//DUMP: OMPScopeDirective
//DUMP: OMPPrivateClause
//DUMP: DeclRefExpr {{.*}}'int' lvalue Var{{.*}}'a' 'int'
//DUMP: OMPReductionClause
//DUMP: DeclRefExpr {{.*}}'int' lvalue Var{{.*}}'i' 'int'
//DUMP: OMPNowaitClause
//PRINT: #pragma omp scope private(a) reduction(+: i) nowait
template <typename T>
T run() {
T a;
T b;
#pragma omp scope private(a) reduction(*:b)
{
b *= a;
}
return b;
}
int template_test() {
double d;
d = run<double>();
return 0;
}
//DUMP: FunctionTemplateDecl {{.*}}run
//DUMP: TemplateTypeParmDecl {{.*}}referenced typename depth 0 index 0 T
//DUMP: FunctionDecl {{.*}}run 'T ()'
//DUMP: OMPScopeDirective
//DUMP: OMPPrivateClause
//DUMP: DeclRefExpr {{.*}}'T' lvalue Var {{.*}} 'a' 'T'
//DUMP: OMPReductionClause
//DUMP: DeclRefExpr {{.*}}'T' lvalue Var {{.*}} 'b' 'T'
//DUMP: FunctionDecl {{.*}}used run 'double ()'
//DUMP: TemplateArgument type 'double'
//DUMP: BuiltinType {{.*}}'double'
//DUMP: OMPScopeDirective
//DUMP: OMPPrivateClause
//DUMP: DeclRefExpr {{.*}}'double':'double' lvalue Var {{.*}} 'a' 'double':'double'
//DUMP: OMPReductionClause
//DUMP: DeclRefExpr {{.*}}'double':'double' lvalue Var {{.*}} 'b' 'double':'double'
//PRINT: #pragma omp scope private(a) reduction(*: b)
#endif // HEADER

View File

@ -0,0 +1,13 @@
// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 %s -verify=expected,omp51
// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 %s -verify=expected,omp51
void test1()
{
int var1;
int var2;
int var3 = 1;
// expected-error@+1 {{directive '#pragma omp scope' cannot contain more than one 'nowait' clause}} //omp51-error@+1{{unexpected OpenMP clause 'firstprivate' in directive '#pragma omp scope'}}
#pragma omp scope private(var1) firstprivate(var3) nowait nowait
{ var1 = 123; ++var2; var3 = 2;}
}

View File

@ -5951,6 +5951,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPSectionsDirective");
case CXCursor_OMPSectionDirective:
return cxstring::createRef("OMPSectionDirective");
case CXCursor_OMPScopeDirective:
return cxstring::createRef("OMPScopeDirective");
case CXCursor_OMPSingleDirective:
return cxstring::createRef("OMPSingleDirective");
case CXCursor_OMPMasterDirective:

View File

@ -680,6 +680,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OMPSectionDirectiveClass:
K = CXCursor_OMPSectionDirective;
break;
case Stmt::OMPScopeDirectiveClass:
K = CXCursor_OMPScopeDirective;
break;
case Stmt::OMPSingleDirectiveClass:
K = CXCursor_OMPSingleDirective;
break;

View File

@ -1979,6 +1979,15 @@ def OMP_BeginAssumes : Directive<"begin assumes"> {}
def OMP_EndAssumes : Directive<"end assumes"> {}
def OMP_BeginDeclareVariant : Directive<"begin declare variant"> {}
def OMP_EndDeclareVariant : Directive<"end declare variant"> {}
def OMP_scope : Directive<"scope"> {
let allowedClauses = [
VersionedClause<OMPC_Private, 51>,
VersionedClause<OMPC_Reduction, 51>,
];
let allowedOnceClauses = [
VersionedClause<OMPC_NoWait, 51>
];
}
def OMP_ParallelWorkshare : Directive<"parallel workshare"> {
let allowedClauses = [
VersionedClause<OMPC_Allocate>,