Skip to content

Commit

Permalink
[OPENMP 4.0] Initial support for '#pragma omp declare simd' directive.
Browse files Browse the repository at this point in the history
Initial parsing/sema/serialization/deserialization support for '#pragma
omp declare simd' directive.
The 'declare simd' construct can be applied to a function to enable the
creation of one or more versions that can process multiple arguments
using SIMD instructions from a single invocation from a SIMD loop.
If the function has any declarations, then the declare simd construct
for any declaration that has one must be equivalent to the one specified
 for the definition. Otherwise, the result is unspecified.
This pragma can be applied many times to the same declaration.
Internally this pragma is represented as an attribute. But we need special processing for this pragma because it must be used before function declaration, this directive is applied to.
Differential Revision: http://reviews.llvm.org/D10599

llvm-svn: 264853
  • Loading branch information
alexey-bataev committed Mar 30, 2016
1 parent 8e46cd0 commit 587e1de
Show file tree
Hide file tree
Showing 16 changed files with 379 additions and 9 deletions.
11 changes: 11 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2244,6 +2244,17 @@ def OMPCaptureNoInit : InheritableAttr {
let Documentation = [Undocumented];
}

def OMPDeclareSimdDecl : Attr {
let Spellings = [Pragma<"omp", "declare simd">];
let Subjects = SubjectList<[Function]>;
let SemaHandler = 0;
let HasCustomParsing = 1;
let Documentation = [OMPDeclareSimdDocs];
let AdditionalMembers = [{
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {}
}];
}

def InternalLinkage : InheritableAttr {
let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">];
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
Expand Down
35 changes: 35 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1888,6 +1888,41 @@ arguments, with arbitrary offsets.
}];
}

