[OPENMP51]Initial parsing/sema for adjust_args clause for 'declare variant'

Adds initial parsing and sema for the 'adjust_args' clause.

Note that an AST clause is not created as it instead adds its expressions
to the OMPDeclareVariantAttr.

Differential Revision: https://reviews.llvm.org/D99905
This commit is contained in:
Mike Rice 2021-10-12 14:55:00 -07:00
parent ea72b55b5c
commit fb4c451001
18 changed files with 390 additions and 38 deletions

View File

@ -3690,6 +3690,8 @@ def OMPDeclareVariant : InheritableAttr {
let Args = [
ExprArgument<"VariantFuncRef">,
OMPTraitInfoArgument<"TraitInfos">,
VariadicExprArgument<"AdjustArgsNothing">,
VariadicExprArgument<"AdjustArgsNeedDevicePtr">
];
let AdditionalMembers = [{
OMPTraitInfo &getTraitInfo() { return *traitInfos; }

View File

@ -1357,7 +1357,8 @@ def err_omp_mapper_illegal_identifier : Error<
def err_omp_mapper_expected_declarator : Error<
"expected declarator on 'omp declare mapper' directive">;
def err_omp_declare_variant_wrong_clause : Error<
"expected '%0' clause on 'omp declare variant' directive">;
"expected %select{'match'|'match' or 'adjust_args'}0 clause on "
"'omp declare variant' directive">;
def err_omp_declare_variant_duplicate_nested_trait : Error<
"nested OpenMP context selector contains duplicated trait '%0'"
" in selector '%1' and set '%2' with different score">;

View File

@ -10817,6 +10817,10 @@ def err_omp_unroll_full_variable_trip_count : Error<
def note_omp_directive_here : Note<"'%0' directive found here">;
def err_omp_instantiation_not_supported
: Error<"instantiation of '%0' not supported yet">;
def err_omp_adjust_arg_multiple_clauses : Error<
"'adjust_arg' argument %0 used in multiple clauses">;
def err_omp_clause_requires_dispatch_construct : Error<
"'%0' clause requires 'dispatch' context selector">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {

View File

@ -59,6 +59,9 @@
#ifndef OPENMP_REDUCTION_MODIFIER
#define OPENMP_REDUCTION_MODIFIER(Name)
#endif
#ifndef OPENMP_ADJUST_ARGS_KIND
#define OPENMP_ADJUST_ARGS_KIND(Name)
#endif
// Static attributes for 'schedule' clause.
OPENMP_SCHEDULE_KIND(static)
@ -149,6 +152,11 @@ OPENMP_REDUCTION_MODIFIER(default)
OPENMP_REDUCTION_MODIFIER(inscan)
OPENMP_REDUCTION_MODIFIER(task)
// Adjust-op kinds for the 'adjust_args' clause.
OPENMP_ADJUST_ARGS_KIND(nothing)
OPENMP_ADJUST_ARGS_KIND(need_device_ptr)
#undef OPENMP_ADJUST_ARGS_KIND
#undef OPENMP_REDUCTION_MODIFIER
#undef OPENMP_DEVICE_MODIFIER
#undef OPENMP_ORDER_KIND

View File

@ -167,6 +167,13 @@ enum OpenMPReductionClauseModifier {
OMPC_REDUCTION_unknown,
};
/// OpenMP adjust-op kinds for 'adjust_args' clause.
enum OpenMPAdjustArgsOpKind {
#define OPENMP_ADJUST_ARGS_KIND(Name) OMPC_ADJUST_ARGS_##Name,
#include "clang/Basic/OpenMPKinds.def"
OMPC_ADJUST_ARGS_unknown,
};
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str,
const LangOptions &LangOpts);
const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type);

View File

@ -10977,8 +10977,10 @@ public:
/// \param VariantRef Expression that references the variant function, which
/// must be used instead of the original one, specified in \p DG.
/// \param TI The context traits associated with the function variant.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef,
OMPTraitInfo &TI, SourceRange SR);
void ActOnOpenMPDeclareVariantDirective(
FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
ArrayRef<Expr *> AdjustArgsNothing,
ArrayRef<Expr *> AdjustArgsNeedDevicePtr, SourceRange SR);
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,

View File

@ -195,6 +195,25 @@ void OMPDeclareVariantAttr::printPrettyPragma(
OS << ")";
}
OS << " match(" << traitInfos << ")";
auto PrintExprs = [&OS, &Policy](Expr **Begin, Expr **End) {
for (Expr **I = Begin; I != End; ++I) {
assert(*I && "Expected non-null Stmt");
if (I != Begin)
OS << ",";
(*I)->printPretty(OS, nullptr, Policy);
}
};
if (adjustArgsNothing_size()) {
OS << " adjust_args(nothing:";
PrintExprs(adjustArgsNothing_begin(), adjustArgsNothing_end());
OS << ")";
}
if (adjustArgsNeedDevicePtr_size()) {
OS << " adjust_args(need_device_ptr:";
PrintExprs(adjustArgsNeedDevicePtr_begin(), adjustArgsNeedDevicePtr_end());
OS << ")";
}
}
#include "clang/AST/AttrImpl.inc"

