Author: CHANDRA GHALE Date: 2025-03-21T14:19:08+05:30 New Revision: 6da8f5661961416c704061a9d401ea6ae480cbc1
URL: https://github.com/llvm/llvm-project/commit/6da8f5661961416c704061a9d401ea6ae480cbc1 DIFF: https://github.com/llvm/llvm-project/commit/6da8f5661961416c704061a9d401ea6ae480cbc1.diff LOG: [OpenMP 6.0] Parse/Sema support for reduction over private variable with reduction clause. (#129938) Initial Parse/Sema support for reduction over private variable with reduction clause. Section 7.6.10 in in OpenMP 6.0 spec. - list item in a reduction clause can now be private in the enclosing context. - Added support for _original-sharing-modifier_ with reduction clause. --------- Co-authored-by: Chandra Ghale <gh...@pe31.hpc.amslabs.hpecorp.net> Added: Modified: clang/docs/OpenMPSupport.rst clang/include/clang/AST/OpenMPClause.h clang/include/clang/Basic/OpenMPKinds.def clang/include/clang/Basic/OpenMPKinds.h clang/include/clang/Sema/SemaOpenMP.h clang/lib/AST/OpenMPClause.cpp clang/lib/Parse/ParseOpenMP.cpp clang/lib/Sema/SemaOpenMP.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/test/OpenMP/for_reduction_messages.cpp clang/test/OpenMP/for_simd_reduction_messages.cpp clang/test/OpenMP/parallel_for_reduction_messages.cpp clang/test/OpenMP/sections_reduction_messages.cpp Removed: ################################################################################ diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst index dcee1db2a18e0..83d90ffef6bc7 100644 --- a/clang/docs/OpenMPSupport.rst +++ b/clang/docs/OpenMPSupport.rst @@ -405,8 +405,8 @@ implementation. | Extensions to depobj construct | :none:`unclaimed` | :none:`unclaimed` | | +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ | Extensions to atomic construct | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Private reductions | :none:`unclaimed` | :none:`unclaimed` | | ++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +| Private reductions | :part:`partial` | :none:`unclaimed` | Parse/Sema:https://github.com/llvm/llvm-project/pull/129938 | +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ | Self maps | :part:`partial` | :none:`unclaimed` | parsing/sema done: https://github.com/llvm/llvm-project/pull/129888 | +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 46f34a7302847..572e62249b46f 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -3701,7 +3701,7 @@ class OMPSharedClause final class OMPReductionClause final : public OMPVarListClause<OMPReductionClause>, public OMPClauseWithPostUpdate, - private llvm::TrailingObjects<OMPReductionClause, Expr *> { + private llvm::TrailingObjects<OMPReductionClause, Expr *, bool> { friend class OMPClauseReader; friend OMPVarListClause; friend TrailingObjects; @@ -3709,6 +3709,10 @@ class OMPReductionClause final /// Reduction modifier. OpenMPReductionClauseModifier Modifier = OMPC_REDUCTION_unknown; + /// Original Sharing modifier. + OpenMPOriginalSharingModifier OriginalSharingModifier = + OMPC_ORIGINAL_SHARING_default; + /// Reduction modifier location. SourceLocation ModifierLoc; @@ -3734,12 +3738,14 @@ class OMPReductionClause final OMPReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, - OpenMPReductionClauseModifier Modifier, unsigned N, - NestedNameSpecifierLoc QualifierLoc, + OpenMPReductionClauseModifier Modifier, + OpenMPOriginalSharingModifier OriginalSharingModifier, + unsigned N, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) : OMPVarListClause<OMPReductionClause>(llvm::omp::OMPC_reduction, StartLoc, LParenLoc, EndLoc, N), OMPClauseWithPostUpdate(this), Modifier(Modifier), + OriginalSharingModifier(OriginalSharingModifier), ModifierLoc(ModifierLoc), ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {} @@ -3755,6 +3761,11 @@ class OMPReductionClause final /// Sets reduction modifier. void setModifier(OpenMPReductionClauseModifier M) { Modifier = M; } + /// Sets Original Sharing modifier. + void setOriginalSharingModifier(OpenMPOriginalSharingModifier M) { + OriginalSharingModifier = M; + } + /// Sets location of the modifier. void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } @@ -3800,6 +3811,31 @@ class OMPReductionClause final /// reduction copies. void setRHSExprs(ArrayRef<Expr *> RHSExprs); + /// Set the list private reduction flags + void setPrivateVariableReductionFlags(ArrayRef<bool> Flags) { + assert(Flags.size() == varlist_size() && + "Number of private flags does not match vars"); + llvm::copy(Flags, getTrailingObjects<bool>()); + } + + /// Get the list of help private variable reduction flags + MutableArrayRef<bool> getPrivateVariableReductionFlags() { + return MutableArrayRef(getTrailingObjects<bool>(), varlist_size()); + } + ArrayRef<bool> getPrivateVariableReductionFlags() const { + return ArrayRef(getTrailingObjects<bool>(), varlist_size()); + } + + /// Returns the number of Expr* objects in trailing storage + size_t numTrailingObjects(OverloadToken<Expr *>) const { + return varlist_size() * (Modifier == OMPC_REDUCTION_inscan ? 8 : 5); + } + + /// Returns the number of bool flags in trailing storage + size_t numTrailingObjects(OverloadToken<bool>) const { + return varlist_size(); + } + /// Get the list of helper destination expressions. MutableArrayRef<Expr *> getRHSExprs() { return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size()); @@ -3897,6 +3933,7 @@ class OMPReductionClause final /// region with this clause. /// \param PostUpdate Expression that must be executed after exit from the /// OpenMP region with this clause. + /// \param IsPrivateVarReduction array for private variable reduction flags static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, @@ -3906,7 +3943,8 @@ class OMPReductionClause final ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, ArrayRef<Expr *> CopyOps, ArrayRef<Expr *> CopyArrayTemps, ArrayRef<Expr *> CopyArrayElems, - Stmt *PreInit, Expr *PostUpdate); + Stmt *PreInit, Expr *PostUpdate, ArrayRef<bool> IsPrivateVarReduction, + OpenMPOriginalSharingModifier OriginalSharingModifier); /// Creates an empty clause with the place for \a N variables. /// @@ -3920,6 +3958,11 @@ class OMPReductionClause final /// Returns modifier. OpenMPReductionClauseModifier getModifier() const { return Modifier; } + /// Returns Original Sharing Modifier. + OpenMPOriginalSharingModifier getOriginalSharingModifier() const { + return OriginalSharingModifier; + } + /// Returns modifier location. SourceLocation getModifierLoc() const { return ModifierLoc; } @@ -3937,6 +3980,11 @@ class OMPReductionClause final using helper_expr_range = llvm::iterator_range<helper_expr_iterator>; using helper_expr_const_range = llvm::iterator_range<helper_expr_const_iterator>; + using helper_flag_iterator = MutableArrayRef<bool>::iterator; + using helper_flag_const_iterator = ArrayRef<bool>::iterator; + using helper_flag_range = llvm::iterator_range<helper_flag_iterator>; + using helper_flag_const_range = + llvm::iterator_range<helper_flag_const_iterator>; helper_expr_const_range privates() const { return helper_expr_const_range(getPrivates().begin(), getPrivates().end()); @@ -3962,6 +4010,16 @@ class OMPReductionClause final return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end()); } + helper_flag_const_range private_var_reduction_flags() const { + return helper_flag_const_range(getPrivateVariableReductionFlags().begin(), + getPrivateVariableReductionFlags().end()); + } + + helper_flag_range private_var_reduction_flags() { + return helper_flag_range(getPrivateVariableReductionFlags().begin(), + getPrivateVariableReductionFlags().end()); + } + helper_expr_const_range reduction_ops() const { return helper_expr_const_range(getReductionOps().begin(), getReductionOps().end()); diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index c4a2cca731607..b0de65df7e397 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -71,6 +71,9 @@ #ifndef OPENMP_REDUCTION_MODIFIER #define OPENMP_REDUCTION_MODIFIER(Name) #endif +#ifndef OPENMP_ORIGINAL_SHARING_MODIFIER +#define OPENMP_ORIGINAL_SHARING_MODIFIER(Name) +#endif #ifndef OPENMP_ADJUST_ARGS_KIND #define OPENMP_ADJUST_ARGS_KIND(Name) #endif @@ -203,6 +206,11 @@ OPENMP_REDUCTION_MODIFIER(default) OPENMP_REDUCTION_MODIFIER(inscan) OPENMP_REDUCTION_MODIFIER(task) +// OpenMP 6.0 modifiers for 'reduction' clause. +OPENMP_ORIGINAL_SHARING_MODIFIER(shared) +OPENMP_ORIGINAL_SHARING_MODIFIER(private) +OPENMP_ORIGINAL_SHARING_MODIFIER(default) + // Adjust-op kinds for the 'adjust_args' clause. OPENMP_ADJUST_ARGS_KIND(nothing) OPENMP_ADJUST_ARGS_KIND(need_device_ptr) @@ -234,6 +242,7 @@ OPENMP_DOACROSS_MODIFIER(source_omp_cur_iteration) #undef OPENMP_ADJUST_ARGS_KIND #undef OPENMP_REDUCTION_MODIFIER #undef OPENMP_DEVICE_MODIFIER +#undef OPENMP_ORIGINAL_SHARING_MODIFIER #undef OPENMP_ORDER_KIND #undef OPENMP_ORDER_MODIFIER #undef OPENMP_LASTPRIVATE_KIND diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h index e80bce34a97e0..6ca9f9c550285 100644 --- a/clang/include/clang/Basic/OpenMPKinds.h +++ b/clang/include/clang/Basic/OpenMPKinds.h @@ -190,6 +190,13 @@ enum OpenMPReductionClauseModifier { OMPC_REDUCTION_unknown, }; +/// OpenMP 6.0 original sharing modifiers +enum OpenMPOriginalSharingModifier { +#define OPENMP_ORIGINAL_SHARING_MODIFIER(Name) OMPC_ORIGINAL_SHARING_##Name, +#include "clang/Basic/OpenMPKinds.def" + OMPC_ORIGINAL_SHARING_unknown, +}; + /// OpenMP adjust-op kinds for 'adjust_args' clause. enum OpenMPAdjustArgsOpKind { #define OPENMP_ADJUST_ARGS_KIND(Name) OMPC_ADJUST_ARGS_##Name, diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h index 7fc9b64f0ae65..6498390fe96f7 100644 --- a/clang/include/clang/Sema/SemaOpenMP.h +++ b/clang/include/clang/Sema/SemaOpenMP.h @@ -1146,6 +1146,7 @@ class SemaOpenMP : public SemaBase { DeclarationNameInfo ReductionOrMapperId; int ExtraModifier = -1; ///< Additional modifier for linear, map, depend or ///< lastprivate clause. + int OriginalSharingModifier = 0; // Default is shared SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers> MapTypeModifiers; SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers> @@ -1155,6 +1156,7 @@ class SemaOpenMP : public SemaBase { SmallVector<SourceLocation, NumberOfOMPMotionModifiers> MotionModifiersLoc; bool IsMapTypeImplicit = false; SourceLocation ExtraModifierLoc; + SourceLocation OriginalSharingModifierLoc; SourceLocation OmpAllMemoryLoc; SourceLocation StepModifierLoc; /// 'step' modifier location for linear clause @@ -1164,6 +1166,12 @@ class SemaOpenMP : public SemaBase { SmallVector<SourceLocation, NumberOfOMPAllocateClauseModifiers> AllocClauseModifiersLoc; Expr *AllocateAlignment = nullptr; + struct OpenMPReductionClauseModifiers { + int ExtraModifier; + int OriginalSharingModifier; + OpenMPReductionClauseModifiers(int Extra, int Original) + : ExtraModifier(Extra), OriginalSharingModifier(Original) {} + }; }; OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind, @@ -1212,7 +1220,8 @@ class SemaOpenMP : public SemaBase { SourceLocation EndLoc); /// Called on well-formed 'reduction' clause. OMPClause *ActOnOpenMPReductionClause( - ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier, + ArrayRef<Expr *> VarList, + OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 648a273c4a2c6..2226791a70b6e 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -799,12 +799,14 @@ OMPReductionClause *OMPReductionClause::Create( ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, ArrayRef<Expr *> CopyOps, ArrayRef<Expr *> CopyArrayTemps, - ArrayRef<Expr *> CopyArrayElems, Stmt *PreInit, Expr *PostUpdate) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>( - (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * VL.size())); - auto *Clause = new (Mem) - OMPReductionClause(StartLoc, LParenLoc, ModifierLoc, EndLoc, ColonLoc, - Modifier, VL.size(), QualifierLoc, NameInfo); + ArrayRef<Expr *> CopyArrayElems, Stmt *PreInit, Expr *PostUpdate, + ArrayRef<bool> IsPrivateVarReduction, + OpenMPOriginalSharingModifier OrignalSharingModifier) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *, bool>( + (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * VL.size(), VL.size())); + auto *Clause = new (Mem) OMPReductionClause( + StartLoc, LParenLoc, ModifierLoc, EndLoc, ColonLoc, Modifier, + OrignalSharingModifier, VL.size(), QualifierLoc, NameInfo); Clause->setVarRefs(VL); Clause->setPrivates(Privates); Clause->setLHSExprs(LHSExprs); @@ -812,6 +814,7 @@ OMPReductionClause *OMPReductionClause::Create( Clause->setReductionOps(ReductionOps); Clause->setPreInitStmt(PreInit); Clause->setPostUpdateExpr(PostUpdate); + Clause->setPrivateVariableReductionFlags(IsPrivateVarReduction); if (Modifier == OMPC_REDUCTION_inscan) { Clause->setInscanCopyOps(CopyOps); Clause->setInscanCopyArrayTemps(CopyArrayTemps); @@ -830,8 +833,8 @@ OMPReductionClause *OMPReductionClause::Create( OMPReductionClause * OMPReductionClause::CreateEmpty(const ASTContext &C, unsigned N, OpenMPReductionClauseModifier Modifier) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>( - (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * N)); + void *Mem = C.Allocate(totalSizeToAlloc<Expr *, bool>( + (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * N, N)); auto *Clause = new (Mem) OMPReductionClause(N); Clause->setModifier(Modifier); return Clause; diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 28386d2260a83..b0e6c2f07a1e7 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -4706,6 +4706,37 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, assert(Tok.is(tok::comma) && "Expected comma."); (void)ConsumeToken(); } + // Handle original(private / shared) Modifier + if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 && + Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" && + NextToken().is(tok::l_paren)) { + // Parse original(private) modifier. + ConsumeToken(); + BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren); + ParenT.consumeOpen(); + if (Tok.is(tok::kw_private)) { + Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private; + Data.OriginalSharingModifierLoc = Tok.getLocation(); + ConsumeToken(); + } else if (Tok.is(tok::identifier) && + (PP.getSpelling(Tok) == "shared" || + PP.getSpelling(Tok) == "default")) { + Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared; + Data.OriginalSharingModifierLoc = Tok.getLocation(); + ConsumeToken(); + } else { + Diag(Tok.getLocation(), diag::err_expected) + << "'private or shared or default'"; + SkipUntil(tok::r_paren); + return false; + } + ParenT.consumeClose(); + if (!Tok.is(tok::comma)) { + Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)"; + return false; + } + (void)ConsumeToken(); + } ColonProtectionRAIIObject ColonRAII(*this); if (getLangOpts().CPlusPlus) ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 890de834533a4..a5f12a1e077c8 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -17377,6 +17377,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, SourceLocation EndLoc = Locs.EndLoc; OMPClause *Res = nullptr; int ExtraModifier = Data.ExtraModifier; + int OriginalSharingModifier = Data.OriginalSharingModifier; SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc; SourceLocation ColonLoc = Data.ColonLoc; switch (Kind) { @@ -17400,7 +17401,9 @@ OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown && "Unexpected lastprivate modifier."); Res = ActOnOpenMPReductionClause( - VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier), + VarList, + OpenMPVarListDataTy::OpenMPReductionClauseModifiers( + ExtraModifier, OriginalSharingModifier), StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc, Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId); break; @@ -18582,14 +18585,20 @@ struct ReductionData { SmallVector<Expr *, 4> ExprPostUpdates; /// Reduction modifier. unsigned RedModifier = 0; + /// Original modifier. + unsigned OrigSharingModifier = 0; + /// Private Variable Reduction + SmallVector<bool, 8> IsPrivateVarReduction; ReductionData() = delete; /// Reserves required memory for the reduction data. - ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) { + ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0) + : RedModifier(Modifier), OrigSharingModifier(OrgModifier) { Vars.reserve(Size); Privates.reserve(Size); LHSs.reserve(Size); RHSs.reserve(Size); ReductionOps.reserve(Size); + IsPrivateVarReduction.reserve(Size); if (RedModifier == OMPC_REDUCTION_inscan) { InscanCopyOps.reserve(Size); InscanCopyArrayTemps.reserve(Size); @@ -18607,6 +18616,7 @@ struct ReductionData { LHSs.emplace_back(nullptr); RHSs.emplace_back(nullptr); ReductionOps.emplace_back(ReductionOp); + IsPrivateVarReduction.emplace_back(false); TaskgroupDescriptors.emplace_back(nullptr); if (RedModifier == OMPC_REDUCTION_inscan) { InscanCopyOps.push_back(nullptr); @@ -18617,7 +18627,7 @@ struct ReductionData { /// Stores reduction data. void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp, Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp, - Expr *CopyArrayElem) { + Expr *CopyArrayElem, bool IsPrivate) { Vars.emplace_back(Item); Privates.emplace_back(Private); LHSs.emplace_back(LHS); @@ -18633,6 +18643,7 @@ struct ReductionData { CopyArrayElem == nullptr && "Copy operation must be used for inscan reductions only."); } + IsPrivateVarReduction.emplace_back(IsPrivate); } }; } // namespace @@ -18846,6 +18857,7 @@ static bool actOnOMPReductionKindClause( FirstIter = false; SourceLocation ELoc; SourceRange ERange; + bool IsPrivate = false; Expr *SimpleRefExpr = RefExpr; auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange, /*AllowArraySection=*/true); @@ -18945,12 +18957,34 @@ static bool actOnOMPReductionKindClause( reportOriginalDsa(S, Stack, D, DVar); continue; } + // OpenMP 6.0 [ 7.6.10 ] + // Support Reduction over private variables with reduction clause. + // A list item in a reduction clause can now be private in the enclosing + // context. For orphaned constructs it is assumed to be shared unless the + // original(private) modifier appears in the clause. + DVar = Stack->getImplicitDSA(D, true); + bool IsOrphaned = false; + OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective(); + OpenMPDirectiveKind ParentDir = Stack->getParentDirective(); + // Check if the construct is orphaned (has no enclosing OpenMP context) + IsOrphaned = ParentDir == OMPD_unknown; + // OpenMP 6.0: Private DSA check + IsPrivate = + (S.getLangOpts().OpenMP > 52) && + ((isOpenMPPrivate(DVar.CKind) && DVar.CKind != OMPC_reduction && + isOpenMPWorksharingDirective(CurrDir) && + !isOpenMPParallelDirective(CurrDir) && + !isOpenMPTeamsDirective(CurrDir) && + !isOpenMPSimdDirective(ParentDir)) || + (IsOrphaned && DVar.CKind == OMPC_unknown) || + RD.OrigSharingModifier != OMPC_ORIGINAL_SHARING_shared); // OpenMP [2.14.3.6, Restrictions, p.1] // A list item that appears in a reduction clause of a worksharing // construct must be shared in the parallel regions to which any of the // worksharing regions arising from the worksharing construct bind. - if (isOpenMPWorksharingDirective(CurrDir) && + + if (!IsPrivate && isOpenMPWorksharingDirective(CurrDir) && !isOpenMPParallelDirective(CurrDir) && !isOpenMPTeamsDirective(CurrDir)) { DVar = Stack->getImplicitDSA(D, true); @@ -19446,17 +19480,23 @@ static bool actOnOMPReductionKindClause( } RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(), TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(), - TempArrayElem.get()); + TempArrayElem.get(), IsPrivate); } return RD.Vars.empty(); } OMPClause *SemaOpenMP::ActOnOpenMPReductionClause( - ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier, + ArrayRef<Expr *> VarList, + OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef<Expr *> UnresolvedReductions) { + OpenMPReductionClauseModifier Modifier = + static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier); + OpenMPOriginalSharingModifier OriginalSharingModifier = + static_cast<OpenMPOriginalSharingModifier>( + Modifiers.OriginalSharingModifier); if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) { Diag(LParenLoc, diag::err_omp_unexpected_clause_value) << getListOfPossibleValues(OMPC_reduction, /*First=*/0, @@ -19478,8 +19518,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPReductionClause( Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction); return nullptr; } - - ReductionData RD(VarList.size(), Modifier); + ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier); if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, ReductionIdScopeSpec, ReductionId, @@ -19493,7 +19532,8 @@ OMPClause *SemaOpenMP::ActOnOpenMPReductionClause( RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps, RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems, buildPreInits(getASTContext(), RD.ExprCaptures), - buildPostUpdate(SemaRef, RD.ExprPostUpdates)); + buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction, + OriginalSharingModifier); } OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause( diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index b5de98e3989ea..f0d198618e912 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1913,14 +1913,16 @@ class TreeTransform { /// Subclasses may override this routine to provide diff erent behavior. OMPClause *RebuildOMPReductionClause( ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier, + OpenMPOriginalSharingModifier OriginalSharingModifier, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef<Expr *> UnresolvedReductions) { return getSema().OpenMP().ActOnOpenMPReductionClause( - VarList, Modifier, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, - ReductionIdScopeSpec, ReductionId, UnresolvedReductions); + VarList, {Modifier, OriginalSharingModifier}, StartLoc, LParenLoc, + ModifierLoc, ColonLoc, EndLoc, ReductionIdScopeSpec, ReductionId, + UnresolvedReductions); } /// Build a new OpenMP 'task_reduction' clause. @@ -10993,8 +10995,8 @@ TreeTransform<Derived>::TransformOMPReductionClause(OMPReductionClause *C) { UnresolvedReductions.push_back(nullptr); } return getDerived().RebuildOMPReductionClause( - Vars, C->getModifier(), C->getBeginLoc(), C->getLParenLoc(), - C->getModifierLoc(), C->getColonLoc(), C->getEndLoc(), + Vars, C->getModifier(), C->getOriginalSharingModifier(), C->getBeginLoc(), + C->getLParenLoc(), C->getModifierLoc(), C->getColonLoc(), C->getEndLoc(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 2b03446aaa30e..930134bcd6501 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11758,6 +11758,12 @@ void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) { Vars.push_back(Record.readSubExpr()); C->setInscanCopyArrayElems(Vars); } + unsigned NumFlags = Record.readInt(); + SmallVector<bool, 16> Flags; + Flags.reserve(NumFlags); + for (unsigned I : llvm::seq<unsigned>(NumFlags)) + Flags.push_back(Record.readInt()); + C->setPrivateVariableReductionFlags(Flags); } void OMPClauseReader::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 9e6da4de680e2..436d5213c70dc 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -8019,6 +8019,10 @@ void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) { for (auto *E : C->copy_array_elems()) Record.AddStmt(E); } + auto PrivateFlags = C->private_var_reduction_flags(); + Record.push_back(std::distance(PrivateFlags.begin(), PrivateFlags.end())); + for (bool Flag : PrivateFlags) + Record.push_back(Flag); } void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) { diff --git a/clang/test/OpenMP/for_reduction_messages.cpp b/clang/test/OpenMP/for_reduction_messages.cpp index 1ef9726205abb..de28ba2c3be02 100644 --- a/clang/test/OpenMP/for_reduction_messages.cpp +++ b/clang/test/OpenMP/for_reduction_messages.cpp @@ -237,6 +237,7 @@ T tmain(T argc) { #pragma omp for reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} for (int i = 0; i < 10; ++i) foo(); +#if defined(_OPENMP) && (_OPENMP <= 202111) #pragma omp parallel private(fl) // expected-note 2 {{defined as private}} #pragma omp for reduction(+ : fl) // expected-error 2 {{reduction variable must be shared}} for (int i = 0; i < 10; ++i) @@ -253,7 +254,7 @@ T tmain(T argc) { #pragma omp for reduction(+ : fl) // expected-error 2 {{reduction variable must be shared}} for (int i = 0; i < 10; ++i) foo(); - +#endif return T(); } @@ -402,10 +403,12 @@ int main(int argc, char **argv) { #pragma omp for reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} for (int i = 0; i < 10; ++i) foo(); +#if defined(_OPENMP) && (_OPENMP <= 202111) #pragma omp parallel private(fl) // expected-note {{defined as private}} #pragma omp for reduction(+ : fl) // expected-error {{reduction variable must be shared}} for (int i = 0; i < 10; ++i) foo(); +#endif #pragma omp parallel private(argv) #pragma omp for reduction(+ : argv[1], get()[0]) // expected-error {{expected variable name as a base of the array subscript}} expected-error {{invalid operands to binary expression ('char *' and 'char *')}} for (int i = 0; i < 10; ++i) diff --git a/clang/test/OpenMP/for_simd_reduction_messages.cpp b/clang/test/OpenMP/for_simd_reduction_messages.cpp index 2550cf481265f..96b3805b10a86 100644 --- a/clang/test/OpenMP/for_simd_reduction_messages.cpp +++ b/clang/test/OpenMP/for_simd_reduction_messages.cpp @@ -236,6 +236,7 @@ T tmain(T argc) { #pragma omp for simd reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} for (int i = 0; i < 10; ++i) foo(); +#if defined(_OPENMP) && (_OPENMP <= 202111) #pragma omp parallel private(fl) // expected-note 2 {{defined as private}} #pragma omp for simd reduction(+ : fl) // expected-error 2 {{reduction variable must be shared}} for (int i = 0; i < 10; ++i) @@ -244,6 +245,7 @@ T tmain(T argc) { #pragma omp for simd reduction(+ : fl) // expected-error 2 {{reduction variable must be shared}} for (int i = 0; i < 10; ++i) foo(); +#endif return T(); } @@ -389,10 +391,12 @@ int main(int argc, char **argv) { #pragma omp for simd reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} for (int i = 0; i < 10; ++i) foo(); +#if defined(_OPENMP) && (_OPENMP <= 202111) #pragma omp parallel private(fl) // expected-note {{defined as private}} #pragma omp for simd reduction(+ : fl) // expected-error {{reduction variable must be shared}} for (int i = 0; i < 10; ++i) foo(); +#endif #pragma omp parallel reduction(* : fl) // expected-note {{defined as reduction}} #pragma omp for simd reduction(+ : fl) // expected-error {{reduction variable must be shared}} for (int i = 0; i < 10; ++i) diff --git a/clang/test/OpenMP/parallel_for_reduction_messages.cpp b/clang/test/OpenMP/parallel_for_reduction_messages.cpp index d4660ae43acf8..60742e5aa6b1d 100644 --- a/clang/test/OpenMP/parallel_for_reduction_messages.cpp +++ b/clang/test/OpenMP/parallel_for_reduction_messages.cpp @@ -89,10 +89,12 @@ class S5 { public: S5(int v) : a(v) {} void foo() { +#if defined(_OPENMP) && (_OPENMP <= 202111) #pragma omp parallel private(a) // expected-note {{defined as private}} #pragma omp for reduction(+:a) // expected-error {{reduction variable must be shared}} for (int i = 0; i < 10; ++i) ::foo(); +#endif #pragma omp parallel for reduction(inscan, +:a) for (int i = 0; i < 10; ++i) { #pragma omp scan inclusive(a) @@ -226,9 +228,96 @@ T tmain(T argc) { #pragma omp parallel for reduction(+ : fl) for (int i = 0; i < 10; ++i) foo(); - +#if defined(_OPENMP) && (_OPENMP >= 202411) +#pragma omp parallel private(fl) +#pragma omp for reduction(original(abcxx),+:fl) // expected-error {{private or shared or default}} expected-warning {{extra tokens at the end of '#pragma omp for'}} +for (int i = 1; i <= 10; i++) + foo(); +#endif return T(); } +namespace private_reduction_test{ +void test_original_modifier(){ +int fl; +#if defined(_OPENMP) && (_OPENMP >= 202411) +#pragma omp parallel private(fl) +#pragma omp for reduction(original(privates),+:fl) // expected-error {{private or shared or default}} expected-warning {{extra tokens at the end of '#pragma omp for'}} +for (int i = 1; i <= 10; i++) + ; + +#pragma omp parallel for reduction(original(private)+ : fl) // expected-error {{expected ',' (comma)}} expected-warning {{extra tokens at the end of '#pragma omp parallel for' }} +for (int i = 0; i < 10; ++i) + ; + +#pragma omp parallel +#pragma omp for reduction(original(shared),+:fl) +for( int i = 0; i < 10; i++) +; +#pragma omp parallel for reduction(original(private),+: fl // expected-error {{expected ')'}} expected-note {{to match this '('}} +for (int i = 0; i < 10; ++i) + ; +#pragma omp parallel firstprivate(fl) +#pragma omp for reduction(+:fl) +for( int i = 0; i < 10; i++) +; + +#pragma omp parallel +#pragma omp for reduction(original(private),+:fl) +for( int i = 0; i < 10; i++) +; + +#endif +} +void test_interaction(){ +int x; +#if defined(_OPENMP) && (_OPENMP >= 202411) +#pragma omp parallel private(x) +#pragma omp for reduction(original(private),+:x) nowait +for (int i = 0; i < 10; ++i) + x += 1; +#pragma omp parallel +{ +#pragma omp for reduction(original(private),+:) // expected-error {{expected expression}} +for( int i = 0; i < 10; ++i) +; +} +#pragma omp parallel private(x) +#pragma omp for reduction(original(private),+:x) ordered +for (int i = 0; i < 10; ++i) + x += 1; +#endif + } +template<typename T> +void test_template_reduction() { + T x = T(); +#if defined(_OPENMP) && (_OPENMP >= 202411) + #pragma omp parallel private(x) + { + #pragma omp for reduction(original(private),+:x) + for (int i = 0; i < 10; ++i) { + x += T(1); + } + } +#endif +} +struct Custom { + int value; + Custom() : value(0) {} + Custom& operator+=(const Custom& other) { + value += other.value; + return *this; + } +}; +void test_user_defined_type() { + Custom c; +#if defined(_OPENMP) && (_OPENMP >= 202411) + #pragma omp parallel private(c) + #pragma omp for reduction(original(private),+:c) + for (int i = 0; i < 10; ++i) + c.value += 1; +#endif + } +} namespace A { double x; diff --git a/clang/test/OpenMP/sections_reduction_messages.cpp b/clang/test/OpenMP/sections_reduction_messages.cpp index f93b4dd016308..42ec3ed6d58e8 100644 --- a/clang/test/OpenMP/sections_reduction_messages.cpp +++ b/clang/test/OpenMP/sections_reduction_messages.cpp @@ -268,6 +268,7 @@ T tmain(T argc) { { foo(); } +#if defined(_OPENMP) && (_OPENMP <= 202111) #pragma omp parallel private(fl) // expected-note 2 {{defined as private}} #pragma omp sections reduction(+ : fl) // expected-error 2 {{reduction variable must be shared}} { @@ -278,6 +279,7 @@ T tmain(T argc) { { foo(); } +#endif return T(); } @@ -453,11 +455,13 @@ int main(int argc, char **argv) { { foo(); } +#if defined(_OPENMP) && (_OPENMP <= 202111) #pragma omp parallel private(fl) // expected-note {{defined as private}} #pragma omp sections reduction(+ : fl) // expected-error {{reduction variable must be shared}} { foo(); } +#endif #pragma omp parallel reduction(* : fl) // expected-note {{defined as reduction}} #pragma omp sections reduction(+ : fl) // expected-error {{reduction variable must be shared}} { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits