Skip to content

Commit ee05167

Browse files
committed
[OpenMP] Allow traits for the OpenMP context selector isa
It was unclear what `isa` was supposed to mean so we did not provide any traits for this context selector. With this patch we will allow *any* string or identifier. We use the target attribute and target info to determine if the trait matches. In other words, we will check if the provided value is a target feature that is available (at the call site). Fixes PR46338 Reviewed By: ABataev Differential Revision: https://reviews.llvm.org/D83281
1 parent 7db017b commit ee05167

File tree

12 files changed

+270
-82
lines changed

12 files changed

+270
-82
lines changed

clang/include/clang/AST/OpenMPClause.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7635,6 +7635,10 @@ class OMPClausePrinter final : public OMPClauseVisitor<OMPClausePrinter> {
76357635

76367636
struct OMPTraitProperty {
76377637
llvm::omp::TraitProperty Kind = llvm::omp::TraitProperty::invalid;
7638+
7639+
/// The raw string as we parsed it. This is needed for the `isa` trait set
7640+
/// (which accepts anything) and (later) extensions.
7641+
StringRef RawString;
76387642
};
76397643
struct OMPTraitSelector {
76407644
Expr *ScoreOrCondition = nullptr;
@@ -7692,6 +7696,23 @@ class OMPTraitInfo {
76927696
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo &TI);
76937697
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo *TI);
76947698

7699+
/// Clang specific specialization of the OMPContext to lookup target features.
7700+
struct TargetOMPContext final : public llvm::omp::OMPContext {
7701+
7702+
TargetOMPContext(ASTContext &ASTCtx,
7703+
std::function<void(StringRef)> &&DiagUnknownTrait,
7704+
const FunctionDecl *CurrentFunctionDecl);
7705+
virtual ~TargetOMPContext() = default;
7706+
7707+
/// See llvm::omp::OMPContext::matchesISATrait
7708+
bool matchesISATrait(StringRef RawString) const override;
7709+
7710+
private:
7711+
std::function<bool(StringRef)> FeatureValidityCheck;
7712+
std::function<void(StringRef)> DiagUnknownTrait;
7713+
llvm::StringMap<bool> FeatureMap;
7714+
};
7715+
76957716
} // namespace clang
76967717

76977718
#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,11 @@ def warn_omp_declare_variant_string_literal_or_identifier
12781278
"%select{set|selector|property}0; "
12791279
"%select{set|selector|property}0 skipped">,
12801280
InGroup<OpenMPClauses>;
1281+
def warn_unknown_begin_declare_variant_isa_trait
1282+
: Warning<"isa trait '%0' is not known to the current target; verify the "
1283+
"spelling or consider restricting the context selector with the "
1284+
"'arch' selector further">,
1285+
InGroup<SourceUsesOpenMP>;
12811286
def note_omp_declare_variant_ctx_options
12821287
: Note<"context %select{set|selector|property}0 options are: %1">;
12831288
def warn_omp_declare_variant_expected

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10320,6 +10320,11 @@ def warn_nested_declare_variant
1032010320
: Warning<"nesting `omp begin/end declare variant` is not supported yet; "
1032110321
"nested context ignored">,
1032210322
InGroup<SourceUsesOpenMP>;
10323+
def warn_unknown_declare_variant_isa_trait
10324+
: Warning<"isa trait '%0' is not known to the current target; verify the "
10325+
"spelling or consider restricting the context selector with the "
10326+
"'arch' selector further">,
10327+
InGroup<SourceUsesOpenMP>;
1032310328
def err_omp_non_pointer_type_array_shaping_base : Error<
1032410329
"expected expression with a pointer to a complete type as a base of an array "
1032510330
"shaping operation">;

clang/lib/AST/OpenMPClause.cpp

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "clang/AST/DeclOpenMP.h"
1818
#include "clang/Basic/LLVM.h"
1919
#include "clang/Basic/OpenMPKinds.h"
20+
#include "clang/Basic/TargetInfo.h"
2021
#include "llvm/ADT/SmallPtrSet.h"
2122
#include "llvm/Support/Casting.h"
2223
#include "llvm/Support/ErrorHandling.h"
@@ -2131,9 +2132,10 @@ void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx,
21312132
Selector.ScoreOrCondition->getIntegerConstantExpr(ASTCtx))
21322133
VMI.addTrait(CondVal->isNullValue()
21332134
? TraitProperty::user_condition_false
2134-
: TraitProperty::user_condition_true);
2135+
: TraitProperty::user_condition_true,
2136+
"<condition>");
21352137
else
2136-
VMI.addTrait(TraitProperty::user_condition_false);
2138+
VMI.addTrait(TraitProperty::user_condition_false, "<condition>");
21372139
continue;
21382140
}
21392141

