Skip to content

[clang][OpenMP] Simplify check for taskloop in `ActOnOpenMPLoopInitia… #98633

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jul 15, 2024
129 changes: 63 additions & 66 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4797,6 +4797,12 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
ShouldBeInTeamsRegion,
ShouldBeInLoopSimdRegion,
} Recommend = NoRecommend;

SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
ArrayRef<OpenMPDirectiveKind> ParentLOC =
getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();

if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
CurrentRegion != OMPD_parallel &&
Expand Down Expand Up @@ -4828,7 +4834,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
<< (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
return CurrentRegion != OMPD_simd;
}
if (ParentRegion == OMPD_atomic) {
if (EnclosingConstruct == OMPD_atomic) {
// OpenMP [2.16, Nesting of Regions]
// OpenMP constructs may not be nested inside an atomic region.
SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
Expand All @@ -4839,8 +4845,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
// Orphaned section directives are prohibited. That is, the section
// directives must appear within the sections construct and must not be
// encountered elsewhere in the sections region.
if (ParentRegion != OMPD_sections &&
ParentRegion != OMPD_parallel_sections) {
if (EnclosingConstruct != OMPD_sections) {
SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
<< (ParentRegion != OMPD_unknown)
<< getOpenMPDirectiveName(ParentRegion);
Expand All @@ -4861,7 +4866,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
(BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
(isOpenMPWorksharingDirective(ParentRegion) ||
ParentRegion == OMPD_loop)) {
EnclosingConstruct == OMPD_loop)) {
int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
<< true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
Expand All @@ -4881,27 +4886,17 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
// construct-type-clause is not taskgroup must be closely nested inside an
// OpenMP construct that matches the type specified in
// construct-type-clause.
NestingProhibited =
!((CancelRegion == OMPD_parallel &&
(ParentRegion == OMPD_parallel ||
ParentRegion == OMPD_target_parallel)) ||
(CancelRegion == OMPD_for &&
(ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
ParentRegion == OMPD_target_parallel_for ||
ParentRegion == OMPD_distribute_parallel_for ||
ParentRegion == OMPD_teams_distribute_parallel_for ||
ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
(CancelRegion == OMPD_taskgroup &&
(ParentRegion == OMPD_task ||
(SemaRef.getLangOpts().OpenMP >= 50 &&
(ParentRegion == OMPD_taskloop ||
ParentRegion == OMPD_master_taskloop ||
ParentRegion == OMPD_masked_taskloop ||
ParentRegion == OMPD_parallel_masked_taskloop ||
ParentRegion == OMPD_parallel_master_taskloop)))) ||
(CancelRegion == OMPD_sections &&
(ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
ParentRegion == OMPD_parallel_sections)));
ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
if (CancelRegion == OMPD_taskgroup) {
NestingProhibited = EnclosingConstruct != OMPD_task &&
(SemaRef.getLangOpts().OpenMP < 50 ||
EnclosingConstruct != OMPD_taskloop);
} else if (CancelRegion == OMPD_sections) {
NestingProhibited = EnclosingConstruct != OMPD_section &&
EnclosingConstruct != OMPD_sections;
} else {
NestingProhibited = CancelRegion != Leafs.back();
}
OrphanSeen = ParentRegion == OMPD_unknown;
} else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
// OpenMP 5.1 [2.22, Nesting of Regions]
Expand Down Expand Up @@ -4942,27 +4937,25 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
// 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.
NestingProhibited =
isOpenMPWorksharingDirective(ParentRegion) ||
isOpenMPGenericLoopDirective(ParentRegion) ||
isOpenMPTaskingDirective(ParentRegion) || ParentRegion == OMPD_master ||
ParentRegion == OMPD_masked || ParentRegion == OMPD_parallel_master ||
ParentRegion == OMPD_parallel_masked || ParentRegion == OMPD_critical ||
ParentRegion == OMPD_ordered;
NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
isOpenMPGenericLoopDirective(ParentRegion) ||
isOpenMPTaskingDirective(ParentRegion) ||
llvm::is_contained({OMPD_masked, OMPD_master,
OMPD_critical, OMPD_ordered},
EnclosingConstruct);
} else if (isOpenMPWorksharingDirective(CurrentRegion) &&
!isOpenMPParallelDirective(CurrentRegion) &&
!isOpenMPTeamsDirective(CurrentRegion)) {
// OpenMP 5.1 [2.22, Nesting of Regions]
// A loop region that binds to a parallel region or a worksharing region
// may not be closely nested inside a worksharing, loop, task, taskloop,
// critical, ordered, atomic, or masked region.
NestingProhibited =
isOpenMPWorksharingDirective(ParentRegion) ||
isOpenMPGenericLoopDirective(ParentRegion) ||
isOpenMPTaskingDirective(ParentRegion) || ParentRegion == OMPD_master ||
ParentRegion == OMPD_masked || ParentRegion == OMPD_parallel_master ||
ParentRegion == OMPD_parallel_masked || ParentRegion == OMPD_critical ||
ParentRegion == OMPD_ordered;
NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
isOpenMPGenericLoopDirective(ParentRegion) ||
isOpenMPTaskingDirective(ParentRegion) ||
llvm::is_contained({OMPD_masked, OMPD_master,
OMPD_critical, OMPD_ordered},
EnclosingConstruct);
Recommend = ShouldBeInParallelRegion;
} else if (CurrentRegion == OMPD_ordered) {
// OpenMP [2.16, Nesting of Regions]
Expand All @@ -4973,7 +4966,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
// OpenMP [2.8.1,simd Construct, Restrictions]
// An ordered construct with the simd clause is the only OpenMP construct
// that can appear in the simd region.
NestingProhibited = ParentRegion == OMPD_critical ||
NestingProhibited = EnclosingConstruct == OMPD_critical ||
isOpenMPTaskingDirective(ParentRegion) ||
!(isOpenMPSimdDirective(ParentRegion) ||
Stack->isParentOrderedRegion());
Expand All @@ -4983,22 +4976,19 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
// If specified, a teams construct must be contained within a target
// construct.
NestingProhibited =
(SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
(SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
ParentRegion != OMPD_target);
(SemaRef.LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
(SemaRef.LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
EnclosingConstruct != OMPD_target);
OrphanSeen = ParentRegion == OMPD_unknown;
Recommend = ShouldBeInTargetRegion;
} else if (CurrentRegion == OMPD_scan) {
if (SemaRef.LangOpts.OpenMP >= 50) {
SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
std::ignore = getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
// OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
// simd, or for simd. This has to take into account combined directives.
// In 5.2 this seems to be implied by the fact that the specified
// separated constructs are do, for, and simd.
OpenMPDirectiveKind Enclosing = LeafOrComposite.back();
NestingProhibited = Enclosing != OMPD_for && Enclosing != OMPD_simd &&
Enclosing != OMPD_for_simd;
NestingProhibited = !llvm::is_contained(
{OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
} else {
NestingProhibited = true;
}
Expand All @@ -5007,7 +4997,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
}
if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
!isOpenMPTargetDataManagementDirective(CurrentRegion) &&
(ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
EnclosingConstruct == OMPD_teams) {
// OpenMP [5.1, 2.22, Nesting of Regions]
// distribute, distribute simd, distribute parallel worksharing-loop,
// distribute parallel worksharing-loop SIMD, loop, parallel regions,
Expand All @@ -5029,17 +5019,15 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
// If the bind clause is present on the loop construct and binding is
// teams then the corresponding loop region must be strictly nested inside
// a teams region.
NestingProhibited = BindKind == OMPC_BIND_teams &&
ParentRegion != OMPD_teams &&
ParentRegion != OMPD_target_teams;
NestingProhibited =
BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
Recommend = ShouldBeInTeamsRegion;
}
if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
// OpenMP 4.5 [2.17 Nesting of Regions]
// The region associated with the distribute construct must be strictly
// nested inside a teams region
NestingProhibited =
(ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
NestingProhibited = EnclosingConstruct != OMPD_teams;
Recommend = ShouldBeInTeamsRegion;
}
if (!NestingProhibited &&
Expand Down Expand Up @@ -9102,14 +9090,15 @@ void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
isOpenMPSimdDirective(DKind)
? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
: OMPC_private;
auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
};
if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
(getLangOpts().OpenMP <= 45 ||
(DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
DKind == OMPD_parallel_master_taskloop ||
DKind == OMPD_parallel_masked_taskloop ||
((isOpenMPWorksharingDirective(DKind) ||
IsOpenMPTaskloopDirective(DKind) ||
isOpenMPDistributeDirective(DKind)) &&
!isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
Expand Down Expand Up @@ -18612,14 +18601,22 @@ OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
// worksharing-loop construct, a worksharing-loop SIMD construct, a simd
// construct, a parallel worksharing-loop construct or a parallel
// worksharing-loop SIMD construct.
if (Modifier == OMPC_REDUCTION_inscan &&
(DSAStack->getCurrentDirective() != OMPD_for &&
DSAStack->getCurrentDirective() != OMPD_for_simd &&
DSAStack->getCurrentDirective() != OMPD_simd &&
DSAStack->getCurrentDirective() != OMPD_parallel_for &&
DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
return nullptr;
// [5.2:136:1-4] A reduction clause with the inscan reduction-modifier may
// only appear on a worksharing-loop construct, a simd construct or a
// combined or composite construct for which any of the aforementioned
// constructs is a constituent construct and distribute is not a constituent
// construct.
if (Modifier == OMPC_REDUCTION_inscan) {
SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
ArrayRef<OpenMPDirectiveKind> CurrentLOC = getLeafOrCompositeConstructs(
DSAStack->getCurrentDirective(), LeafOrComposite);
bool Valid = llvm::any_of(CurrentLOC, [](OpenMPDirectiveKind DK) {
return llvm::is_contained({OMPD_for, OMPD_simd, OMPD_for_simd}, DK);
});
if (!Valid) {
Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
return nullptr;
}
}

ReductionData RD(VarList.size(), Modifier);
Expand Down
Loading