Skip to content

Commit 1d7960a

Browse files
committed
[Flang][OpenMP][OpenACC] Add function for mapping parser clause classes with the corresponding clause kind.
1. Generate the mapping for clauses between the parser class and the corresponding clause kind for OpenMP and OpenACC using tablegen. 2. Add a common function to get the OmpObjectList from the OpenMP clauses to avoid repetition of code. Reviewed by: Kiranchandramohan @kiranchandramohan , Valentin Clement @clementval Differential Revision: https://reviews.llvm.org/D98603
1 parent f7be9db commit 1d7960a

File tree

4 files changed

+116
-74
lines changed

4 files changed

+116
-74
lines changed

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 63 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -840,51 +840,36 @@ void OmpStructureChecker::CheckReductionArraySection(
840840

841841
void OmpStructureChecker::CheckMultipleAppearanceAcrossContext(
842842
const parser::OmpObjectList &redObjectList) {
843-
const parser::OmpObjectList *objList{nullptr};
844843
// TODO: Verify the assumption here that the immediately enclosing region is
845844
// the parallel region to which the worksharing construct having reduction
846845
// binds to.
847846
if (auto *enclosingContext{GetEnclosingDirContext()}) {
848847
for (auto it : enclosingContext->clauseInfo) {
849848
llvmOmpClause type = it.first;
850849
const auto *clause = it.second;
851-
if (type == llvm::omp::Clause::OMPC_private) {
852-
const auto &pClause{std::get<parser::OmpClause::Private>(clause->u)};
853-
objList = &pClause.v;
854-
} else if (type == llvm::omp::Clause::OMPC_firstprivate) {
855-
const auto &fpClause{
856-
std::get<parser::OmpClause::Firstprivate>(clause->u)};
857-
objList = &fpClause.v;
858-
} else if (type == llvm::omp::Clause::OMPC_lastprivate) {
859-
const auto &lpClause{
860-
std::get<parser::OmpClause::Lastprivate>(clause->u)};
861-
objList = &lpClause.v;
862-
} else if (type == llvm::omp::Clause::OMPC_reduction) {
863-
const auto &rClause{std::get<parser::OmpClause::Reduction>(clause->u)};
864-
const auto &olist{std::get<1>(rClause.v.t)};
865-
objList = &olist;
866-
}
867-
if (objList) {
868-
for (const auto &ompObject : objList->v) {
869-
if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
870-
if (const auto *symbol{name->symbol}) {
871-
for (const auto &redOmpObject : redObjectList.v) {
872-
if (const auto *rname{
873-
parser::Unwrap<parser::Name>(redOmpObject)}) {
874-
if (const auto *rsymbol{rname->symbol}) {
875-
if (rsymbol->name() == symbol->name()) {
876-
context_.Say(GetContext().clauseSource,
877-
"%s variable '%s' is %s in outer context must"
878-
" be shared in the parallel regions to which any"
879-
" of the worksharing regions arising from the "
880-
"worksharing"
881-
" construct bind."_err_en_US,
882-
parser::ToUpperCaseLetters(
883-
getClauseName(llvm::omp::Clause::OMPC_reduction)
884-
.str()),
885-
symbol->name(),
886-
parser::ToUpperCaseLetters(
887-
getClauseName(type).str()));
850+
if (llvm::omp::privateReductionSet.test(type)) {
851+
if (const auto *objList{GetOmpObjectList(*clause)}) {
852+
for (const auto &ompObject : objList->v) {
853+
if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
854+
if (const auto *symbol{name->symbol}) {
855+
for (const auto &redOmpObject : redObjectList.v) {
856+
if (const auto *rname{
857+
parser::Unwrap<parser::Name>(redOmpObject)}) {
858+
if (const auto *rsymbol{rname->symbol}) {
859+
if (rsymbol->name() == symbol->name()) {
860+
context_.Say(GetContext().clauseSource,
861+
"%s variable '%s' is %s in outer context must"
862+
" be shared in the parallel regions to which any"
863+
" of the worksharing regions arising from the "
864+
"worksharing"
865+
" construct bind."_err_en_US,
866+
parser::ToUpperCaseLetters(
867+
getClauseName(llvm::omp::Clause::OMPC_reduction)
868+
.str()),
869+
symbol->name(),
870+
parser::ToUpperCaseLetters(
871+
getClauseName(type).str()));
872+
}
888873
}
889874
}
890875
}
@@ -1213,7 +1198,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
12131198
DirectivesClauseTriple dirClauseTriple;
12141199
SymbolSourceMap currSymbols;
12151200
GetSymbolsInObjectList(x.v, currSymbols);
1216-
CheckDefinableObjects(currSymbols, llvm::omp::Clause::OMPC_lastprivate);
1201+
CheckDefinableObjects(currSymbols, GetClauseKindForParserClass(x));
12171202

12181203
// Check lastprivate variables in worksharing constructs
12191204
dirClauseTriple.emplace(llvm::omp::Directive::OMPD_do,
@@ -1224,7 +1209,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
12241209
llvm::omp::Directive::OMPD_parallel, llvm::omp::privateReductionSet));
12251210

12261211
CheckPrivateSymbolsInOuterCxt(
1227-
currSymbols, dirClauseTriple, llvm::omp::Clause::OMPC_lastprivate);
1212+
currSymbols, dirClauseTriple, GetClauseKindForParserClass(x));
12281213
}
12291214

12301215
llvm::StringRef OmpStructureChecker::getClauseName(llvm::omp::Clause clause) {
@@ -1368,40 +1353,11 @@ void OmpStructureChecker::CheckPrivateSymbolsInOuterCxt(
13681353
if (auto *enclosingContext{GetEnclosingContextWithDir(enclosingDir)}) {
13691354
for (auto it{enclosingContext->clauseInfo.begin()};
13701355
it != enclosingContext->clauseInfo.end(); ++it) {
1371-
// TODO: Replace the hard-coded clause names by using autogen checks or
1372-
// a function which maps parser::OmpClause::<name> to the corresponding
1373-
// llvm::omp::Clause::OMPC_<name>
1374-
std::visit(common::visitors{
1375-
[&](const parser::OmpClause::Private &x) {
1376-
if (enclosingClauseSet.test(
1377-
llvm::omp::Clause::OMPC_private)) {
1378-
GetSymbolsInObjectList(x.v, enclosingSymbols);
1379-
}
1380-
},
1381-
[&](const parser::OmpClause::Firstprivate &x) {
1382-
if (enclosingClauseSet.test(
1383-
llvm::omp::Clause::OMPC_firstprivate)) {
1384-
GetSymbolsInObjectList(x.v, enclosingSymbols);
1385-
}
1386-
},
1387-
[&](const parser::OmpClause::Lastprivate &x) {
1388-
if (enclosingClauseSet.test(
1389-
llvm::omp::Clause::OMPC_lastprivate)) {
1390-
GetSymbolsInObjectList(x.v, enclosingSymbols);
1391-
}
1392-
},
1393-
[&](const parser::OmpClause::Reduction &x) {
1394-
if (enclosingClauseSet.test(
1395-
llvm::omp::Clause::OMPC_reduction)) {
1396-
const auto &ompObjectList{
1397-
std::get<parser::OmpObjectList>(x.v.t)};
1398-
GetSymbolsInObjectList(
1399-
ompObjectList, enclosingSymbols);
1400-
}
1401-
},
1402-
[&](const auto &) {},
1403-
},
1404-
it->second->u);
1356+
if (enclosingClauseSet.test(it->first)) {
1357+
if (const auto *ompObjectList{GetOmpObjectList(*it->second)}) {
1358+
GetSymbolsInObjectList(*ompObjectList, enclosingSymbols);
1359+
}
1360+
}
14051361
}
14061362

14071363
// Check if the symbols in current context are private in outer context
@@ -1497,4 +1453,37 @@ void OmpStructureChecker::CheckWorkshareBlockStmts(
14971453
}
14981454
}
14991455

1456+
const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList(
1457+
const parser::OmpClause &clause) {
1458+
1459+
// Clauses with OmpObjectList as its data member
1460+
using MemberObjectListClauses = std::tuple<parser::OmpClause::Copyprivate,
1461+
parser::OmpClause::Copyin, parser::OmpClause::Firstprivate,
1462+
parser::OmpClause::From, parser::OmpClause::Lastprivate,
1463+
parser::OmpClause::Link, parser::OmpClause::Private,
1464+
parser::OmpClause::Shared, parser::OmpClause::To>;
1465+
1466+
// Clauses with OmpObjectList in the tuple
1467+
using TupleObjectListClauses = std::tuple<parser::OmpClause::Allocate,
1468+
parser::OmpClause::Map, parser::OmpClause::Reduction>;
1469+
1470+
// TODO:: Generate the tuples using TableGen.
1471+
// Handle other constructs with OmpObjectList such as OpenMPThreadprivate.
1472+
return std::visit(
1473+
common::visitors{
1474+
[&](const auto &x) -> const parser::OmpObjectList * {
1475+
using Ty = std::decay_t<decltype(x)>;
1476+
if constexpr (common::HasMember<Ty, MemberObjectListClauses>) {
1477+
return &x.v;
1478+
} else if constexpr (common::HasMember<Ty,
1479+
TupleObjectListClauses>) {
1480+
return &(std::get<parser::OmpObjectList>(x.v.t));
1481+
} else {
1482+
return nullptr;
1483+
}
1484+
},
1485+
},
1486+
clause.u);
1487+
}
1488+
15001489
} // namespace Fortran::semantics

flang/lib/Semantics/check-omp-structure.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,13 @@ class OmpStructureChecker
153153
#define GEN_FLANG_CLAUSE_CHECK_ENTER
154154
#include "llvm/Frontend/OpenMP/OMP.inc"
155155

156+
// Get the OpenMP Clause Kind for the corresponding Parser class
157+
template <typename A>
158+
llvm::omp::Clause GetClauseKindForParserClass(const A &) {
159+
#define GEN_FLANG_CLAUSE_PARSER_KIND_MAP
160+
#include "llvm/Frontend/OpenMP/OMP.inc"
161+
}
162+
156163
private:
157164
bool HasInvalidWorksharingNesting(
158165
const parser::CharBlock &, const OmpDirectiveSet &);
@@ -197,6 +204,7 @@ class OmpStructureChecker
197204
const parser::Name &name, const llvm::omp::Clause clause);
198205
void CheckMultipleAppearanceAcrossContext(
199206
const parser::OmpObjectList &ompObjectList);
207+
const parser::OmpObjectList *GetOmpObjectList(const parser::OmpClause &);
200208
};
201209
} // namespace Fortran::semantics
202210
#endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_

llvm/test/TableGen/directive1.td

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,3 +256,23 @@ def TDL_DirA : Directive<"dira"> {
256256
// GEN-NEXT: }
257257
// GEN-EMPTY:
258258
// GEN-NEXT: #endif // GEN_FLANG_CLAUSE_UNPARSE
259+
// GEN-EMPTY:
260+
// GEN-NEXT: #ifdef GEN_FLANG_CLAUSE_CHECK_ENTER
261+
// GEN-NEXT: #undef GEN_FLANG_CLAUSE_CHECK_ENTER
262+
// GEN-EMPTY:
263+
// GEN-NEXT: void Enter(const parser::TdlClause::Clausea &);
264+
// GEN-NEXT: void Enter(const parser::TdlClause::Clauseb &);
265+
// GEN-EMPTY:
266+
// GEN-NEXT: #endif // GEN_FLANG_CLAUSE_CHECK_ENTER
267+
// GEN-EMPTY:
268+
// GEN-NEXT: #ifdef GEN_FLANG_CLAUSE_PARSER_KIND_MAP
269+
// GEN-NEXT: #undef GEN_FLANG_CLAUSE_PARSER_KIND_MAP
270+
// GEN-EMPTY:
271+
// GEN-NEXT: if constexpr (std::is_same_v<A, parser::TdlClause::Clausea>)
272+
// GEN-NEXT: return llvm::tdl::Clause::TDLC_clausea;
273+
// GEN-NEXT: if constexpr (std::is_same_v<A, parser::TdlClause::Clauseb>)
274+
// GEN-NEXT: return llvm::tdl::Clause::TDLC_clauseb;
275+
// GEN-NEXT: llvm_unreachable("Invalid Tdl Parser clause");
276+
// GEN-EMPTY:
277+
// GEN-NEXT: #endif // GEN_FLANG_CLAUSE_PARSER_KIND_MAP
278+
// GEN-EMPTY:

llvm/utils/TableGen/DirectiveEmitter.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,29 @@ void GenerateFlangClauseCheckPrototypes(const DirectiveLanguage &DirLang,
647647
}
648648
}
649649

650+
// Generate the mapping for clauses between the parser class and the
651+
// corresponding clause Kind
652+
void GenerateFlangClauseParserKindMap(const DirectiveLanguage &DirLang,
653+
raw_ostream &OS) {
654+
655+
IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_KIND_MAP", OS);
656+
657+
OS << "\n";
658+
for (const auto &C : DirLang.getClauses()) {
659+
Clause Clause{C};
660+
OS << "if constexpr (std::is_same_v<A, parser::"
661+
<< DirLang.getFlangClauseBaseClass()
662+
<< "::" << Clause.getFormattedParserClassName();
663+
OS << ">)\n";
664+
OS << " return llvm::" << DirLang.getCppNamespace()
665+
<< "::Clause::" << DirLang.getClausePrefix() << Clause.getFormattedName()
666+
<< ";\n";
667+
}
668+
669+
OS << "llvm_unreachable(\"Invalid " << DirLang.getName()
670+
<< " Parser clause\");\n";
671+
}
672+
650673
// Generate the implementation section for the enumeration in the directive
651674
// language
652675
void EmitDirectivesFlangImpl(const DirectiveLanguage &DirLang,
@@ -665,6 +688,8 @@ void EmitDirectivesFlangImpl(const DirectiveLanguage &DirLang,
665688
GenerateFlangClauseUnparse(DirLang, OS);
666689

667690
GenerateFlangClauseCheckPrototypes(DirLang, OS);
691+
692+
GenerateFlangClauseParserKindMap(DirLang, OS);
668693
}
669694

670695
void GenerateClauseClassMacro(const DirectiveLanguage &DirLang,

0 commit comments

Comments
 (0)