@@ -2143,11 +2145,12 @@ void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx,
21432145
if ((Score = Selector.ScoreOrCondition->getIntegerConstantExpr(ASTCtx)))
21442146
ScorePtr = &*Score;
21452147
else
2146-
VMI.addTrait(TraitProperty::user_condition_false);
2148+
VMI.addTrait(TraitProperty::user_condition_false,
2149+
"<non-constant-score>");
21472150
}
21482151

21492152
for (const OMPTraitProperty &Property : Selector.Properties)
2150-
VMI.addTrait(Set.Kind, Property.Kind, ScorePtr);
2153+
VMI.addTrait(Set.Kind, Property.Kind, Property.RawString, ScorePtr);
21512154

21522155
if (Set.Kind != TraitSet::construct)
21532156
continue;
@@ -2204,7 +2207,8 @@ void OMPTraitInfo::print(llvm::raw_ostream &OS,
22042207
if (!FirstProperty)
22052208
OS << ", ";
22062209
FirstProperty = false;
2207-
OS << getOpenMPContextTraitPropertyName(Property.Kind);
2210+
OS << getOpenMPContextTraitPropertyName(Property.Kind,
2211+
Property.RawString);
22082212
}
22092213
}
22102214
OS << ")";
@@ -2231,7 +2235,9 @@ std::string OMPTraitInfo::getMangledName() const {
22312235
continue;
22322236

22332237
for (const OMPTraitProperty &Property : Selector.Properties)
2234-
OS << '$' << 'P' << getOpenMPContextTraitPropertyName(Property.Kind);
2238+
OS << '$' << 'P'
2239+
<< getOpenMPContextTraitPropertyName(Property.Kind,
2240+
Property.RawString);
22352241
}
22362242
}
22372243
return OS.str();
@@ -2261,8 +2267,9 @@ OMPTraitInfo::OMPTraitInfo(StringRef MangledName) {
22612267
Selector.Properties.push_back(OMPTraitProperty());
22622268
OMPTraitProperty &Property = Selector.Properties.back();
22632269
std::pair<StringRef, StringRef> PropRestPair = MangledName.split('$');
2264-
Property.Kind =
2265-
getOpenMPContextTraitPropertyKind(Set.Kind, PropRestPair.first);
2270+
Property.RawString = PropRestPair.first;
2271+
Property.Kind = getOpenMPContextTraitPropertyKind(
2272+
Set.Kind, Selector.Kind, PropRestPair.first);
22662273
MangledName = PropRestPair.second;
22672274
} while (true);
22682275
} while (true);
@@ -2280,3 +2287,24 @@ llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
22802287
const OMPTraitInfo *TI) {
22812288
return TI ? OS << *TI : OS;
22822289
}
2290+
2291+
TargetOMPContext::TargetOMPContext(
2292+
ASTContext &ASTCtx, std::function<void(StringRef)> &&DiagUnknownTrait,
2293+
const FunctionDecl *CurrentFunctionDecl)
2294+
: OMPContext(ASTCtx.getLangOpts().OpenMPIsDevice,
2295+
ASTCtx.getTargetInfo().getTriple()),
2296+
FeatureValidityCheck([&](StringRef FeatureName) {
2297+
return ASTCtx.getTargetInfo().isValidFeatureName(FeatureName);
2298+
}),
2299+
DiagUnknownTrait(std::move(DiagUnknownTrait)) {
2300+
ASTCtx.getFunctionFeatureMap(FeatureMap, CurrentFunctionDecl);
2301+
}
2302+
2303+
bool TargetOMPContext::matchesISATrait(StringRef RawString) const {
2304+
auto It = FeatureMap.find(RawString);
2305+
if (It != FeatureMap.end())
2306+
return It->second;
2307+
if (!FeatureValidityCheck(RawString))
2308+
DiagUnknownTrait(RawString);
2309+
return false;
2310+
}

clang/lib/Parse/ParseOpenMP.cpp

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,8 @@ void Parser::parseOMPTraitPropertyKind(
869869
return;
870870
}
871871

