diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 22 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 12 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Basic/OpenMPKinds.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 111 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 32 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 9 |
9 files changed, 209 insertions, 7 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 8588dda363c..e6aa472c399 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1214,6 +1214,28 @@ OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPLinearClause(NumVars); } +OMPAlignedClause * +OMPAlignedClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, Expr *A) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPAlignedClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * (VL.size() + 1)); + OMPAlignedClause *Clause = new (Mem) + OMPAlignedClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setAlignment(A); + return Clause; +} + +OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C, + unsigned NumVars) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPAlignedClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * (NumVars + 1)); + return new (Mem) OMPAlignedClause(NumVars); +} + OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 0804d4089bb..c9d09b74ea9 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -677,6 +677,18 @@ void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) { } } +void OMPClausePrinter::VisitOMPAlignedClause(OMPAlignedClause *Node) { + if (!Node->varlist_empty()) { + OS << "aligned"; + VisitOMPClauseList(Node, '('); + if (Node->getAlignment() != nullptr) { + OS << ": "; + Node->getAlignment()->printPretty(OS, nullptr, Policy, 0); + } + OS << ")"; + } +} + void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) { if (!Node->varlist_empty()) { OS << "copyin"; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 9cff6d67437..d96a6116ae9 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -308,6 +308,10 @@ void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) { VisitOMPClauseList(C); Profiler->VisitStmt(C->getStep()); } +void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) { + VisitOMPClauseList(C); + Profiler->VisitStmt(C->getAlignment()); +} void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) { VisitOMPClauseList(C); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index c0142410b49..3da669c8988 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -88,6 +88,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_firstprivate: case OMPC_shared: case OMPC_linear: + case OMPC_aligned: case OMPC_copyin: break; } @@ -125,6 +126,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_firstprivate: case OMPC_shared: case OMPC_linear: + case OMPC_aligned: case OMPC_copyin: break; } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index c053aac3400..e293148b0af 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -255,7 +255,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, /// clause: /// if-clause | num_threads-clause | safelen-clause | default-clause | /// private-clause | firstprivate-clause | shared-clause | linear-clause | -/// collapse-clause +/// aligned-clause | collapse-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -304,6 +304,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_firstprivate: case OMPC_shared: case OMPC_linear: + case OMPC_aligned: case OMPC_copyin: Clause = ParseOpenMPVarListClause(CKind); break; @@ -400,6 +401,8 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { /// 'shared' '(' list ')' /// linear-clause: /// 'linear' '(' list [ ':' linear-step ] ')' +/// aligned-clause: +/// 'aligned' '(' list [ ':' alignment ] ')' /// OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); @@ -413,7 +416,7 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { SmallVector<Expr *, 5> Vars; bool IsComma = true; - const bool MayHaveTail = (Kind == OMPC_linear); + 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))) { ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); @@ -435,7 +438,7 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { Diag(Tok, diag::err_omp_expected_punc) << getOpenMPClauseName(Kind); } - // Parse ':' linear-step + // Parse ':' linear-step (or ':' alignment). Expr *TailExpr = nullptr; const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); if (MustHaveTail) { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 3a42332b407..c78c42952ca 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -57,20 +57,23 @@ private: DeclRefExpr *RefExpr; }; typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy; + typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy; struct SharingMapTy { DeclSAMapTy SharingMap; + AlignedMapTy AlignedMap; DefaultDataSharingAttributes DefaultAttr; OpenMPDirectiveKind Directive; DeclarationNameInfo DirectiveName; Scope *CurScope; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope) - : SharingMap(), DefaultAttr(DSA_unspecified), Directive(DKind), - DirectiveName(std::move(Name)), CurScope(CurScope) {} + : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified), + Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope) { + } SharingMapTy() - : SharingMap(), DefaultAttr(DSA_unspecified), Directive(OMPD_unknown), - DirectiveName(), CurScope(nullptr) {} + : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified), + Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr) {} }; typedef SmallVector<SharingMapTy, 64> StackTy; @@ -99,6 +102,11 @@ public: Stack.pop_back(); } + /// \brief If 'aligned' declaration for given variable \a D was not seen yet, + /// add it and return NULL; otherwise return previous occurence's expression + /// for diagnostics. + DeclRefExpr *addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE); + /// \brief Adds explicit data sharing attribute to the specified declaration. void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A); @@ -242,6 +250,20 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter, return getDSA(std::next(Iter), D); } +DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) { + assert(Stack.size() > 1 && "Data sharing attributes stack is empty"); + auto It = Stack.back().AlignedMap.find(D); + if (It == Stack.back().AlignedMap.end()) { + assert(NewDE && "Unexpected nullptr expr to be added into aligned map"); + Stack.back().AlignedMap[D] = NewDE; + return nullptr; + } else { + assert(It->second && "Unexpected nullptr expr in the aligned map"); + return It->second; + } + return nullptr; +} + void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) { if (A == OMPC_threadprivate) { Stack[0].SharingMap[D].Attributes = A; @@ -855,6 +877,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_firstprivate: case OMPC_shared: case OMPC_linear: + case OMPC_aligned: case OMPC_copyin: case OMPC_threadprivate: case OMPC_unknown: @@ -1025,6 +1048,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_firstprivate: case OMPC_shared: case OMPC_linear: + case OMPC_aligned: case OMPC_copyin: case OMPC_threadprivate: case OMPC_unknown: @@ -1128,6 +1152,10 @@ Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc, ColonLoc, EndLoc); break; + case OMPC_aligned: + Res = ActOnOpenMPAlignedClause(VarList, TailExpr, StartLoc, LParenLoc, + ColonLoc, EndLoc); + break; case OMPC_copyin: Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc); break; @@ -1641,6 +1669,81 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, Vars, StepExpr); } +OMPClause *Sema::ActOnOpenMPAlignedClause( + ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) { + + SmallVector<Expr *, 8> Vars; + for (auto &RefExpr : VarList) { + assert(RefExpr && "NULL expr in OpenMP aligned clause."); + if (isa<DependentScopeDeclRefExpr>(RefExpr)) { + // It will be analyzed later. + Vars.push_back(RefExpr); + continue; + } + + SourceLocation ELoc = RefExpr->getExprLoc(); + // OpenMP [2.1, C/C++] + // A list item is a variable name. + DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr); + if (!DE || !isa<VarDecl>(DE->getDecl())) { + Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange(); + continue; + } + + VarDecl *VD = cast<VarDecl>(DE->getDecl()); + + // OpenMP [2.8.1, simd construct, Restrictions] + // The type of list items appearing in the aligned clause must be + // array, pointer, reference to array, or reference to pointer. + QualType QType = DE->getType() + .getNonReferenceType() + .getUnqualifiedType() + .getCanonicalType(); + const Type *Ty = QType.getTypePtrOrNull(); + if (!Ty || (!Ty->isDependentType() && !Ty->isArrayType() && + !Ty->isPointerType())) { + Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr) + << QType << getLangOpts().CPlusPlus << RefExpr->getSourceRange(); + bool IsDecl = + VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + continue; + } + + // OpenMP [2.8.1, simd construct, Restrictions] + // A list-item cannot appear in more than one aligned clause. + if (DeclRefExpr *PrevRef = DSAStack->addUniqueAligned(VD, DE)) { + Diag(ELoc, diag::err_omp_aligned_twice) << RefExpr->getSourceRange(); + Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) + << getOpenMPClauseName(OMPC_aligned); + continue; + } + + Vars.push_back(DE); + } + + // OpenMP [2.8.1, simd construct, Description] + // The parameter of the aligned clause, alignment, must be a constant + // positive integer expression. + // If no optional parameter is specified, implementation-defined default + // alignments for SIMD instructions on the target platforms are assumed. + if (Alignment != nullptr) { + ExprResult AlignResult = + VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned); + if (AlignResult.isInvalid()) + return nullptr; + Alignment = AlignResult.get(); + } + if (Vars.empty()) + return nullptr; + + return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc, + EndLoc, Vars, Alignment); +} + OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index d2683bec649..a13c3e442e2 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1419,6 +1419,19 @@ public: ColonLoc, EndLoc); } + /// \brief Build a new OpenMP 'aligned' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPAlignedClause(ArrayRef<Expr *> VarList, Expr *Alignment, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPAlignedClause(VarList, Alignment, StartLoc, + LParenLoc, ColonLoc, EndLoc); + } + /// \brief Build a new OpenMP 'copyin' clause. /// /// By default, performs semantic analysis to build the new statement. @@ -6508,6 +6521,25 @@ TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) { template<typename Derived> OMPClause * +TreeTransform<Derived>::TransformOMPAlignedClause(OMPAlignedClause *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()); + } + ExprResult Alignment = getDerived().TransformExpr(C->getAlignment()); + if (Alignment.isInvalid()) + return nullptr; + return getDerived().RebuildOMPAlignedClause( + Vars, Alignment.get(), C->getLocStart(), C->getLParenLoc(), + C->getColonLoc(), C->getLocEnd()); +} + +template<typename Derived> +OMPClause * TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *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 89bc7fefa2f..f7031da7a36 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1703,6 +1703,9 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_linear: C = OMPLinearClause::CreateEmpty(Context, Record[Idx++]); break; + case OMPC_aligned: + C = OMPAlignedClause::CreateEmpty(Context, Record[Idx++]); + break; case OMPC_copyin: C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]); break; @@ -1790,6 +1793,18 @@ void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) { C->setStep(Reader->Reader.ReadSubExpr()); } +void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + C->setColonLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); + C->setAlignment(Reader->Reader.ReadSubExpr()); +} + void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) { C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); unsigned NumVars = C->varlist_size(); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index a79772a533e..2adf86978ab 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1737,6 +1737,15 @@ void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) { Writer->Writer.AddStmt(C->getStep()); } +void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + Writer->Writer.AddSourceLocation(C->getColonLoc(), Record); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); + Writer->Writer.AddStmt(C->getAlignment()); +} + void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) { Record.push_back(C->varlist_size()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); |