def OMPDeclareSimdDocs : Documentation {
let Category = DocCatStmt;
let Heading = "#pragma omp declare simd";
let Content = [{
The `declare simd` construct can be applied to a function to enable the creation
of one or more versions that can process multiple arguments using SIMD
instructions from a single invocation in a SIMD loop. The `declare simd`
directive is a declarative directive. There may be multiple `declare simd`
directives for a function. The use of a `declare simd` construct on a function
enables the creation of SIMD versions of the associated function that can be
used to process multiple arguments from a single invocation from a SIMD loop
concurrently.
The syntax of the `declare simd` construct is as follows:

.. code-block:: c

#pragma omp declare simd [clause[[,] clause] ...] new-line
[#pragma omp declare simd [clause[[,] clause] ...] new-line]
[...]
function definition or declaration

where clause is one of the following:

.. code-block:: c

simdlen(length)
linear(argument-list[:constant-linear-step])
aligned(argument-list[:alignment])
uniform(argument-list)
inbranch
notinbranch

}];
}

def NotTailCalledDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,8 @@ def err_omp_expected_identifier_for_critical : Error<
"expected identifier specifying the name of the 'omp critical' directive">;
def err_omp_expected_reduction_identifier : Error<
"expected identifier or one of the following operators: '+', '-', '*', '&', '|', '^', '&&', or '||'">;
def err_omp_decl_in_declare_simd : Error<
"function declaration is expected after 'declare simd' directive">;
def err_omp_unknown_map_type : Error<
"incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
def err_omp_unknown_map_type_modifier : Error<
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -8039,6 +8039,10 @@ def err_omp_single_copyprivate_with_nowait : Error<
"the 'copyprivate' clause must not be used with the 'nowait' clause">;
def note_omp_nowait_clause_here : Note<
"'nowait' clause is here">;
def err_omp_single_decl_in_declare_simd : Error<
"single declaration is expected after 'declare simd' directive">;
def err_omp_function_expected : Error<
"'#pragma omp declare simd' can only be applied to functions">;
def err_omp_wrong_cancel_region : Error<
"one of 'for', 'parallel', 'sections' or 'taskgroup' is expected">;
def err_omp_parent_cancel_region_nowait : Error<
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/OpenMPKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections")
OPENMP_DIRECTIVE_EXT(for_simd, "for simd")
OPENMP_DIRECTIVE_EXT(cancellation_point, "cancellation point")
OPENMP_DIRECTIVE_EXT(declare_reduction, "declare reduction")
OPENMP_DIRECTIVE_EXT(declare_simd, "declare simd")
OPENMP_DIRECTIVE(taskloop)
OPENMP_DIRECTIVE_EXT(taskloop_simd, "taskloop simd")
OPENMP_DIRECTIVE(distribute)
Expand Down
7 changes: 5 additions & 2 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -2428,7 +2428,7 @@ class Parser : public CodeCompletionHandler {
ParsingDeclRAIIObject *DiagsFromTParams = nullptr);
DeclGroupPtrTy ParseCXXClassMemberDeclarationWithPragmas(
AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs,
DeclSpec::TST TagType, Decl *TagDecl);
DeclSpec::TST TagType, Decl *Tag);
void ParseConstructorInitializer(Decl *ConstructorDecl);
MemInitResult ParseMemInitializer(Decl *ConstructorDecl);
void HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
Expand Down Expand Up @@ -2457,7 +2457,10 @@ class Parser : public CodeCompletionHandler {
//===--------------------------------------------------------------------===//
// OpenMP: Directives and clauses.
/// \brief Parses declarative OpenMP directives.
DeclGroupPtrTy ParseOpenMPDeclarativeDirective(AccessSpecifier AS);
DeclGroupPtrTy ParseOpenMPDeclarativeDirectiveWithExtDecl(
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
DeclSpec::TST TagType = DeclSpec::TST_unspecified,
Decl *TagDecl = nullptr);
/// \brief Parse 'omp declare reduction' construct.
DeclGroupPtrTy ParseOpenMPDeclareReductionDirective(AccessSpecifier AS);
/// \brief Parses simple list of variables.
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ namespace clang {
class ObjCProtocolDecl;
class OMPThreadPrivateDecl;
class OMPDeclareReductionDecl;
class OMPDeclareSimdDecl;
class OMPClause;
struct OverloadCandidate;
class OverloadCandidateSet;
Expand Down Expand Up @@ -8087,6 +8088,11 @@ class Sema {
SourceLocation EndLoc,
llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);

/// \brief Called on well-formed '\#pragma omp declare simd' after parsing of
/// the associated method/function.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG,
SourceLocation StartLoc);

OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,
SourceLocation StartLoc,
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/OpenMPKinds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,8 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
case OMPD_declare_simd:
break;
case OMPD_cancel:
switch (CKind) {
#define OPENMP_CANCEL_CLAUSE(Name) \
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3654,8 +3654,10 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
}

if (Tok.is(tok::annot_pragma_openmp)) {
// There may be declared reduction operator inside structure/union.
(void)ParseOpenMPDeclarativeDirective(AS_public);
// Result can be ignored, because it must be always empty.
AccessSpecifier AS = AS_none;
ParsedAttributesWithRange Attrs(AttrFactory);
(void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs);
continue;
}

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2919,7 +2919,8 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
}

if (Tok.is(tok::annot_pragma_openmp))
return ParseOpenMPDeclarativeDirective(AS);
return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, AccessAttrs, TagType,
TagDecl);