872-
TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Name);
872+
TIProperty.RawString = Name;
873+
TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
873874
if (TIProperty.Kind != TraitProperty::invalid) {
874875
if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
875876
TIProperty.Kind = TraitProperty::invalid;
@@ -910,7 +911,7 @@ void Parser::parseOMPTraitPropertyKind(
910911
{TraitSet::construct, TraitSet::user, TraitSet::implementation,
911912
TraitSet::device}) {
912913
TraitProperty PropertyForName =
913-
getOpenMPContextTraitPropertyKind(PotentialSet, Name);
914+
getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);
914915
if (PropertyForName == TraitProperty::invalid)
915916
continue;
916917
Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
@@ -949,8 +950,8 @@ static bool checkExtensionProperty(Parser &P, SourceLocation Loc,
949950
for (OMPTraitProperty &SeenProp : TISelector.Properties)
950951
if (IsMatchExtension(SeenProp)) {
951952
P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
952-
StringRef SeenName =
953-
llvm::omp::getOpenMPContextTraitPropertyName(SeenProp.Kind);
953+
StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
954+
SeenProp.Kind, SeenProp.RawString);
954955
SourceLocation SeenLoc = Seen[SeenName];
955956
P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
956957
<< CONTEXT_TRAIT_LVL << SeenName;
@@ -995,11 +996,13 @@ void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,
995996
}
996997

997998
Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
998-
<< getOpenMPContextTraitPropertyName(TIProperty.Kind)
999+
<< getOpenMPContextTraitPropertyName(TIProperty.Kind,
1000+
TIProperty.RawString)
9991001
<< getOpenMPContextTraitSelectorName(TISelector.Kind)
10001002
<< getOpenMPContextTraitSetName(Set);
10011003
Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
1002-
<< getOpenMPContextTraitPropertyName(TIProperty.Kind)
1004+
<< getOpenMPContextTraitPropertyName(TIProperty.Kind,
1005+
TIProperty.RawString)
10031006
<< getOpenMPContextTraitSelectorName(
10041007
getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
10051008
<< getOpenMPContextTraitSetName(
@@ -1045,8 +1048,8 @@ void Parser::parseOMPTraitSelectorKind(
10451048
for (const auto &PotentialSet :
10461049
{TraitSet::construct, TraitSet::user, TraitSet::implementation,
10471050
TraitSet::device}) {
1048-
TraitProperty PropertyForName =
1049-
getOpenMPContextTraitPropertyKind(PotentialSet, Name);
1051+
TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1052+
PotentialSet, TraitSelector::invalid, Name);
10501053
if (PropertyForName == TraitProperty::invalid)
10511054
continue;
10521055
Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
@@ -1140,7 +1143,8 @@ void Parser::parseOMPContextSelector(
11401143

11411144
if (!RequiresProperty) {
11421145
TISelector.Properties.push_back(
1143-
{getOpenMPContextTraitPropertyForSelector(TISelector.Kind)});
1146+
{getOpenMPContextTraitPropertyForSelector(TISelector.Kind),
1147+
getOpenMPContextTraitSelectorName(TISelector.Kind)});
11441148
return;
11451149
}
11461150

@@ -1157,7 +1161,8 @@ void Parser::parseOMPContextSelector(
11571161
if (!Condition.isUsable())
11581162
return FinishSelector();
11591163
TISelector.ScoreOrCondition = Condition.get();
1160-
TISelector.Properties.push_back({TraitProperty::user_condition_unknown});
1164+
TISelector.Properties.push_back(
1165+
{TraitProperty::user_condition_unknown, "<condition>"});
11611166
return;
11621167
}
11631168

@@ -1236,8 +1241,8 @@ void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,
12361241
for (const auto &PotentialSet :
12371242
{TraitSet::construct, TraitSet::user, TraitSet::implementation,
12381243
TraitSet::device}) {
1239-
TraitProperty PropertyForName =
1240-
getOpenMPContextTraitPropertyKind(PotentialSet, Name);
1244+
TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1245+
PotentialSet, TraitSelector::invalid, Name);
12411246
if (PropertyForName == TraitProperty::invalid)
12421247
continue;
12431248
Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
@@ -1820,8 +1825,15 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
18201825
VariantMatchInfo VMI;
18211826
ASTContext &ASTCtx = Actions.getASTContext();
18221827
TI.getAsVariantMatchInfo(ASTCtx, VMI);
1823-
OMPContext OMPCtx(ASTCtx.getLangOpts().OpenMPIsDevice,
1824-
ASTCtx.getTargetInfo().getTriple());
1828+
1829+
std::function<void(StringRef)> DiagUnknownTrait = [this, Loc](
1830+
StringRef ISATrait) {
1831+
// TODO Track the selector locations in a way that is accessible here to
1832+
// improve the diagnostic location.
1833+
Diag(Loc, diag::warn_unknown_begin_declare_variant_isa_trait) << ISATrait;
1834+
};
1835+
TargetOMPContext OMPCtx(ASTCtx, std::move(DiagUnknownTrait),
1836+
/* CurrentFunctionDecl */ nullptr);
18251837

18261838
if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) {
18271839
Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI);

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5895,8 +5895,15 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
58955895
return Call;
58965896

58975897
ASTContext &Context = getASTContext();
5898-
OMPContext OMPCtx(getLangOpts().OpenMPIsDevice,
5899-
Context.getTargetInfo().getTriple());
5898+
std::function<void(StringRef)> DiagUnknownTrait = [this,
5899+
CE](StringRef ISATrait) {
5900+
// TODO Track the selector locations in a way that is accessible here to
5901+
// improve the diagnostic location.
5902+
Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
5903+
<< ISATrait;
5904+
};
5905+
TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
5906+
getCurFunctionDecl());
59005907

59015908
SmallVector<Expr *, 4> Exprs;
59025909
SmallVector<VariantMatchInfo, 4> VMIs;
@@ -5908,7 +5915,8 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
59085915
VariantMatchInfo VMI;
59095916
OMPTraitInfo &TI = A->getTraitInfo();
59105917
TI.getAsVariantMatchInfo(Context, VMI);
5911-
if (!isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ false))
5918+
if (!isVariantApplicableInContext(VMI, OMPCtx,
5919+
/* DeviceSetOnly */ false))
59125920
continue;
59135921

59145922
VMIs.push_back(VMI);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %clang_cc1 -verify -fopenmp -x c -triple %itanium_abi_triple -emit-llvm %s -o - -fopenmp-version=50 | FileCheck %s --check-prefix=GENERIC
2+
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t -fopenmp-version=50 %s
3+
// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -fopenmp-version=50 | FileCheck %s --check-prefix=GENERIC
4+
5+
// RUN: %clang_cc1 -target-feature +avx512f -verify -fopenmp -x c -triple %itanium_abi_triple -emit-llvm %s -o - -fopenmp-version=50 | FileCheck %s --check-prefix=WITHFEATURE
6+
// RUN: %clang_cc1 -target-feature +avx512f -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t -fopenmp-version=50 %s
7+
// RUN: %clang_cc1 -target-feature +avx512f -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -fopenmp-version=50 | FileCheck %s --check-prefix=WITHFEATURE
8+
9+
// expected-no-diagnostics
10+
11+
// Test taken from PR46338 (by linna su)
12+
13+
#ifndef HEADER
14+
#define HEADER
15+
16+
void base_saxpy(int, float, float *, float *);
17+
void avx512_saxpy(int, float, float *, float *);
18+
19+
#pragma omp declare variant(avx512_saxpy) \
20+
match(device = {isa(avx512f)})
21+
void base_saxpy(int n, float s, float *x, float *y) {
22+
#pragma omp parallel for
23+
for (int i = 0; i < n; i++)
24+
y[i] = s * x[i] + y[i];
25+
}
26+
27+
void avx512_saxpy(int n, float s, float *x, float *y) {
28+
#pragma omp parallel for simd simdlen(16) aligned(x, y : 64)
29+
for (int i = 0; i < n; i++)
30+
y[i] = s * x[i] + y[i];
31+
}
32+
33+
void caller(int n, float s, float *x, float *y) {
34+
// GENERIC: define void @{{.*}}caller
35+
// GENERIC: call void @{{.*}}base_saxpy
36+
// WITHFEATURE: define void @{{.*}}caller
37+
// WITHFEATURE: call void @{{.*}}avx512_saxpy
38+
base_saxpy(n, s, x, y);
39+
}
40+
41+
__attribute__((target("avx512f"))) void variant_caller(int n, float s, float *x, float *y) {
42+
// GENERIC: define void @{{.*}}variant_caller
43+
// GENERIC: call void @{{.*}}avx512_saxpy
44+
// WITHFEATURE: define void @{{.*}}variant_caller
45+
// WITHFEATURE: call void @{{.*}}avx512_saxpy
46+
base_saxpy(n, s, x, y);
47+
}
48+
49+
#endif

clang/test/OpenMP/declare_variant_messages.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,18 @@ void marked_variant(void);
137137
#pragma omp declare variant(marked_variant) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-warning {{variant function in '#pragma omp declare variant' is itself marked as '#pragma omp declare variant'}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
138138
void marked(void);
139139

140+
#pragma omp declare variant(foo) match(device = {isa("foo")})
141+
int unknown_isa_trait(void);
142+
#pragma omp declare variant(foo) match(device = {isa(foo)})
143+
int unknown_isa_trait2(void);
144+
#pragma omp declare variant(foo) match(device = {kind(fpga), isa(bar)})
145+
int ignored_isa_trait(void);
146+
147+
void caller() {
148+
unknown_isa_trait(); // expected-warning {{isa trait 'foo' is not known to the current target; verify the spelling or consider restricting the context selector with the 'arch' selector further}}
149+
unknown_isa_trait2(); // expected-warning {{isa trait 'foo' is not known to the current target; verify the spelling or consider restricting the context selector with the 'arch' selector further}}
150+
ignored_isa_trait();
151+
}
140152

141153
#pragma omp declare variant // expected-error {{function declaration is expected after 'declare variant' directive}}
142154

0 commit comments

Comments
 (0)