[OPENMP 4.0] Support for 'inbranch|noinbranch' clauses in 'declare

simd'.

Added parsing/semantic analysis for 'inbranch|notinbranch' clauses of
'#pragma omp declare simd' construct.

llvm-svn: 265287
This commit is contained in:
Alexey Bataev 2016-04-04 10:12:15 +00:00
parent 1519491eaf
commit 20dfd77826
9 changed files with 77 additions and 18 deletions

View File

@ -2265,8 +2265,14 @@ def OMPDeclareSimdDecl : Attr {
let SemaHandler = 0; let SemaHandler = 0;
let HasCustomParsing = 1; let HasCustomParsing = 1;
let Documentation = [OMPDeclareSimdDocs]; let Documentation = [OMPDeclareSimdDocs];
let Args = [EnumArgument<"BranchState", "BranchStateTy",
["", "inbranch", "notinbranch"],
["BS_Undefined", "BS_Inbranch", "BS_Notinbranch"]>];
let AdditionalMembers = [{ let AdditionalMembers = [{
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {} void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy)
const {
OS << ' ' << ConvertBranchStateTyToStr(getBranchState());
}
}]; }];
} }

View File

@ -961,6 +961,8 @@ def err_omp_unknown_map_type_modifier : Error<
"incorrect map type modifier, expected 'always'">; "incorrect map type modifier, expected 'always'">;
def err_omp_map_type_missing : Error< def err_omp_map_type_missing : Error<
"missing map type">; "missing map type">;
def err_omp_declare_simd_inbranch_notinbranch : Error<
"unexpected '%0' clause, '%1' is specified already">;
// Pragma loop support. // Pragma loop support.
def err_pragma_loop_missing_argument : Error< def err_pragma_loop_missing_argument : Error<

View File

@ -8091,8 +8091,10 @@ public:
/// \brief Called on well-formed '\#pragma omp declare simd' after parsing of /// \brief Called on well-formed '\#pragma omp declare simd' after parsing of
/// the associated method/function. /// the associated method/function.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, DeclGroupPtrTy
SourceLocation StartLoc); ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG,
OMPDeclareSimdDeclAttr::BranchStateTy BS,
SourceRange SR);
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr, Expr *Expr,

View File

@ -323,6 +323,37 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
IsCorrect); IsCorrect);
} }
/// Parses clauses for 'declare simd' directive.
/// clause:
/// 'inbranch' | 'notinbranch'
static void parseDeclareSimdClauses(Parser &P,
OMPDeclareSimdDeclAttr::BranchStateTy &BS) {
SourceRange BSRange;
const Token &Tok = P.getCurToken();
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
if (Tok.isNot(tok::identifier))
break;
OMPDeclareSimdDeclAttr::BranchStateTy Out;
StringRef TokName = Tok.getIdentifierInfo()->getName();
// Parse 'inranch|notinbranch' clauses.
if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(TokName, Out)) {
if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
<< TokName << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS)
<< BSRange;
}
BS = Out;
BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
} else
// TODO: add parsing of other clauses.
break;
P.ConsumeToken();
// Skip ',' if any.
if (Tok.is(tok::comma))
P.ConsumeToken();
}
}
/// \brief Parsing of declarative OpenMP directives. /// \brief Parsing of declarative OpenMP directives.
/// ///
/// threadprivate-directive: /// threadprivate-directive:
@ -387,8 +418,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
// //
ConsumeToken(); ConsumeToken();
// The last seen token is annot_pragma_openmp_end - need to check for OMPDeclareSimdDeclAttr::BranchStateTy BS =
// extra tokens. OMPDeclareSimdDeclAttr::BS_Undefined;
parseDeclareSimdClauses(*this, BS);
// Need to check for extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) { if (Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok, diag::warn_omp_extra_tokens_at_eol) Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
<< getOpenMPDirectiveName(OMPD_declare_simd); << getOpenMPDirectiveName(OMPD_declare_simd);
@ -396,12 +430,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
ConsumeAnyToken(); ConsumeAnyToken();
} }
// Skip the last annot_pragma_openmp_end. // Skip the last annot_pragma_openmp_end.
ConsumeToken(); SourceLocation EndLoc = ConsumeToken();
DeclGroupPtrTy Ptr; DeclGroupPtrTy Ptr;
if (Tok.is(tok::annot_pragma_openmp)) { if (Tok.is(tok::annot_pragma_openmp))
Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag); Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
} else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Here we expect to see some function declaration. // Here we expect to see some function declaration.
if (AS == AS_none) { if (AS == AS_none) {
assert(TagType == DeclSpec::TST_unspecified); assert(TagType == DeclSpec::TST_unspecified);
@ -419,7 +453,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
return DeclGroupPtrTy(); return DeclGroupPtrTy();
} }
return Actions.ActOnOpenMPDeclareSimdDirective(Ptr, Loc); return Actions.ActOnOpenMPDeclareSimdDirective(Ptr, BS,
SourceRange(Loc, EndLoc));
} }
case OMPD_unknown: case OMPD_unknown:
Diag(Tok, diag::err_omp_unknown_directive); Diag(Tok, diag::err_omp_unknown_directive);

