diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2016-04-12 09:35:56 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2016-04-12 09:35:56 +0000 |
commit | d93d376ba9c9f2443f3bdd61e43e7b09b762ad24 (patch) | |
tree | 483e9beb248cea3f008785cf153b4987b5ae3fc5 /clang/lib | |
parent | 65f86cd8b09b15e6ba531309325750d1a3f4af7c (diff) | |
download | bcm5719-llvm-d93d376ba9c9f2443f3bdd61e43e7b09b762ad24.tar.gz bcm5719-llvm-d93d376ba9c9f2443f3bdd61e43e7b09b762ad24.zip |
[OPENMP 4.0] Support for 'aligned' clause in 'declare simd' directive.
The aligned clause declares that the object to which each list item points is aligned to the number of bytes expressed in the optional parameter of the aligned clause.
'aligned' '(' <argument-list> [ ':' <alignment> ] ')'
The optional 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.
The special this pointer can be used as if was one of the arguments to the function in any of the linear, aligned, or uniform clauses.
llvm-svn: 266052
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 137 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 75 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 20 |
3 files changed, 165 insertions, 67 deletions
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 6112c90cacd..b41a2a86f51 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -329,63 +329,6 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { IsCorrect); } -/// Parses clauses for 'declare simd' directive. -/// clause: -/// 'inbranch' | 'notinbranch' -/// 'simdlen' '(' <expr> ')' -/// { 'uniform' '(' <argument_list> ')' } -static bool parseDeclareSimdClauses(Parser &P, - OMPDeclareSimdDeclAttr::BranchStateTy &BS, - ExprResult &SimdLen, - SmallVectorImpl<Expr *> &Uniforms) { - SourceRange BSRange; - const Token &Tok = P.getCurToken(); - bool IsError = false; - while (Tok.isNot(tok::annot_pragma_openmp_end)) { - if (Tok.isNot(tok::identifier)) - break; - OMPDeclareSimdDeclAttr::BranchStateTy Out; - IdentifierInfo *II = Tok.getIdentifierInfo(); - StringRef ClauseName = II->getName(); - // Parse 'inranch|notinbranch' clauses. - if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { - if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { - P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) - << ClauseName - << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; - IsError = true; - } - BS = Out; - BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); - P.ConsumeToken(); - } else if (ClauseName.equals("simdlen")) { - if (SimdLen.isUsable()) { - P.Diag(Tok, diag::err_omp_more_one_clause) - << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; - IsError = true; - } - P.ConsumeToken(); - SourceLocation RLoc; - SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); - if (SimdLen.isInvalid()) - IsError = true; - } else if (ClauseName.equals("uniform")) { - Parser::OpenMPVarListDataTy Data; - - P.ConsumeToken(); - if (P.ParseOpenMPVarList(OMPD_declare_simd, - getOpenMPClauseKind(ClauseName), Uniforms, Data)) - IsError = true; - } else - // TODO: add parsing of other clauses. - break; - // Skip ',' if any. - if (Tok.is(tok::comma)) - P.ConsumeToken(); - } - return IsError; -} - namespace { /// RAII that recreates function context for correct parsing of clauses of /// 'declare simd' construct. @@ -442,6 +385,75 @@ public: }; } // namespace +/// Parses clauses for 'declare simd' directive. +/// clause: +/// 'inbranch' | 'notinbranch' +/// 'simdlen' '(' <expr> ')' +/// { 'uniform' '(' <argument_list> ')' } +/// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' } +static bool parseDeclareSimdClauses(Parser &P, + OMPDeclareSimdDeclAttr::BranchStateTy &BS, + ExprResult &SimdLen, + SmallVectorImpl<Expr *> &Uniforms, + SmallVectorImpl<Expr *> &Aligneds, + SmallVectorImpl<Expr *> &Alignments) { + SourceRange BSRange; + const Token &Tok = P.getCurToken(); + bool IsError = false; + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + if (Tok.isNot(tok::identifier)) + break; + OMPDeclareSimdDeclAttr::BranchStateTy Out; + IdentifierInfo *II = Tok.getIdentifierInfo(); + StringRef ClauseName = II->getName(); + // Parse 'inranch|notinbranch' clauses. + if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { + if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { + P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) + << ClauseName + << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; + IsError = true; + } + BS = Out; + BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); + P.ConsumeToken(); + } else if (ClauseName.equals("simdlen")) { + if (SimdLen.isUsable()) { + P.Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; + IsError = true; + } + P.ConsumeToken(); + SourceLocation RLoc; + SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); + if (SimdLen.isInvalid()) + IsError = true; + } else { + OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); + if (CKind == OMPC_uniform || CKind == OMPC_aligned) { + Parser::OpenMPVarListDataTy Data; + auto *Vars = &Uniforms; + if (CKind == OMPC_aligned) { + Vars = &Aligneds; + } + + P.ConsumeToken(); + if (P.ParseOpenMPVarList(OMPD_declare_simd, + getOpenMPClauseKind(ClauseName), *Vars, Data)) + IsError = true; + if (CKind == OMPC_aligned) + Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr); + } else + // TODO: add parsing of other clauses. + break; + } + // Skip ',' if any. + if (Tok.is(tok::comma)) + P.ConsumeToken(); + } + return IsError; +} + /// Parse clauses for '#pragma omp declare simd'. Parser::DeclGroupPtrTy Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, @@ -456,7 +468,10 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, OMPDeclareSimdDeclAttr::BS_Undefined; ExprResult Simdlen; SmallVector<Expr *, 4> Uniforms; - bool IsError = parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms); + SmallVector<Expr *, 4> Aligneds; + SmallVector<Expr *, 4> Alignments; + bool IsError = parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds, + Alignments); // Need to check for extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { Diag(Tok, diag::warn_omp_extra_tokens_at_eol) @@ -466,9 +481,11 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, } // Skip the last annot_pragma_openmp_end. SourceLocation EndLoc = ConsumeToken(); - if (!IsError) + if (!IsError) { return Actions.ActOnOpenMPDeclareSimdDirective( - Ptr, BS, Simdlen.get(), Uniforms, SourceRange(Loc, EndLoc)); + Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, + SourceRange(Loc, EndLoc)); + } return Ptr; } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 43a774eec66..287bb368184 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -3192,7 +3192,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, - ArrayRef<Expr *> Uniforms, SourceRange SR) { + ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds, + ArrayRef<Expr *> Alignments, SourceRange SR) { + assert(Aligneds.size() == Alignments.size()); if (!DG || DG.get().isNull()) return DeclGroupPtrTy(); @@ -3235,9 +3237,76 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); } + // OpenMP [2.8.2, declare simd construct, Description] + // The aligned clause declares that the object to which each list item points + // is aligned to the number of bytes expressed in the optional parameter of + // the aligned clause. + // The special this pointer can be used as if was one of the arguments to the + // function in any of the linear, aligned, or uniform clauses. + // The type of list items appearing in the aligned clause must be array, + // pointer, reference to array, or reference to pointer. + llvm::DenseMap<Decl *, Expr *> AlignedArgs; + Expr *AlignedThis = nullptr; + for (auto *E : Aligneds) { + E = E->IgnoreParenImpCasts(); + if (auto *DRE = dyn_cast<DeclRefExpr>(E)) + if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { + auto *CanonPVD = PVD->getCanonicalDecl(); + if (FD->getNumParams() > PVD->getFunctionScopeIndex() && + FD->getParamDecl(PVD->getFunctionScopeIndex()) + ->getCanonicalDecl() == CanonPVD) { + // 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(AlignedArgs[CanonPVD]->getExprLoc(), + diag::note_omp_explicit_dsa) + << getOpenMPClauseName(OMPC_aligned); + continue; + } + AlignedArgs[CanonPVD] = E; + QualType QTy = PVD->getType() + .getNonReferenceType() + .getUnqualifiedType() + .getCanonicalType(); + const Type *Ty = QTy.getTypePtrOrNull(); + if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) { + Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr) + << QTy << getLangOpts().CPlusPlus << E->getSourceRange(); + Diag(PVD->getLocation(), diag::note_previous_decl) << PVD; + } + continue; + } + } + if (isa<CXXThisExpr>(E)) { + if (AlignedThis) { + Diag(E->getExprLoc(), diag::err_omp_aligned_twice) + << 2 << E->getSourceRange(); + Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa) + << getOpenMPClauseName(OMPC_aligned); + } + AlignedThis = E; + continue; + } + Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) + << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); + } + // The optional 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. + SmallVector<Expr *, 4> NewAligns; + for (auto *E : Alignments) { + ExprResult Align; + if (E) + Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned); + NewAligns.push_back(Align.get()); + } auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit( Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()), - Uniforms.size(), SR); + Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(), + const_cast<Expr **>(NewAligns.data()), NewAligns.size(), SR); ADecl->addAttr(NewAttr); return ConvertDeclToDeclGroup(ADecl); } @@ -8859,7 +8928,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClause( // OpenMP [2.8.1, simd construct, Restrictions] // A list-item cannot appear in more than one aligned clause. if (Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) { - Diag(ELoc, diag::err_omp_aligned_twice) << ERange; + Diag(ELoc, diag::err_omp_aligned_twice) << 0 << ERange; Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(OMPC_aligned); continue; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 168bf6f451d..3a320e11d14 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -247,7 +247,7 @@ static void instantiateOMPDeclareSimdDeclAttr( New = FTD->getTemplatedDecl(); auto *FD = cast<FunctionDecl>(New); auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(FD->getDeclContext()); - SmallVector<Expr *, 4> Uniforms; + SmallVector<Expr *, 4> Uniforms, Aligneds, Alignments; auto &&Subst = [&](Expr *E) -> ExprResult { if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) @@ -273,9 +273,21 @@ static void instantiateOMPDeclareSimdDeclAttr( } } - (void)S.ActOnOpenMPDeclareSimdDirective(S.ConvertDeclToDeclGroup(New), - Attr.getBranchState(), Simdlen.get(), - Uniforms, Attr.getRange()); + auto AI = Attr.alignments_begin(); + for (auto *E : Attr.aligneds()) { + ExprResult Inst = Subst(E); + if (Inst.isInvalid()) + continue; + Aligneds.push_back(Inst.get()); + Inst = ExprEmpty(); + if (*AI) + Inst = S.SubstExpr(*AI, TemplateArgs); + Alignments.push_back(Inst.get()); + ++AI; + } + (void)S.ActOnOpenMPDeclareSimdDirective( + S.ConvertDeclToDeclGroup(New), Attr.getBranchState(), Simdlen.get(), + Uniforms, Aligneds, Alignments, Attr.getRange()); } void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, |