[flang][OpenMP] Split DEFAULT into DEFAULT(dsa) and DEFAULT(variant) (#212128)
The 5.0 and 5.1 specs used DEFAULT clause for what is now OTHERWISE. Separate these two claues to be able to specify their properties independently.
This commit is contained in:
parent
750ed0a823
commit
07dfc602db
12 changed files with 77 additions and 64 deletions
|
|
@ -602,6 +602,7 @@ public:
|
|||
NODE(parser, OmpDefaultClause)
|
||||
NODE_ENUM(OmpDefaultClause, DataSharingAttribute)
|
||||
NODE(parser, OmpDefaultmapClause)
|
||||
NODE(parser, OmpDefaultVariantClause)
|
||||
NODE(OmpDefaultmapClause, Modifier)
|
||||
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
|
||||
NODE(parser, OmpDeleteModifier)
|
||||
|
|
|
|||
|
|
@ -4523,17 +4523,9 @@ struct OmpApplyClause {
|
|||
// data-sharing-attribute ->
|
||||
// SHARED | NONE | // since 4.5
|
||||
// PRIVATE | FIRSTPRIVATE // since 5.0
|
||||
//
|
||||
// When used in METADIRECTIVE:
|
||||
// default-clause ->
|
||||
// DEFAULT(directive-specification) // since 5.0, until 5.1
|
||||
// See also otherwise-clause.
|
||||
struct OmpDefaultClause {
|
||||
ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None)
|
||||
UNION_CLASS_BOILERPLATE(OmpDefaultClause);
|
||||
std::variant<DataSharingAttribute,
|
||||
common::Indirection<OmpDirectiveSpecification>>
|
||||
u;
|
||||
WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, DataSharingAttribute);
|
||||
};
|
||||
|
||||
// Ref: [4.5:103-107], [5.0:324-325], [5.1:357-358], [5.2:161-162]
|
||||
|
|
@ -4554,6 +4546,16 @@ struct OmpDefaultmapClause {
|
|||
std::tuple<ImplicitBehavior, MODIFIERS()> t;
|
||||
};
|
||||
|
||||
// Ref: [5.0:56-57], [5.1:60-62]
|
||||
//
|
||||
// default-clause ->
|
||||
// DEFAULT(directive-specification) // since 5.0, until 5.1
|
||||
// See also otherwise-clause.
|
||||
struct OmpDefaultVariantClause {
|
||||
WRAPPER_CLASS_BOILERPLATE(
|
||||
OmpDefaultVariantClause, common::Indirection<OmpDirectiveSpecification>);
|
||||
};
|
||||
|
||||
// Ref: [4.5:169-172], [5.0:255-259], [5.1:288-292], [5.2:91-93]
|
||||
//
|
||||
// iteration-offset ->
|
||||
|
|
|
|||
|
|
@ -649,13 +649,11 @@ Copyprivate make(const parser::OmpClause::Copyprivate &inp,
|
|||
return Copyprivate{/*List=*/makeObjects(inp.v, semaCtx)};
|
||||
}
|
||||
|
||||
// The Default clause is overloaded in OpenMP 5.0 and 5.1: it can be either
|
||||
// a data-sharing clause, or a METADIRECTIVE clause. In the latter case, it
|
||||
// has been superseded by the OTHERWISE clause.
|
||||
// Disambiguate this in this representation: for the DSA case, create Default,
|
||||
// and in the other case create Otherwise.
|
||||
Default makeDefault(const parser::OmpClause::Default &inp,
|
||||
semantics::SemanticsContext &semaCtx) {
|
||||
// The DEFAULT clause is OpenMP 5.0 and 5.1 that represents the default
|
||||
// directive variant in METADIRECTIVE is represented by the DefaultVariant
|
||||
// class.
|
||||
Default make(const parser::OmpClause::Default &inp,
|
||||
semantics::SemanticsContext &semaCtx) {
|
||||
// inp.v -> parser::OmpDefaultClause
|
||||
using wrapped = parser::OmpDefaultClause;
|
||||
|
||||
|
|
@ -669,11 +667,12 @@ Default makeDefault(const parser::OmpClause::Default &inp,
|
|||
// clang-format on
|
||||
);
|
||||
|
||||
auto dsa = std::get<wrapped::DataSharingAttribute>(inp.v.u);
|
||||
return Default{/*DataSharingAttribute=*/convert(dsa)};
|
||||
return Default{/*DataSharingAttribute=*/convert(inp.v.v)};
|
||||
}
|
||||
|
||||
Otherwise makeOtherwise(const parser::OmpClause::Default &inp,
|
||||
// Lower the DefaultVariant (specific to OpenMP 5.0 and 5.1) directly to
|
||||
// OTHERWISE (which replaced it since 5.2).
|
||||
Otherwise makeOtherwise(const parser::OmpClause::DefaultVariant &inp,
|
||||
semantics::SemanticsContext &semaCtx) {
|
||||
return Otherwise{};
|
||||
}
|
||||
|
|
@ -1806,18 +1805,9 @@ Clause makeClause(const parser::OmpClause &cls,
|
|||
semantics::SemanticsContext &semaCtx) {
|
||||
return Fortran::common::visit( //
|
||||
common::visitors{
|
||||
[&](const parser::OmpClause::Default &s) {
|
||||
using DSA = parser::OmpDefaultClause::DataSharingAttribute;
|
||||
using ODS = common::Indirection<parser::OmpDirectiveSpecification>;
|
||||
if (std::holds_alternative<DSA>(s.v.u)) {
|
||||
return makeClause(llvm::omp::Clause::OMPC_default,
|
||||
clause::makeDefault(s, semaCtx), cls.source);
|
||||
} else if (std::holds_alternative<ODS>(s.v.u)) {
|
||||
return makeClause(llvm::omp::Clause::OMPC_otherwise,
|
||||
clause::makeOtherwise(s, semaCtx), cls.source);
|
||||
} else {
|
||||
llvm_unreachable("Unexpected alternative");
|
||||
}
|
||||
[&](const parser::OmpClause::DefaultVariant &s) {
|
||||
return makeClause(llvm::omp::Clause::OMPC_default_variant,
|
||||
clause::makeOtherwise(s, semaCtx), cls.source);
|
||||
},
|
||||
[&](const parser::OmpClause::Depend &s) {
|
||||
using TaskDep = parser::OmpDependClause::TaskDep;
|
||||
|
|
|
|||
|
|
@ -6019,12 +6019,10 @@ static void genMetadirective(lower::AbstractConverter &converter,
|
|||
std::get_if<parser::OmpClause::Otherwise>(&clause.u)) {
|
||||
if (otherwiseClause->v && otherwiseClause->v->v)
|
||||
fallback = getFallbackVariant(otherwiseClause->v->v->value());
|
||||
} else if (const auto *defaultClause =
|
||||
std::get_if<parser::OmpClause::Default>(&clause.u)) {
|
||||
if (const auto *dirSpecPtr = std::get_if<
|
||||
common::Indirection<parser::OmpDirectiveSpecification>>(
|
||||
&defaultClause->v.u))
|
||||
fallback = getFallbackVariant(dirSpecPtr->value());
|
||||
} else if (const auto *defaultVariantClause =
|
||||
std::get_if<parser::OmpClause::DefaultVariant>(&clause.u)) {
|
||||
const auto &dirSpec = defaultVariantClause->v.v;
|
||||
fallback = getFallbackVariant(dirSpec.value());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1215,10 +1215,10 @@ TYPE_PARSER(construct<OmpDefaultClause::DataSharingAttribute>(
|
|||
"NONE" >> pure(OmpDefaultClause::DataSharingAttribute::None)))
|
||||
|
||||
TYPE_PARSER(construct<OmpDefaultClause>(
|
||||
construct<OmpDefaultClause>(
|
||||
Parser<OmpDefaultClause::DataSharingAttribute>{}) ||
|
||||
construct<OmpDefaultClause>(
|
||||
indirect(OmpDirectiveSpecificationParser(/*allowCommas=*/false)))))
|
||||
Parser<OmpDefaultClause::DataSharingAttribute>{}))
|
||||
|
||||
TYPE_PARSER(construct<OmpDefaultVariantClause>(
|
||||
indirect(OmpDirectiveSpecificationParser(/*allowCommas=*/false))))
|
||||
|
||||
TYPE_PARSER(construct<OmpDynGroupprivateClause>(
|
||||
maybe(nonemptyList(Parser<OmpDynGroupprivateClause::Modifier>{}) / ":"),
|
||||
|
|
@ -1521,8 +1521,12 @@ TYPE_PARSER( //
|
|||
parenthesized(Parser<OmpObjectList>{}))) ||
|
||||
"COPYPRIVATE" >> construct<OmpClause>(construct<OmpClause::Copyprivate>(
|
||||
(parenthesized(Parser<OmpObjectList>{})))) ||
|
||||
"DEFAULT"_id >> construct<OmpClause>(construct<OmpClause::Default>(
|
||||
parenthesized(Parser<OmpDefaultClause>{}))) ||
|
||||
"DEFAULT"_id >>
|
||||
// Default or DefaultVariant depending on the argument.
|
||||
(construct<OmpClause>(construct<OmpClause::Default>(
|
||||
parenthesized(Parser<OmpDefaultClause>{}))) ||
|
||||
construct<OmpClause>(construct<OmpClause::DefaultVariant>(
|
||||
parenthesized(Parser<OmpDefaultVariantClause>{})))) ||
|
||||
"DEFAULTMAP" >> construct<OmpClause>(construct<OmpClause::Defaultmap>(
|
||||
parenthesized(Parser<OmpDefaultmapClause>{}))) ||
|
||||
"DEPEND" >> construct<OmpClause>(construct<OmpClause::Depend>(
|
||||
|
|
|
|||
|
|
@ -54,8 +54,7 @@ bool HasDefaultNone(const parser::OmpDirectiveSpecification &spec) {
|
|||
return false;
|
||||
}
|
||||
const auto &defaultClause{std::get<parser::OmpClause::Default>(clause->u)};
|
||||
const auto *dsa{std::get_if<DataSharingAttribute>(&defaultClause.v.u)};
|
||||
return dsa && *dsa == DataSharingAttribute::None;
|
||||
return defaultClause.v.v == DataSharingAttribute::None;
|
||||
}
|
||||
|
||||
bool HasNestedPrivateDSA(const Symbol &symbol, const Scope &scope) {
|
||||
|
|
|
|||
|
|
@ -2511,22 +2511,20 @@ void OmpAttributeVisitor::Post(const parser::OmpDefaultClause &x) {
|
|||
// The DEFAULT clause may also be used on METADIRECTIVE. In that case
|
||||
// there is nothing to do.
|
||||
using DataSharingAttribute = parser::OmpDefaultClause::DataSharingAttribute;
|
||||
if (auto *dsa{std::get_if<DataSharingAttribute>(&x.u)}) {
|
||||
if (!dirContext_.empty()) {
|
||||
switch (*dsa) {
|
||||
case DataSharingAttribute::Private:
|
||||
SetContextDefaultDSA(Symbol::Flag::OmpPrivate);
|
||||
break;
|
||||
case DataSharingAttribute::Firstprivate:
|
||||
SetContextDefaultDSA(Symbol::Flag::OmpFirstPrivate);
|
||||
break;
|
||||
case DataSharingAttribute::Shared:
|
||||
SetContextDefaultDSA(Symbol::Flag::OmpShared);
|
||||
break;
|
||||
case DataSharingAttribute::None:
|
||||
SetContextDefaultDSA(Symbol::Flag::OmpNone);
|
||||
break;
|
||||
}
|
||||
if (!dirContext_.empty()) {
|
||||
switch (x.v) {
|
||||
case DataSharingAttribute::Private:
|
||||
SetContextDefaultDSA(Symbol::Flag::OmpPrivate);
|
||||
break;
|
||||
case DataSharingAttribute::Firstprivate:
|
||||
SetContextDefaultDSA(Symbol::Flag::OmpFirstPrivate);
|
||||
break;
|
||||
case DataSharingAttribute::Shared:
|
||||
SetContextDefaultDSA(Symbol::Flag::OmpShared);
|
||||
break;
|
||||
case DataSharingAttribute::None:
|
||||
SetContextDefaultDSA(Symbol::Flag::OmpNone);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@ end
|
|||
!PARSE-TREE: | | OmpDirectiveSpecification
|
||||
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = nothing
|
||||
!PARSE-TREE: | | | OmpClauseList ->
|
||||
!PARSE-TREE: | OmpClause -> Default -> OmpDefaultClause -> OmpDirectiveSpecification
|
||||
!PARSE-TREE: | OmpClause -> DefaultVariant -> OmpDefaultVariantClause -> OmpDirectiveSpecification
|
||||
!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = nothing
|
||||
!PARSE-TREE: | | OmpClauseList ->
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ class Clause<list<Spelling> ss> {
|
|||
// Spellings of the clause.
|
||||
list<Spelling> spellings = ss;
|
||||
|
||||
// Optional name for the generated enum (if different from spelling).
|
||||
string name = ?;
|
||||
|
||||
// Optional class holding value of the clause in clang AST.
|
||||
string clangClass = "";
|
||||
|
||||
|
|
@ -227,6 +230,9 @@ class Directive<list<Spelling> ss> {
|
|||
// Spellings of the directive.
|
||||
list<Spelling> spellings = ss;
|
||||
|
||||
// Optional name for the generated enum (if different from spelling).
|
||||
string name = ?;
|
||||
|
||||
// Clauses cannot appear twice in the three allowed lists below. Also, since
|
||||
// required implies allowed, the same clause cannot appear in both the
|
||||
// allowedClauses and requiredClauses lists.
|
||||
|
|
|
|||
|
|
@ -147,6 +147,8 @@ def OMPC_Counts : Clause<[Spelling<"counts">]> {
|
|||
let clangClass = "OMPCountsClause";
|
||||
}
|
||||
def OMPC_Default : Clause<[Spelling<"default">]> {
|
||||
// This is for default DSA.
|
||||
// For the "otherwise" clause, use OMPC_DefaultVariant.
|
||||
let clangClass = "OMPDefaultClause";
|
||||
let flangClass = "OmpDefaultClause";
|
||||
}
|
||||
|
|
@ -154,6 +156,10 @@ def OMPC_DefaultMap : Clause<[Spelling<"defaultmap">]> {
|
|||
let clangClass = "OMPDefaultmapClause";
|
||||
let flangClass = "OmpDefaultmapClause";
|
||||
}
|
||||
def OMPC_DefaultVariant : Clause<[Spelling<"default">]> {
|
||||
let name = "default_variant";
|
||||
let flangClass = "OmpDefaultVariantClause";
|
||||
}
|
||||
def OMPC_Depend : Clause<[Spelling<"depend">]> {
|
||||
let clangClass = "OMPDependClause";
|
||||
let flangClass = "OmpDependClause";
|
||||
|
|
@ -1056,7 +1062,7 @@ def OMP_Metadirective : Directive<[Spelling<"metadirective">]> {
|
|||
VersionedClause<OMPC_When>,
|
||||
];
|
||||
let allowedOnceClauses = [
|
||||
VersionedClause<OMPC_Default, 50, 51>,
|
||||
VersionedClause<OMPC_DefaultVariant, 50, 51>,
|
||||
VersionedClause<OMPC_Otherwise, 52>,
|
||||
];
|
||||
let association = AS_None;
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ public:
|
|||
// ex: async -> Async
|
||||
// num_threads -> NumThreads
|
||||
std::string getFormattedParserClassName() const {
|
||||
StringRef Name = getSpellingForIdentifier();
|
||||
std::string Name = getFormattedName();
|
||||
return BaseRecord::getUpperCamelName(Name, "_");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -460,6 +460,15 @@ static void generateGetKind(ArrayRef<const Record *> Records, raw_ostream &OS,
|
|||
|
||||
directive::VersionRange All;
|
||||
|
||||
// When a given spelling maps to more than one enum kind, this function
|
||||
// will return one of them, but it's unspecified which one.
|
||||
// This can happen whem a directive/clause uses the same spelling as
|
||||
// another directive/clause, e.g. when it varies depending on the version:
|
||||
// OMPC_foo : {"foo", v1.0}, {"bar", v2.0}
|
||||
// OMPC_bar : {"bar", v1.0}, {"baz", v2.0}
|
||||
// or when the same spelling can be used to mean different things:
|
||||
// OMPC_do_one_thing : {"doit"}
|
||||
// OMPC_do_something_else : {"doit"}
|
||||
for (const Record *R : Records) {
|
||||
BaseRecord Rec(R);
|
||||
std::string Ident = ImplicitAsUnknown && R->getValueAsBit("isImplicit")
|
||||
|
|
|
|||
Loading…
Reference in a new issue