View File

@ -125,6 +125,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
#define OPENMP_REDUCTION_MODIFIER(Name) .Case(#Name, OMPC_REDUCTION_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_REDUCTION_unknown);
case OMPC_adjust_args:
return llvm::StringSwitch<OpenMPAdjustArgsOpKind>(Str)
#define OPENMP_ADJUST_ARGS_KIND(Name) .Case(#Name, OMPC_ADJUST_ARGS_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_ADJUST_ARGS_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
@ -369,6 +374,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'reduction' clause modifier");
case OMPC_adjust_args:
switch (Type) {
case OMPC_ADJUST_ARGS_unknown:
return "unknown";
#define OPENMP_ADJUST_ARGS_KIND(Name) \
case OMPC_ADJUST_ARGS_##Name: \
return #Name;
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'adjust_args' clause kind");
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:

View File

@ -5989,6 +5989,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_nocontext:
case OMPC_filter:
case OMPC_when:
case OMPC_adjust_args:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}

View File

@ -1402,21 +1402,69 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
ASTContext &ASTCtx = Actions.getASTContext();
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI))
return;
SmallVector<Expr *, 6> AdjustNothing;
SmallVector<Expr *, 6> AdjustNeedDevicePtr;
// At least one clause is required.
if (Tok.is(tok::annot_pragma_openmp_end)) {
Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
<< (getLangOpts().OpenMP < 51 ? 0 : 1);
}
bool IsError = false;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OpenMPClauseKind CKind = Tok.isAnnotation()
? OMPC_unknown
: getOpenMPClauseKind(PP.getSpelling(Tok));
if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
getLangOpts().OpenMP)) {
Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
<< (getLangOpts().OpenMP < 51 ? 0 : 1);
IsError = true;
}
if (!IsError) {
switch (CKind) {
case OMPC_match:
IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
break;
case OMPC_adjust_args: {
ConsumeToken();
Parser::OpenMPVarListDataTy Data;
SmallVector<Expr *> Vars;
IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
Vars, Data);
if (!IsError)
llvm::append_range(Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing
? AdjustNothing
: AdjustNeedDevicePtr,
Vars);
break;
}
default:
llvm_unreachable("Unexpected clause for declare variant.");
}
}
if (IsError) {
while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
;
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
return;
}
// Skip ',' if any.
if (Tok.is(tok::comma))
ConsumeToken();
}
Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
Actions.checkOpenMPDeclareVariantFunction(
Ptr, AssociatedFunction.get(), TI,
SourceRange(Loc, Tok.getLocation()));
// Skip last tokens.
while (Tok.isNot(tok::annot_pragma_openmp_end))
ConsumeAnyToken();
if (DeclVarData && !TI.Sets.empty())
Actions.ActOnOpenMPDeclareVariantDirective(
DeclVarData->first, DeclVarData->second, TI,
SourceRange(Loc, Tok.getLocation()));
DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
AdjustNeedDevicePtr, SourceRange(Loc, Tok.getLocation()));
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
@ -1431,24 +1479,15 @@ bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
: getOpenMPClauseKind(PP.getSpelling(Tok));
if (CKind != OMPC_match) {
Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
<< getOpenMPClauseName(OMPC_match);
while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
;
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
<< (getLangOpts().OpenMP < 51 ? 0 : 1);
return true;
}
(void)ConsumeToken();
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
getOpenMPClauseName(OMPC_match).data())) {
while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
;
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
getOpenMPClauseName(OMPC_match).data()))
return true;
}
// Parse inner context selectors.
parseOMPContextSelectors(Loc, TI);
@ -2029,8 +2068,13 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
ASTContext &ASTCtx = Actions.getASTContext();
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI))
if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
;
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
break;
}
// Skip last tokens.
skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
@ -4100,6 +4144,23 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
}
} else if (Kind == OMPC_adjust_args) {
// Handle adjust-op for adjust_args clause.
ColonProtectionRAIIObject ColonRAII(*this);
Data.ExtraModifier = getOpenMPSimpleClauseType(
Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
getLangOpts());
Data.ExtraModifierLoc = Tok.getLocation();
if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
} else {
ConsumeToken();
if (Tok.is(tok::colon))
Data.ColonLoc = Tok.getLocation();
ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
"adjust-op");
}
}
bool IsComma =
@ -4107,7 +4168,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
(Kind == OMPC_reduction && !InvalidReductionId) ||
(Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
(Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown);
(Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
(Kind == OMPC_adjust_args &&
Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
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))) {

View File

@ -6808,7 +6808,9 @@ void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
Context, VariantFuncRef, DVScope.TI);
Context, VariantFuncRef, DVScope.TI,
/*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
/*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0);
for (FunctionDecl *BaseFD : Bases)
BaseFD->addAttr(OMPDeclareVariantA);
}
@ -7181,12 +7183,66 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
return std::make_pair(FD, cast<Expr>(DRE));
}
void Sema::ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD,
Expr *VariantRef,
OMPTraitInfo &TI,
SourceRange SR) {
auto *NewAttr =
OMPDeclareVariantAttr::CreateImplicit(Context, VariantRef, &TI, SR);
void Sema::ActOnOpenMPDeclareVariantDirective(
FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
ArrayRef<Expr *> AdjustArgsNothing,
ArrayRef<Expr *> AdjustArgsNeedDevicePtr, SourceRange SR) {
// OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
// An adjust_args clause or append_args clause can only be specified if the
// dispatch selector of the construct selector set appears in the match
// clause.
SmallVector<Expr *, 8> AllAdjustArgs;
llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
if (!AllAdjustArgs.empty()) {
VariantMatchInfo VMI;
TI.getAsVariantMatchInfo(Context, VMI);
if (!llvm::is_contained(
VMI.ConstructTraits,
llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
Diag(AllAdjustArgs[0]->getExprLoc(),
diag::err_omp_clause_requires_dispatch_construct)
<< getOpenMPClauseName(OMPC_adjust_args);
return;
}
}
// OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
// Each argument can only appear in a single adjust_args clause for each
// declare variant directive.
llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
for (Expr *E : AllAdjustArgs) {
E = E->IgnoreParenImpCasts();
if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
const VarDecl *CanonPVD = PVD->getCanonicalDecl();
if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
FD->getParamDecl(PVD->getFunctionScopeIndex())
->getCanonicalDecl() == CanonPVD) {
// It's a parameter of the function, check duplicates.
if (!AdjustVars.insert(CanonPVD).second) {
Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
<< PVD;
return;
}
continue;
}
}
}
// Anything that is not a function parameter is an error.
Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
return;
}
auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
Context, VariantRef, &TI, const_cast<Expr **>(AdjustArgsNothing.data()),
AdjustArgsNothing.size(),
const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
AdjustArgsNeedDevicePtr.size(), SR);
FD->addAttr(NewAttr);
}

View File

@ -481,7 +481,22 @@ static void instantiateOMPDeclareVariantAttr(
}
}
S.ActOnOpenMPDeclareVariantDirective(FD, E, TI, Attr.getRange());
SmallVector<Expr *, 8> NothingExprs;
SmallVector<Expr *, 8> NeedDevicePtrExprs;
for (Expr *E : Attr.adjustArgsNothing()) {
ExprResult ER = Subst(E);
if (ER.isInvalid())
continue;
NothingExprs.push_back(ER.get());
}
for (Expr *E : Attr.adjustArgsNeedDevicePtr()) {
ExprResult ER = Subst(E);
if (ER.isInvalid())
continue;
NeedDevicePtrExprs.push_back(ER.get());
}
S.ActOnOpenMPDeclareVariantDirective(FD, E, TI, NothingExprs,
NeedDevicePtrExprs, Attr.getRange());
}
static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr(

View File

@ -0,0 +1,107 @@
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -fsyntax-only -verify -o - %s
//RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -fsyntax-only -verify -o - %s
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -emit-pch -o %t %s
// expected-no-diagnostics
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -ast-print %s | FileCheck %s --check-prefix=PRINT
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -ast-dump %s | FileCheck %s --check-prefix=DUMP
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -include-pch %t -ast-print %s | FileCheck %s --check-prefix=PRINT
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
//RUN: -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP
#ifndef HEADER
#define HEADER
void foo_v1(float *AAA, float *BBB, int *I) {return;}
void foo_v2(float *AAA, float *BBB, int *I) {return;}
void foo_v3(float *AAA, float *BBB, int *I) {return;}
//DUMP: FunctionDecl{{.*}} foo 'void (float *, float *, int *)'
//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(x86, x86_64)}
//DUMP: DeclRefExpr{{.*}}Function{{.*}}foo_v3
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'I'
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(ppc)}
//DUMP: DeclRefExpr{{.*}}Function{{.*}}foo_v2
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'AAA'
//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(arm)}
//DUMP: DeclRefExpr{{.*}}Function{{.*}}foo_v1
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'AAA'
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
//PRINT: #pragma omp declare variant(foo_v3) match(construct={dispatch}, device={arch(x86, x86_64)}) adjust_args(nothing:I) adjust_args(need_device_ptr:BBB)
//PRINT: #pragma omp declare variant(foo_v2) match(construct={dispatch}, device={arch(ppc)}) adjust_args(need_device_ptr:AAA)
//PRINT: omp declare variant(foo_v1) match(construct={dispatch}, device={arch(arm)}) adjust_args(need_device_ptr:AAA,BBB)
#pragma omp declare variant(foo_v1) \
match(construct={dispatch}, device={arch(arm)}) \
adjust_args(need_device_ptr:AAA,BBB)
#pragma omp declare variant(foo_v2) \
match(construct={dispatch}, device={arch(ppc)}), \
adjust_args(need_device_ptr:AAA)
#pragma omp declare variant(foo_v3) \
adjust_args(need_device_ptr:BBB) adjust_args(nothing:I) \
match(construct={dispatch}, device={arch(x86,x86_64)})
void foo(float *AAA, float *BBB, int *I) {return;}
void Foo_Var(float *AAA, float *BBB) {return;}
#pragma omp declare variant(Foo_Var) \
match(construct={dispatch}, device={arch(x86_64)}) \
adjust_args(need_device_ptr:AAA) adjust_args(nothing:BBB)
template<typename T>
void Foo(T *AAA, T *BBB) {return;}
//PRINT: #pragma omp declare variant(Foo_Var) match(construct={dispatch}, device={arch(x86_64)}) adjust_args(nothing:BBB) adjust_args(need_device_ptr:AAA)
//DUMP: FunctionDecl{{.*}} Foo 'void (T *, T *)'
//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(x86_64)}
//DUMP: DeclRefExpr{{.*}}Function{{.*}}Foo_Var
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'AAA'
//
//DUMP: FunctionDecl{{.*}} Foo 'void (float *, float *)'
//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(x86_64)}
//DUMP: DeclRefExpr{{.*}}Function{{.*}}Foo_Var
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'AAA'
void func()
{
float *A;
float *B;
//#pragma omp dispatch
Foo(A, B);
}
#endif // HEADER

View File

@ -0,0 +1,47 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -DOMP51 -std=c++11 -o - %s
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -DOMP50 -std=c++11 -o - %s
int Other;
void foo_v1(float *AAA, float *BBB, int *I) { return; }
void foo_v2(float *AAA, float *BBB, int *I) { return; }
void foo_v3(float *AAA, float *BBB, int *I) { return; }
#ifdef OMP51
// expected-error@+3 {{'adjust_arg' argument 'AAA' used in multiple clauses}}
#pragma omp declare variant(foo_v1) \
match(construct={dispatch}, device={arch(arm)}) \
adjust_args(need_device_ptr:AAA,BBB) adjust_args(need_device_ptr:AAA)
// expected-error@+3 {{'adjust_arg' argument 'AAA' used in multiple clauses}}
#pragma omp declare variant(foo_v1) \
match(construct={dispatch}, device={arch(ppc)}), \
adjust_args(need_device_ptr:AAA) adjust_args(nothing:AAA)
// expected-error@+2 {{use of undeclared identifier 'J'}}
#pragma omp declare variant(foo_v1) \
adjust_args(nothing:J) \
match(construct={dispatch}, device={arch(x86,x86_64)})
// expected-error@+2 {{expected reference to one of the parameters of function 'foo'}}
#pragma omp declare variant(foo_v3) \
adjust_args(nothing:Other) \
match(construct={dispatch}, device={arch(x86,x86_64)})
// expected-error@+2 {{'adjust_args' clause requires 'dispatch' context selector}}
#pragma omp declare variant(foo_v3) \
adjust_args(nothing:BBB) match(construct={target}, device={arch(arm)})
// expected-error@+2 {{'adjust_args' clause requires 'dispatch' context selector}}
#pragma omp declare variant(foo_v3) \
adjust_args(nothing:BBB) match(device={arch(ppc)})
#endif // OMP51
#ifdef OMP50
// expected-error@+2 {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foo_v1) \
adjust_args(need_device_ptr:AAA) match(device={arch(arm)})
#endif // OMP50
void foo(float *AAA, float *BBB, int *I) { return; }

View File

@ -20,12 +20,12 @@ int foo(void);
#pragma omp declare variant(foo) match(xxx) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp declare variant(foo) match(xxx=) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp declare variant(foo) match(xxx=yyy) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp declare variant(foo) match(xxx=yyy}) // expected-error {{expected ')'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(xxx=yyy}) // expected-error {{expected ')'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foo) match(xxx={) // expected-error {{expected ')'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp declare variant(foo) match(xxx={vvv, vvv}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp declare variant(foo) match(xxx={vvv} xxx) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp declare variant(foo) match(xxx={vvv}) xxx // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp declare variant(foo) match(xxx={vvv}) xxx // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foo) match(implementation={xxx}) // expected-warning {{'xxx' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foo) match(implementation={vendor}) // expected-warning {{the context selector 'vendor' in context set 'implementation' requires a context property defined in parentheses; selector ignored}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foo) match(implementation={vendor(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}}
@ -58,9 +58,9 @@ int bar(void);
int score_and_cond_non_const();
#pragma omp declare variant(foo) match(construct={teams,parallel,for,simd})
#pragma omp declare variant(foo) match(construct={target teams}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(construct={parallel for}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(construct={for simd}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(construct={target teams}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foo) match(construct={parallel for}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foo) match(construct={for simd}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
int construct(void);
#pragma omp declare variant(foo) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}

View File

@ -28,7 +28,7 @@ T foofoo();
#pragma omp declare variant(foofoo <int>) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector; selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <int>) match(implementation = {vvv, vvv}) // expected-warning {{'vvv' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-warning {{'vvv' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <int>) match(implementation = {vvv} implementation) // expected-error {{expected ')'}} expected-warning {{'vvv' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <int>) match(implementation = {vvv}) implementation // expected-warning {{'vvv' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <int>) match(implementation = {vvv}) implementation // expected-warning {{'vvv' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foofoo <int>) match(implementation={xxx}) // expected-warning {{'xxx' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor}) // expected-warning {{the context selector 'vendor' in context set 'implementation' requires a context property defined in parentheses; selector ignored}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}}
@ -72,7 +72,7 @@ int bar();
#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)}) // expected-error {{expected expression}} expected-error {{use of undeclared identifier 'expr'}} expected-error {{expected expression}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)}) // expected-error {{expected expression}} expected-error {{use of undeclared identifier 'expr'}} expected-error {{expected expression}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <T>) match(implementation = {vvv} implementation) // expected-error {{expected ')'}} expected-warning {{'vvv' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <T>) match(implementation = {vvv}) xxx // expected-warning {{'vvv' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <T>) match(implementation = {vvv}) xxx // expected-warning {{'vvv' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(C ibm)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}}

View File

@ -1422,6 +1422,7 @@ CHECK_SIMPLE_CLAUSE(Novariants, OMPC_novariants)
CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext)
CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter)
CHECK_SIMPLE_CLAUSE(When, OMPC_when)
CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args)
CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)
CHECK_REQ_SCALAR_INT_CLAUSE(NumTasks, OMPC_num_tasks)

View File

@ -314,6 +314,7 @@ def OMPC_Uniform : Clause<"uniform"> {
}
def OMPC_DeviceType : Clause<"device_type"> {}
def OMPC_Match : Clause<"match"> {}
def OMPC_AdjustArgs : Clause<"adjust_args"> { }
def OMPC_Depobj : Clause<"depobj"> {
let clangClass = "OMPDepobjClause";
let isImplicit = true;
@ -1518,6 +1519,9 @@ def OMP_DeclareVariant : Directive<"declare variant"> {
let allowedClauses = [
VersionedClause<OMPC_Match>
];
let allowedExclusiveClauses = [
VersionedClause<OMPC_AdjustArgs, 51>
];
}
def OMP_MasterTaskloop : Directive<"master taskloop"> {
let allowedClauses = [