// Parse all the comma separated declarators.
return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList());
Expand Down
57 changes: 55 additions & 2 deletions clang/lib/Parse/ParseOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
static const unsigned F[][3] = {
{ OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
{ OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
{ OMPD_declare, OMPD_simd, OMPD_declare_simd },
{ OMPD_target, OMPD_data, OMPD_target_data },
{ OMPD_target, OMPD_enter, OMPD_target_enter },
{ OMPD_target, OMPD_exit, OMPD_target_exit },
Expand Down Expand Up @@ -332,8 +333,14 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
/// annot_pragma_openmp 'declare' 'reduction' [...]
/// annot_pragma_openmp_end
///
Parser::DeclGroupPtrTy
Parser::ParseOpenMPDeclarativeDirective(AccessSpecifier AS) {
/// declare-simd-directive:
/// annot_pragma_openmp 'declare simd' {<clause> [,]}
/// annot_pragma_openmp_end
/// <function declaration/definition>
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
DeclSpec::TST TagType, Decl *Tag) {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
ParenBraceBracketBalancer BalancerRAIIObj(*this);

Expand Down Expand Up @@ -373,6 +380,47 @@ Parser::ParseOpenMPDeclarativeDirective(AccessSpecifier AS) {
return Res;
}
break;
case OMPD_declare_simd: {
// The syntax is:
// { #pragma omp declare simd }
// <function-declaration-or-definition>
//

ConsumeToken();
// The last seen token is annot_pragma_openmp_end - need to check for
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
<< getOpenMPDirectiveName(OMPD_declare_simd);
while (Tok.isNot(tok::annot_pragma_openmp_end))
ConsumeAnyToken();
}
// Skip the last annot_pragma_openmp_end.
ConsumeToken();

DeclGroupPtrTy Ptr;
if (Tok.is(tok::annot_pragma_openmp)) {
Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
} else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Here we expect to see some function declaration.
if (AS == AS_none) {
assert(TagType == DeclSpec::TST_unspecified);
MaybeParseCXX11Attributes(Attrs);
MaybeParseMicrosoftAttributes(Attrs);
ParsingDeclSpec PDS(*this);
Ptr = ParseExternalDeclaration(Attrs, &PDS);
} else {
Ptr =
ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
}
}
if (!Ptr) {
Diag(Loc, diag::err_omp_decl_in_declare_simd);
return DeclGroupPtrTy();
}

return Actions.ActOnOpenMPDeclareSimdDirective(Ptr, Loc);
}
case OMPD_unknown:
Diag(Tok, diag::err_omp_unknown_directive);
break;
Expand Down Expand Up @@ -627,6 +675,11 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
OMPDirectiveScope.Exit();
break;
}
case OMPD_declare_simd:
Diag(Tok, diag::err_omp_unexpected_directive)
<< getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end);
break;
case OMPD_unknown:
Diag(Tok, diag::err_omp_unknown_directive);
SkipUntil(tok::annot_pragma_openmp_end);
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Parse/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -659,8 +659,10 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
case tok::annot_pragma_opencl_extension:
HandlePragmaOpenCLExtension();
return nullptr;
case tok::annot_pragma_openmp:
return ParseOpenMPDeclarativeDirective(/*AS=*/AS_none);
case tok::annot_pragma_openmp: {
AccessSpecifier AS = AS_none;
return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, attrs);
}
case tok::annot_pragma_ms_pointers_to_members:
HandlePragmaMSPointersToMembers();
return nullptr;
Expand Down
28 changes: 28 additions & 0 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1701,6 +1701,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_target_enter_data:
case OMPD_target_exit_data:
case OMPD_declare_reduction:
case OMPD_declare_simd:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
Expand Down Expand Up @@ -3155,6 +3156,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
break;
case OMPD_threadprivate:
case OMPD_declare_reduction:
case OMPD_declare_simd:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
Expand All @@ -3175,6 +3177,32 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
return Res;
}

Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG,
SourceLocation StartLoc) {
if (!DG || DG.get().isNull())
return DeclGroupPtrTy();

if (!DG.get().isSingleDecl()) {
Diag(StartLoc, diag::err_omp_single_decl_in_declare_simd);
return DG;
}
auto *ADecl = DG.get().getSingleDecl();
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
ADecl = FTD->getTemplatedDecl();

if (!isa<FunctionDecl>(ADecl)) {
Diag(ADecl->getLocation(), diag::err_omp_function_expected)
<< ADecl->getDeclContext()->isFileContext();
return DeclGroupPtrTy();
}

auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
Context, SourceRange(StartLoc, StartLoc));
ADecl->addAttr(NewAttr);
return ConvertDeclToDeclGroup(ADecl);
}

StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
Expand Down
17 changes: 17 additions & 0 deletions clang/test/OpenMP/declare_simd_ast_print.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics

#ifndef HEADER
#define HEADER

#pragma omp declare simd
#pragma omp declare simd
void add_1(float *d, float *s1, float *s2) __attribute__((cold));

// CHECK: #pragma omp declare simd
// CHECK-NEXT: #pragma omp declare simd
// CHECK-NEXT: void add_1(float *d, float *s1, float *s2) __attribute__((cold))

#endif
Loading

0 comments on commit 587e1de

Please sign in to comment.