diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 188 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 61 |
2 files changed, 249 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 1bf44127f23..1eb2ec45dbe 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -31,6 +31,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" +#include "llvm/ADT/PointerEmbeddedInt.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -84,9 +85,26 @@ private: CriticalsWithHintsTy; typedef llvm::DenseMap<OMPDependClause *, OperatorOffsetTy> DoacrossDependMapTy; + struct ReductionData { + SourceRange ReductionRange; + llvm::PointerUnion<const Expr *, + llvm::PointerEmbeddedInt<BinaryOperatorKind>> + ReductionOp; + ReductionData() = default; + void set(BinaryOperatorKind BO, SourceRange RR) { + ReductionRange = RR; + ReductionOp = BO; + } + void set(const Expr *RefExpr, SourceRange RR) { + ReductionRange = RR; + ReductionOp = RefExpr; + } + }; + typedef llvm::DenseMap<ValueDecl *, ReductionData> DeclReductionMapTy; struct SharingMapTy final { DeclSAMapTy SharingMap; + DeclReductionMapTy ReductionMap; AlignedMapTy AlignedMap; MappedExprComponentsTy MappedExprComponents; LoopControlVariablesMapTy LCVMap; @@ -221,6 +239,21 @@ public: void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A, DeclRefExpr *PrivateCopy = nullptr); + /// Adds additional information for the reduction items with the reduction id + /// represented as an operator. + void addReductionData(ValueDecl *D, SourceRange SR, BinaryOperatorKind BOK); + /// Adds additional information for the reduction items with the reduction id + /// represented as reduction identifier. + void addReductionData(ValueDecl *D, SourceRange SR, const Expr *ReductionRef); + /// Returns the location and reduction operation from the innermost parent + /// region for the given \p D. + bool getTopMostReductionData(ValueDecl *D, SourceRange &SR, + BinaryOperatorKind &BOK); + /// Returns the location and reduction operation from the innermost parent + /// region for the given \p D. + bool getTopMostReductionData(ValueDecl *D, SourceRange &SR, + const Expr *&ReductionRef); + /// \brief Returns data sharing attributes from top of the stack for the /// specified declaration. DSAVarData getTopDSA(ValueDecl *D, bool FromParent); @@ -709,6 +742,81 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A, } } +void DSAStackTy::addReductionData(ValueDecl *D, SourceRange SR, + BinaryOperatorKind BOK) { + D = getCanonicalDecl(D); + assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); + auto &Data = Stack.back().first.back().SharingMap[D]; + assert( + Data.Attributes == OMPC_reduction && + "Additional reduction info may be specified only for reduction items."); + auto &ReductionData = Stack.back().first.back().ReductionMap[D]; + assert(ReductionData.ReductionRange.isInvalid() && + "Additional reduction info may be specified only once for reduction " + "items."); + ReductionData.set(BOK, SR); +} + +void DSAStackTy::addReductionData(ValueDecl *D, SourceRange SR, + const Expr *ReductionRef) { + D = getCanonicalDecl(D); + assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); + auto &Data = Stack.back().first.back().SharingMap[D]; + assert( + Data.Attributes == OMPC_reduction && + "Additional reduction info may be specified only for reduction items."); + auto &ReductionData = Stack.back().first.back().ReductionMap[D]; + assert(ReductionData.ReductionRange.isInvalid() && + "Additional reduction info may be specified only once for reduction " + "items."); + ReductionData.set(ReductionRef, SR); +} + +bool DSAStackTy::getTopMostReductionData(ValueDecl *D, SourceRange &SR, + BinaryOperatorKind &BOK) { + D = getCanonicalDecl(D); + assert(!isStackEmpty() && Stack.back().first.size() > 1 && + "Data-sharing attributes stack is empty or has only 1 region."); + for (auto I = std::next(Stack.back().first.rbegin(), 0), + E = Stack.back().first.rend(); + I != E; std::advance(I, 1)) { + auto &Data = I->SharingMap[D]; + if (Data.Attributes != OMPC_reduction) + continue; + auto &ReductionData = I->ReductionMap[D]; + if (!ReductionData.ReductionOp || + ReductionData.ReductionOp.is<const Expr *>()) + return false; + SR = ReductionData.ReductionRange; + BOK = ReductionData.ReductionOp + .get<llvm::PointerEmbeddedInt<BinaryOperatorKind>>(); + return true; + } + return false; +} + +bool DSAStackTy::getTopMostReductionData(ValueDecl *D, SourceRange &SR, + const Expr *&ReductionRef) { + D = getCanonicalDecl(D); + assert(!isStackEmpty() && Stack.back().first.size() > 1 && + "Data-sharing attributes stack is empty or has only 1 region."); + for (auto I = std::next(Stack.back().first.rbegin(), 0), + E = Stack.back().first.rend(); + I != E; std::advance(I, 1)) { + auto &Data = I->SharingMap[D]; + if (Data.Attributes != OMPC_reduction) + continue; + auto &ReductionData = I->ReductionMap[D]; + if (!ReductionData.ReductionOp || + !ReductionData.ReductionOp.is<const Expr *>()) + return false; + SR = ReductionData.ReductionRange; + ReductionRef = ReductionData.ReductionOp.get<const Expr *>(); + return true; + } + return false; +} + bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) { D = D->getCanonicalDecl(); if (!isStackEmpty() && Stack.back().first.size() > 1) { @@ -6853,6 +6961,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_shared: case OMPC_reduction: case OMPC_task_reduction: + case OMPC_in_reduction: case OMPC_linear: case OMPC_aligned: case OMPC_copyin: @@ -7157,6 +7266,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_lastprivate: case OMPC_reduction: case OMPC_task_reduction: + case OMPC_in_reduction: case OMPC_linear: case OMPC_default: case OMPC_proc_bind: @@ -7473,6 +7583,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_shared: case OMPC_reduction: case OMPC_task_reduction: + case OMPC_in_reduction: case OMPC_linear: case OMPC_aligned: case OMPC_copyin: @@ -7631,6 +7742,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_shared: case OMPC_reduction: case OMPC_task_reduction: + case OMPC_in_reduction: case OMPC_linear: case OMPC_aligned: case OMPC_copyin: @@ -7829,6 +7941,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_shared: case OMPC_reduction: case OMPC_task_reduction: + case OMPC_in_reduction: case OMPC_linear: case OMPC_aligned: case OMPC_copyin: @@ -7946,6 +8059,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause( EndLoc, ReductionIdScopeSpec, ReductionId); break; + case OMPC_in_reduction: + Res = + ActOnOpenMPInReductionClause(VarList, StartLoc, LParenLoc, ColonLoc, + EndLoc, ReductionIdScopeSpec, ReductionId); + break; case OMPC_linear: Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc, LinKind, DepLinMapLoc, ColonLoc, EndLoc); @@ -9428,6 +9546,51 @@ static bool ActOnOMPReductionKindClause( continue; } + // OpenMP [2.15.4.6, Restrictions, p.2] + // A list item that appears in an in_reduction clause of a task construct + // must appear in a task_reduction clause of a construct associated with a + // taskgroup region that includes the participating task in its taskgroup + // set. The construct associated with the innermost region that meets this + // condition must specify the same reduction-identifier as the in_reduction + // clause. + if (ClauseKind == OMPC_in_reduction) { + DVar = Stack->hasDSA( + D, [](OpenMPClauseKind K) { return K != OMPC_unknown; }, + [](OpenMPDirectiveKind K) { return K == OMPD_taskgroup; }, + /*FromParent=*/true); + if (DVar.CKind != OMPC_reduction || DVar.DKind != OMPD_taskgroup) { + S.Diag(ELoc, diag::err_omp_in_reduction_not_task_reduction); + continue; + } + SourceRange ParentSR; + BinaryOperatorKind ParentBOK; + const Expr *ParentReductionOp; + bool IsParentBOK = Stack->getTopMostReductionData(D, ParentSR, ParentBOK); + bool IsParentReductionOp = + Stack->getTopMostReductionData(D, ParentSR, ParentReductionOp); + if ((DeclareReductionRef.isUnset() && IsParentReductionOp) || + (DeclareReductionRef.isUsable() && IsParentBOK) || BOK != ParentBOK || + IsParentReductionOp) { + bool EmitError = true; + if (IsParentReductionOp && DeclareReductionRef.isUsable()) { + llvm::FoldingSetNodeID RedId, ParentRedId; + ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true); + DeclareReductionRef.get()->Profile(RedId, Context, + /*Canonical=*/true); + EmitError = RedId != ParentRedId; + } + if (EmitError) { + S.Diag(ReductionId.getLocStart(), + diag::err_omp_reduction_identifier_mismatch) + << ReductionIdRange << RefExpr->getSourceRange(); + S.Diag(ParentSR.getBegin(), + diag::note_omp_previous_reduction_identifier) + << ParentSR << DVar.RefExpr->getSourceRange(); + continue; + } + } + } + DeclRefExpr *Ref = nullptr; Expr *VarsExpr = RefExpr->IgnoreParens(); if (!VD && !S.CurContext->isDependentContext()) { @@ -9465,6 +9628,10 @@ static bool ActOnOMPReductionKindClause( // All reduction items are still marked as reduction (to do not increase // code base size). Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref); + if (DeclareReductionRef.isUsable()) + Stack->addReductionData(D, ReductionIdRange, DeclareReductionRef.get()); + else + Stack->addReductionData(D, ReductionIdRange, BOK); RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get()); } return RD.Vars.empty(); @@ -9512,6 +9679,27 @@ OMPClause *Sema::ActOnOpenMPTaskReductionClause( buildPostUpdate(*this, RD.ExprPostUpdates)); } +OMPClause *Sema::ActOnOpenMPInReductionClause( + ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, + CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, + ArrayRef<Expr *> UnresolvedReductions) { + ReductionData RD(VarList.size()); + + if (ActOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList, + StartLoc, LParenLoc, ColonLoc, EndLoc, + ReductionIdScopeSpec, ReductionId, + UnresolvedReductions, RD)) + return nullptr; + + return OMPInReductionClause::Create( + Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars, + ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, + RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, + buildPreInits(Context, RD.ExprCaptures), + buildPostUpdate(*this, RD.ExprPostUpdates)); +} + bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc) { if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) || diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 91da9f88c59..ee67e15b9ae 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1666,6 +1666,22 @@ public: ReductionId, UnresolvedReductions); } + /// Build a new OpenMP 'in_reduction' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause * + RebuildOMPInReductionClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, + CXXScopeSpec &ReductionIdScopeSpec, + const DeclarationNameInfo &ReductionId, + ArrayRef<Expr *> UnresolvedReductions) { + return getSema().ActOnOpenMPInReductionClause( + VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, ReductionIdScopeSpec, + ReductionId, UnresolvedReductions); + } + /// \brief Build a new OpenMP 'linear' clause. /// /// By default, performs semantic analysis to build the new OpenMP clause. @@ -8461,6 +8477,51 @@ OMPClause *TreeTransform<Derived>::TransformOMPTaskReductionClause( template <typename Derived> OMPClause * +TreeTransform<Derived>::TransformOMPInReductionClause(OMPInReductionClause *C) { + llvm::SmallVector<Expr *, 16> Vars; + Vars.reserve(C->varlist_size()); + for (auto *VE : C->varlists()) { + ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE)); + if (EVar.isInvalid()) + return nullptr; + Vars.push_back(EVar.get()); + } + CXXScopeSpec ReductionIdScopeSpec; + ReductionIdScopeSpec.Adopt(C->getQualifierLoc()); + + DeclarationNameInfo NameInfo = C->getNameInfo(); + if (NameInfo.getName()) { + NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo); + if (!NameInfo.getName()) + return nullptr; + } + // Build a list of all UDR decls with the same names ranged by the Scopes. + // The Scope boundary is a duplication of the previous decl. + llvm::SmallVector<Expr *, 16> UnresolvedReductions; + for (auto *E : C->reduction_ops()) { + // Transform all the decls. + if (E) { + auto *ULE = cast<UnresolvedLookupExpr>(E); + UnresolvedSet<8> Decls; + for (auto *D : ULE->decls()) { + NamedDecl *InstD = + cast<NamedDecl>(getDerived().TransformDecl(E->getExprLoc(), D)); + Decls.addDecl(InstD, InstD->getAccess()); + } + UnresolvedReductions.push_back(UnresolvedLookupExpr::Create( + SemaRef.Context, /*NamingClass=*/nullptr, + ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo, + /*ADL=*/true, ULE->isOverloaded(), Decls.begin(), Decls.end())); + } else + UnresolvedReductions.push_back(nullptr); + } + return getDerived().RebuildOMPInReductionClause( + Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(), + C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions); +} + +template <typename Derived> +OMPClause * TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) { llvm::SmallVector<Expr *, 16> Vars; Vars.reserve(C->varlist_size()); |