diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2017-07-21 18:48:21 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2017-07-21 18:48:21 +0000 |
commit | fa312f33f8409f43fab488ec983546b275199ab7 (patch) | |
tree | f2710f90420f0587cc1a681142001d6942d29999 /clang/lib | |
parent | 6ab9ea961435aa5341460f120b2c40abbf8528f7 (diff) | |
download | bcm5719-llvm-fa312f33f8409f43fab488ec983546b275199ab7.tar.gz bcm5719-llvm-fa312f33f8409f43fab488ec983546b275199ab7.zip |
[OPENMP] Initial support for 'in_reduction' clause.
Parsing/sema analysis for 'in_reduction' clause for task-based
directives.
llvm-svn: 308768
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/OpenMPClause.cpp | 57 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 22 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Basic/OpenMPKinds.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 188 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 61 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 37 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 19 |
10 files changed, 430 insertions, 12 deletions
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 2c4d159a1bc..9dcf5c19201 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -48,6 +48,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { return static_cast<const OMPReductionClause *>(C); case OMPC_task_reduction: return static_cast<const OMPTaskReductionClause *>(C); + case OMPC_in_reduction: + return static_cast<const OMPInReductionClause *>(C); case OMPC_linear: return static_cast<const OMPLinearClause *>(C); case OMPC_if: @@ -116,6 +118,8 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) return static_cast<const OMPReductionClause *>(C); case OMPC_task_reduction: return static_cast<const OMPTaskReductionClause *>(C); + case OMPC_in_reduction: + return static_cast<const OMPInReductionClause *>(C); case OMPC_linear: return static_cast<const OMPLinearClause *>(C); case OMPC_schedule: @@ -562,6 +566,59 @@ OMPTaskReductionClause *OMPTaskReductionClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPTaskReductionClause(N); } +void OMPInReductionClause::setPrivates(ArrayRef<Expr *> Privates) { + assert(Privates.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(Privates.begin(), Privates.end(), varlist_end()); +} + +void OMPInReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) { + assert( + LHSExprs.size() == varlist_size() && + "Number of LHS expressions is not the same as the preallocated buffer"); + std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end()); +} + +void OMPInReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) { + assert( + RHSExprs.size() == varlist_size() && + "Number of RHS expressions is not the same as the preallocated buffer"); + std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end()); +} + +void OMPInReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) { + assert(ReductionOps.size() == varlist_size() && "Number of in reduction " + "expressions is not the same " + "as the preallocated buffer"); + std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end()); +} + +OMPInReductionClause *OMPInReductionClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, + ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs, + ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit, + Expr *PostUpdate) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size())); + OMPInReductionClause *Clause = new (Mem) OMPInReductionClause( + StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo); + Clause->setVarRefs(VL); + Clause->setPrivates(Privates); + Clause->setLHSExprs(LHSExprs); + Clause->setRHSExprs(RHSExprs); + Clause->setReductionOps(ReductionOps); + Clause->setPreInitStmt(PreInit); + Clause->setPostUpdateExpr(PostUpdate); + return Clause; +} + +OMPInReductionClause *OMPInReductionClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N)); + return new (Mem) OMPInReductionClause(N); +} + OMPFlushClause *OMPFlushClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 5ebaa32b49c..f4418c92406 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -859,6 +859,28 @@ void OMPClausePrinter::VisitOMPTaskReductionClause( } } +void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) { + if (!Node->varlist_empty()) { + OS << "in_reduction("; + NestedNameSpecifier *QualifierLoc = + Node->getQualifierLoc().getNestedNameSpecifier(); + OverloadedOperatorKind OOK = + Node->getNameInfo().getName().getCXXOverloadedOperator(); + if (QualifierLoc == nullptr && OOK != OO_None) { + // Print reduction identifier in C format + OS << getOperatorSpelling(OOK); + } else { + // Use C++ format + if (QualifierLoc != nullptr) + QualifierLoc->print(OS, Policy); + OS << Node->getNameInfo(); + } + OS << ":"; + VisitOMPClauseList(Node, ' '); + OS << ")"; + } +} + void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) { if (!Node->varlist_empty()) { OS << "linear"; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index e06386018d6..a86fded2a2c 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -573,6 +573,30 @@ void OMPClauseProfiler::VisitOMPTaskReductionClause( Profiler->VisitStmt(E); } } +void OMPClauseProfiler::VisitOMPInReductionClause( + const OMPInReductionClause *C) { + Profiler->VisitNestedNameSpecifier( + C->getQualifierLoc().getNestedNameSpecifier()); + Profiler->VisitName(C->getNameInfo().getName()); + VisitOMPClauseList(C); + VistOMPClauseWithPostUpdate(C); + for (auto *E : C->privates()) { + if (E) + Profiler->VisitStmt(E); + } + for (auto *E : C->lhs_exprs()) { + if (E) + Profiler->VisitStmt(E); + } + for (auto *E : C->rhs_exprs()) { + if (E) + Profiler->VisitStmt(E); + } + for (auto *E : C->reduction_ops()) { + if (E) + Profiler->VisitStmt(E); + } +} void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) { VisitOMPClauseList(C); VistOMPClauseWithPostUpdate(C); diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 050c0cc466d..5eea4b5a5cf 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -139,6 +139,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_shared: case OMPC_reduction: case OMPC_task_reduction: + case OMPC_in_reduction: case OMPC_aligned: case OMPC_copyin: case OMPC_copyprivate: @@ -279,6 +280,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_shared: case OMPC_reduction: case OMPC_task_reduction: + case OMPC_in_reduction: case OMPC_aligned: case OMPC_copyin: case OMPC_copyprivate: @@ -851,8 +853,8 @@ bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) { bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) { return Kind == OMPC_private || Kind == OMPC_firstprivate || Kind == OMPC_lastprivate || Kind == OMPC_linear || - Kind == OMPC_reduction || - Kind == OMPC_task_reduction; // TODO add next clauses like 'reduction'. + Kind == OMPC_reduction || Kind == OMPC_task_reduction || + Kind == OMPC_in_reduction; // TODO add next clauses like 'reduction'. } bool clang::isOpenMPThreadPrivate(OpenMPClauseKind Kind) { diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 6135cf31d17..b9f5d3979eb 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -3467,6 +3467,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, case OMPC_lastprivate: case OMPC_reduction: case OMPC_task_reduction: + case OMPC_in_reduction: case OMPC_safelen: case OMPC_simdlen: case OMPC_collapse: diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index d9a088595ab..353b0795f66 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -1102,7 +1102,8 @@ bool Parser::ParseOpenMPSimpleVarList( /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | /// thread_limit-clause | priority-clause | grainsize-clause | /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | -/// from-clause | is_device_ptr-clause | task_reduction-clause +/// from-clause | is_device_ptr-clause | task_reduction-clause | +/// in_reduction-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -1221,6 +1222,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_shared: case OMPC_reduction: case OMPC_task_reduction: + case OMPC_in_reduction: case OMPC_linear: case OMPC_aligned: case OMPC_copyin: @@ -1586,7 +1588,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, BalancedDelimiterTracker LinearT(*this, tok::l_paren, tok::annot_pragma_openmp_end); // Handle reduction-identifier for reduction clause. - if (Kind == OMPC_reduction || Kind == OMPC_task_reduction) { + if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || + Kind == OMPC_in_reduction) { ColonProtectionRAIIObject ColonRAII(*this); if (getLangOpts().CPlusPlus) ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec, @@ -1734,13 +1737,14 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Diag(Tok, diag::warn_pragma_expected_colon) << "map type"; } - bool IsComma = (Kind != OMPC_reduction && Kind != OMPC_task_reduction && - Kind != OMPC_depend && Kind != OMPC_map) || - (Kind == OMPC_reduction && !InvalidReductionId) || - (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown && - (!MapTypeModifierSpecified || - Data.MapTypeModifier == OMPC_MAP_always)) || - (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); + bool IsComma = + (Kind != OMPC_reduction && Kind != OMPC_task_reduction && + Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || + (Kind == OMPC_reduction && !InvalidReductionId) || + (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown && + (!MapTypeModifierSpecified || + Data.MapTypeModifier == OMPC_MAP_always)) || + (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && Tok.isNot(tok::annot_pragma_openmp_end))) { @@ -1796,7 +1800,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, } /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', -/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction' or 'task_reduction'. +/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or +/// 'in_reduction'. /// /// private-clause: /// 'private' '(' list ')' @@ -1814,6 +1819,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, /// 'reduction' '(' reduction-identifier ':' list ')' /// task_reduction-clause: /// 'task_reduction' '(' reduction-identifier ':' list ')' +/// in_reduction-clause: +/// 'in_reduction' '(' reduction-identifier ':' list ')' /// copyprivate-clause: /// 'copyprivate' '(' list ')' /// flush-clause: 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()); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 21adcddd3a4..272d30260cf 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1837,6 +1837,9 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_task_reduction: C = OMPTaskReductionClause::CreateEmpty(Context, Reader->Record.readInt()); break; + case OMPC_in_reduction: + C = OMPInReductionClause::CreateEmpty(Context, Reader->Record.readInt()); + break; case OMPC_linear: C = OMPLinearClause::CreateEmpty(Context, Reader->Record.readInt()); break; @@ -2175,6 +2178,40 @@ void OMPClauseReader::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) { C->setReductionOps(Vars); } +void OMPClauseReader::VisitOMPInReductionClause(OMPInReductionClause *C) { + VisitOMPClauseWithPostUpdate(C); + C->setLParenLoc(Reader->ReadSourceLocation()); + C->setColonLoc(Reader->ReadSourceLocation()); + NestedNameSpecifierLoc NNSL = Reader->Record.readNestedNameSpecifierLoc(); + DeclarationNameInfo DNI; + Reader->ReadDeclarationNameInfo(DNI); + C->setQualifierLoc(NNSL); + C->setNameInfo(DNI); + + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned I = 0; I != NumVars; ++I) + Vars.push_back(Reader->Record.readSubExpr()); + C->setVarRefs(Vars); + Vars.clear(); + for (unsigned I = 0; I != NumVars; ++I) + Vars.push_back(Reader->Record.readSubExpr()); + C->setPrivates(Vars); + Vars.clear(); + for (unsigned I = 0; I != NumVars; ++I) + Vars.push_back(Reader->Record.readSubExpr()); + C->setLHSExprs(Vars); + Vars.clear(); + for (unsigned I = 0; I != NumVars; ++I) + Vars.push_back(Reader->Record.readSubExpr()); + C->setRHSExprs(Vars); + Vars.clear(); + for (unsigned I = 0; I != NumVars; ++I) + Vars.push_back(Reader->Record.readSubExpr()); + C->setReductionOps(Vars); +} + void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) { VisitOMPClauseWithPostUpdate(C); C->setLParenLoc(Reader->ReadSourceLocation()); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index ae2e0b88c31..f8e41eda53a 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1982,6 +1982,25 @@ void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) { Record.AddStmt(E); } +void OMPClauseWriter::VisitOMPInReductionClause(OMPInReductionClause *C) { + Record.push_back(C->varlist_size()); + VisitOMPClauseWithPostUpdate(C); + Record.AddSourceLocation(C->getLParenLoc()); + Record.AddSourceLocation(C->getColonLoc()); + Record.AddNestedNameSpecifierLoc(C->getQualifierLoc()); + Record.AddDeclarationNameInfo(C->getNameInfo()); + for (auto *VE : C->varlists()) + Record.AddStmt(VE); + for (auto *VE : C->privates()) + Record.AddStmt(VE); + for (auto *E : C->lhs_exprs()) + Record.AddStmt(E); + for (auto *E : C->rhs_exprs()) + Record.AddStmt(E); + for (auto *E : C->reduction_ops()) + Record.AddStmt(E); +} + void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) { Record.push_back(C->varlist_size()); VisitOMPClauseWithPostUpdate(C); |