View File

@ -3183,12 +3183,13 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Sema::DeclGroupPtrTy Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, Sema::ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG,
SourceLocation StartLoc) { OMPDeclareSimdDeclAttr::BranchStateTy BS,
SourceRange SR) {
if (!DG || DG.get().isNull()) if (!DG || DG.get().isNull())
return DeclGroupPtrTy(); return DeclGroupPtrTy();
if (!DG.get().isSingleDecl()) { if (!DG.get().isSingleDecl()) {
Diag(StartLoc, diag::err_omp_single_decl_in_declare_simd); Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd);
return DG; return DG;
} }
auto *ADecl = DG.get().getSingleDecl(); auto *ADecl = DG.get().getSingleDecl();
@ -3201,8 +3202,7 @@ Sema::ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG,
return DeclGroupPtrTy(); return DeclGroupPtrTy();
} }
auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit( auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(Context, BS, SR);
Context, SourceRange(StartLoc, StartLoc));
ADecl->addAttr(NewAttr); ADecl->addAttr(NewAttr);
return ConvertDeclToDeclGroup(ADecl); return ConvertDeclToDeclGroup(ADecl);
} }

View File

@ -8,9 +8,13 @@
#pragma omp declare simd #pragma omp declare simd
#pragma omp declare simd #pragma omp declare simd
#pragma omp declare simd inbranch
#pragma omp declare simd notinbranch
void add_1(float *d, float *s1, float *s2) __attribute__((cold)); void add_1(float *d, float *s1, float *s2) __attribute__((cold));
// CHECK: #pragma omp declare simd // CHECK: #pragma omp declare simd notinbranch
// CHECK-NEXT: #pragma omp declare simd inbranch
// CHECK-NEXT: #pragma omp declare simd
// CHECK-NEXT: #pragma omp declare simd // CHECK-NEXT: #pragma omp declare simd
// CHECK-NEXT: void add_1(float *d, float *s1, float *s2) __attribute__((cold)) // CHECK-NEXT: void add_1(float *d, float *s1, float *s2) __attribute__((cold))

View File

@ -7,9 +7,13 @@
#define HEADER #define HEADER
#pragma omp declare simd #pragma omp declare simd
#pragma omp declare simd inbranch
#pragma omp declare simd notinbranch
void add_1(float *d) __attribute__((cold)); void add_1(float *d) __attribute__((cold));
// CHECK: #pragma omp declare simd // CHECK: #pragma omp declare simd notinbranch
// CHECK-NEXT: #pragma omp declare simd inbranch
// CHECK-NEXT: #pragma omp declare simd
// CHECK-NEXT: void add_1(float *d) __attribute__((cold)); // CHECK-NEXT: void add_1(float *d) __attribute__((cold));
// //

View File

@ -46,6 +46,12 @@ void h(int *hp, int *hp2, int *hq, int *lin) {
h((float *)hp, (float *)hp2, (float *)hq, (float *)lin); h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
} }
#pragma omp declare simd inbranch inbranch
#pragma omp declare simd notinbranch notinbranch
#pragma omp declare simd inbranch inbranch notinbranch // expected-error {{unexpected 'notinbranch' clause, 'inbranch' is specified already}}
#pragma omp declare simd notinbranch notinbranch inbranch // expected-error {{unexpected 'inbranch' clause, 'notinbranch' is specified already}}
void foo();
template <class T> template <class T>
struct St { struct St {
// expected-error@+2 {{function declaration is expected after 'declare simd' directive}} // expected-error@+2 {{function declaration is expected after 'declare simd' directive}}

View File

@ -59,10 +59,10 @@ struct S {
// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} <<invalid sloc>> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &' // CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} <<invalid sloc>> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'
#pragma omp declare simd #pragma omp declare simd
#pragma omp declare simd #pragma omp declare simd inbranch
void foo(); void foo();
// CHECK: `-FunctionDecl {{.+}} <line:63:1, col:10> col:6 foo 'void (void)' // CHECK: `-FunctionDecl {{.+}} <line:63:1, col:10> col:6 foo 'void (void)'
// CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} <line:62:9> Implicit // CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} <line:62:9, col:34> Implicit BS_Inbranch
// CHECK-NEXT: `-OMPDeclareSimdDeclAttr {{.+}} <line:61:9> Implicit // CHECK-NEXT: `-OMPDeclareSimdDeclAttr {{.+}} <line:61:9, col:25> Implicit BS_Undefined