diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/OpenMPClause.cpp | 28 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Basic/OpenMPKinds.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 91 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 28 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 8 |
9 files changed, 171 insertions, 7 deletions
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 7315d7c3cdb..f062c3e463a 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -135,6 +135,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: break; } @@ -213,6 +214,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: break; } @@ -1155,6 +1157,25 @@ OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPIsDevicePtrClause(Sizes); } +OMPNontemporalClause *OMPNontemporalClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + // Allocate space for nontemporal variables. + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); + auto *Clause = + new (Mem) OMPNontemporalClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPNontemporalClause *OMPNontemporalClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); + return new (Mem) OMPNontemporalClause(N); +} + //===----------------------------------------------------------------------===// // OpenMP clauses printing methods //===----------------------------------------------------------------------===// @@ -1648,3 +1669,10 @@ void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) { } } +void OMPClausePrinter::VisitOMPNontemporalClause(OMPNontemporalClause *Node) { + if (!Node->varlist_empty()) { + OS << "nontemporal"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index c94d2c54bae..56a65e8deb9 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -769,6 +769,9 @@ void OMPClauseProfiler::VisitOMPIsDevicePtrClause( const OMPIsDevicePtrClause *C) { VisitOMPClauseList(C); } +void OMPClauseProfiler::VisitOMPNontemporalClause(const OMPNontemporalClause *C) { + VisitOMPClauseList(C); +} } void diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 6dadfce1eb8..3222db71365 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -223,6 +223,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_reverse_offload: case OMPC_dynamic_allocators: case OMPC_match: + case OMPC_nontemporal: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -417,6 +418,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_reverse_offload: case OMPC_dynamic_allocators: case OMPC_match: + case OMPC_nontemporal: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -427,6 +429,9 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, unsigned OpenMPVersion) { assert(unsigned(DKind) <= unsigned(OMPD_unknown)); assert(CKind <= OMPC_unknown); + // Nontemporal clause is not supported in OpenMP < 5.0. + if (OpenMPVersion < 50 && CKind == OMPC_nontemporal) + return false; switch (DKind) { case OMPD_parallel: switch (CKind) { diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 3c266a5a314..e8a3790e3b5 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4206,6 +4206,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Clause is not allowed in 'omp atomic'."); } } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 9dbbcc08db8..181ed331325 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -2194,6 +2194,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_use_device_ptr: case OMPC_is_device_ptr: case OMPC_allocate: + case OMPC_nontemporal: Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); break; case OMPC_device_type: diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index afe0f1a0dcd..915bf53d06e 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -83,7 +83,7 @@ private: DeclRefExpr *PrivateCopy = nullptr; }; using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>; - using AlignedMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>; + using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>; using LCDeclInfo = std::pair<unsigned, VarDecl *>; using LoopControlVariablesMapTy = llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>; @@ -125,7 +125,8 @@ private: struct SharingMapTy { DeclSAMapTy SharingMap; DeclReductionMapTy ReductionMap; - AlignedMapTy AlignedMap; + UsedRefMapTy AlignedMap; + UsedRefMapTy NontemporalMap; MappedExprComponentsTy MappedExprComponents; LoopControlVariablesMapTy LCVMap; DefaultDataSharingAttributes DefaultAttr = DSA_unspecified; @@ -421,6 +422,10 @@ public: /// add it and return NULL; otherwise return previous occurrence's expression /// for diagnostics. const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE); + /// If 'nontemporal' declaration for given variable \a D was not seen yet, + /// add it and return NULL; otherwise return previous occurrence's expression + /// for diagnostics. + const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE); /// Register specified variable as loop control variable. void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture); @@ -1073,6 +1078,21 @@ const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D, return It->second; } +const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D, + const Expr *NewDE) { + assert(!isStackEmpty() && "Data sharing attributes stack is empty"); + D = getCanonicalDecl(D); + SharingMapTy &StackElem = getTopOfStack(); + auto It = StackElem.NontemporalMap.find(D); + if (It == StackElem.NontemporalMap.end()) { + assert(NewDE && "Unexpected nullptr expr to be added into aligned map"); + StackElem.NontemporalMap[D] = NewDE; + return nullptr; + } + assert(It->second && "Unexpected nullptr expr in the aligned map"); + return It->second; +} + void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) { assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); D = getCanonicalDecl(D); @@ -4874,6 +4894,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_nontemporal: continue; case OMPC_allocator: case OMPC_flush: @@ -5019,8 +5040,9 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( // OpenMP [2.8.1, simd construct, Restrictions] // A list-item cannot appear in more than one aligned clause. if (AlignedArgs.count(CanonPVD) > 0) { - Diag(E->getExprLoc(), diag::err_omp_aligned_twice) - << 1 << E->getSourceRange(); + Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice) + << 1 << getOpenMPClauseName(OMPC_aligned) + << E->getSourceRange(); Diag(AlignedArgs[CanonPVD]->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(OMPC_aligned); @@ -5042,8 +5064,8 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( } if (isa<CXXThisExpr>(E)) { if (AlignedThis) { - Diag(E->getExprLoc(), diag::err_omp_aligned_twice) - << 2 << E->getSourceRange(); + Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice) + << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange(); Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(OMPC_aligned); } @@ -10735,6 +10757,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Clause is not allowed."); } return Res; @@ -11445,6 +11468,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Unexpected OpenMP clause."); } return CaptureRegion; @@ -11868,6 +11892,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_dynamic_allocators: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Clause is not allowed."); } return Res; @@ -12048,6 +12073,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Clause is not allowed."); } return Res; @@ -12259,6 +12285,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Clause is not allowed."); } return Res; @@ -12426,6 +12453,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause( Res = ActOnOpenMPAllocateClause(TailExpr, VarList, StartLoc, LParenLoc, ColonLoc, EndLoc); break; + case OMPC_nontemporal: + Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -14553,7 +14583,8 @@ OMPClause *Sema::ActOnOpenMPAlignedClause( // OpenMP [2.8.1, simd construct, Restrictions] // A list-item cannot appear in more than one aligned clause. if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) { - Diag(ELoc, diag::err_omp_aligned_twice) << 0 << ERange; + Diag(ELoc, diag::err_omp_used_in_clause_twice) + << 0 << getOpenMPClauseName(OMPC_aligned) << ERange; Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(OMPC_aligned); continue; @@ -17122,3 +17153,49 @@ OMPClause *Sema::ActOnOpenMPAllocateClause( return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator, ColonLoc, EndLoc, Vars); } + +OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + SmallVector<Expr *, 8> Vars; + for (Expr *RefExpr : VarList) { + assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); + SourceLocation ELoc; + SourceRange ERange; + Expr *SimpleRefExpr = RefExpr; + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange); + if (Res.second) + // It will be analyzed later. + Vars.push_back(RefExpr); + ValueDecl *D = Res.first; + if (!D) + continue; + + auto *VD = dyn_cast<VarDecl>(D); + + // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions. + // A list-item cannot appear in more than one nontemporal clause. + if (const Expr *PrevRef = + DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) { + Diag(ELoc, diag::err_omp_used_in_clause_twice) + << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange; + Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) + << getOpenMPClauseName(OMPC_nontemporal); + continue; + } + + DeclRefExpr *Ref = nullptr; + if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext()) + Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true); + Vars.push_back((VD || !Ref || CurContext->isDependentContext()) + ? RefExpr->IgnoreParens() + : Ref); + } + + if (Vars.empty()) + return nullptr; + + return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc, + Vars); +} diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 2e4e9128506..2860db365f3 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -22,6 +22,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" +#include "clang/AST/OpenMPClause.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" @@ -2001,6 +2002,18 @@ public: MLoc, KindLoc, EndLoc); } + /// Build a new OpenMP 'nontemporal' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPNontemporalClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, + EndLoc); + } + /// Rebuild the operand to an Objective-C \@synchronized statement. /// /// By default, performs semantic analysis to build the new statement. @@ -9266,6 +9279,21 @@ TreeTransform<Derived>::TransformOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) { return getDerived().RebuildOMPIsDevicePtrClause(Vars, Locs); } +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPNontemporalClause(OMPNontemporalClause *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()); + } + return getDerived().RebuildOMPNontemporalClause( + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index a2e4e7b469c..9258a6fb126 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11698,6 +11698,9 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_allocate: C = OMPAllocateClause::CreateEmpty(Context, Record.readInt()); break; + case OMPC_nontemporal: + C = OMPNontemporalClause::CreateEmpty(Context, Record.readInt()); + break; } assert(C && "Unknown OMPClause type"); @@ -12454,3 +12457,13 @@ void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) { } C->setComponents(Components, ListSizes); } + +void OMPClauseReader::VisitOMPNontemporalClause(OMPNontemporalClause *C) { + C->setLParenLoc(Record.readSourceLocation()); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Record.readSubExpr()); + C->setVarRefs(Vars); +} diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index a8ea8563a1d..a632072d01b 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/OpenMPClause.h" #include "clang/Serialization/ASTRecordWriter.h" #include "ASTCommon.h" #include "ASTReaderInternals.h" @@ -6537,3 +6538,10 @@ void OMPClauseWriter::VisitOMPAtomicDefaultMemOrderClause( Record.AddSourceLocation(C->getLParenLoc()); Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc()); } + +void OMPClauseWriter::VisitOMPNontemporalClause(OMPNontemporalClause *C) { + Record.push_back(C->varlist_size()); + Record.AddSourceLocation(C->getLParenLoc()); + for (auto *VE : C->varlists()) + Record.AddStmt(VE); +} |