1818#include "flang/Parser/openmp-utils.h"
1919#include "flang/Parser/parse-tree.h"
2020#include "llvm/ADT/ArrayRef.h"
21+ #include "llvm/ADT/Bitset.h"
2122#include "llvm/ADT/STLExtras.h"
2223#include "llvm/ADT/StringRef.h"
2324#include "llvm/ADT/StringSet.h"
2425#include "llvm/Frontend/OpenMP/OMP.h"
26+ #include "llvm/Support/MathExtras.h"
27+
28+ #include <algorithm>
29+ #include <cctype>
30+ #include <iterator>
31+ #include <list>
32+ #include <optional>
33+ #include <string>
34+ #include <tuple>
35+ #include <type_traits>
36+ #include <utility>
37+ #include <variant>
38+ #include <vector>
2539
2640// OpenMP Directives and Clauses
2741namespace Fortran::parser {
2842using namespace Fortran::parser::omp;
2943
44+ static constexpr size_t DirectiveCount{
45+ static_cast<size_t>(llvm::omp::Directive::Last_) -
46+ static_cast<size_t>(llvm::omp::Directive::First_) + 1};
47+ using DirectiveSet = llvm::Bitset<llvm::NextPowerOf2(DirectiveCount)>;
48+
3049// Helper function to print the buffer contents starting at the current point.
3150[[maybe_unused]] static std::string ahead(const ParseState &state) {
3251 return std::string(
@@ -1349,95 +1368,46 @@ TYPE_PARSER(sourced(construct<OpenMPUtilityConstruct>(
13491368TYPE_PARSER(sourced(construct<OmpMetadirectiveDirective>(
13501369 verbatim("METADIRECTIVE"_tok), Parser<OmpClauseList>{})))
13511370
1352- // Omp directives enclosing do loop
1353- TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
1354- "DISTRIBUTE PARALLEL DO SIMD" >>
1355- pure(llvm::omp::Directive::OMPD_distribute_parallel_do_simd),
1356- "DISTRIBUTE PARALLEL DO" >>
1357- pure(llvm::omp::Directive::OMPD_distribute_parallel_do),
1358- "DISTRIBUTE SIMD" >> pure(llvm::omp::Directive::OMPD_distribute_simd),
1359- "DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_distribute),
1360- "DO SIMD" >> pure(llvm::omp::Directive::OMPD_do_simd),
1361- "DO" >> pure(llvm::omp::Directive::OMPD_do),
1362- "LOOP" >> pure(llvm::omp::Directive::OMPD_loop),
1363- "MASKED TASKLOOP SIMD" >>
1364- pure(llvm::omp::Directive::OMPD_masked_taskloop_simd),
1365- "MASKED TASKLOOP" >> pure(llvm::omp::Directive::OMPD_masked_taskloop),
1366- "MASTER TASKLOOP SIMD" >>
1367- pure(llvm::omp::Directive::OMPD_master_taskloop_simd),
1368- "MASTER TASKLOOP" >> pure(llvm::omp::Directive::OMPD_master_taskloop),
1369- "PARALLEL DO SIMD" >> pure(llvm::omp::Directive::OMPD_parallel_do_simd),
1370- "PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_parallel_do),
1371- "PARALLEL MASKED TASKLOOP SIMD" >>
1372- pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd),
1373- "PARALLEL MASKED TASKLOOP" >>
1374- pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop),
1375- "PARALLEL MASTER TASKLOOP SIMD" >>
1376- pure(llvm::omp::Directive::OMPD_parallel_master_taskloop_simd),
1377- "PARALLEL MASTER TASKLOOP" >>
1378- pure(llvm::omp::Directive::OMPD_parallel_master_taskloop),
1379- "SIMD" >> pure(llvm::omp::Directive::OMPD_simd),
1380- "TARGET LOOP" >> pure(llvm::omp::Directive::OMPD_target_loop),
1381- "TARGET PARALLEL DO SIMD" >>
1382- pure(llvm::omp::Directive::OMPD_target_parallel_do_simd),
1383- "TARGET PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_target_parallel_do),
1384- "TARGET PARALLEL LOOP" >>
1385- pure(llvm::omp::Directive::OMPD_target_parallel_loop),
1386- "TARGET SIMD" >> pure(llvm::omp::Directive::OMPD_target_simd),
1387- "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
1388- pure(llvm::omp::Directive::
1389- OMPD_target_teams_distribute_parallel_do_simd),
1390- "TARGET TEAMS DISTRIBUTE PARALLEL DO" >>
1391- pure(llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do),
1392- "TARGET TEAMS DISTRIBUTE SIMD" >>
1393- pure(llvm::omp::Directive::OMPD_target_teams_distribute_simd),
1394- "TARGET TEAMS DISTRIBUTE" >>
1395- pure(llvm::omp::Directive::OMPD_target_teams_distribute),
1396- "TARGET TEAMS LOOP" >> pure(llvm::omp::Directive::OMPD_target_teams_loop),
1397- "TASKLOOP SIMD" >> pure(llvm::omp::Directive::OMPD_taskloop_simd),
1398- "TASKLOOP" >> pure(llvm::omp::Directive::OMPD_taskloop),
1399- "TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
1400- pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd),
1401- "TEAMS DISTRIBUTE PARALLEL DO" >>
1402- pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do),
1403- "TEAMS DISTRIBUTE SIMD" >>
1404- pure(llvm::omp::Directive::OMPD_teams_distribute_simd),
1405- "TEAMS DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_teams_distribute),
1406- "TEAMS LOOP" >> pure(llvm::omp::Directive::OMPD_teams_loop),
1407- "TILE" >> pure(llvm::omp::Directive::OMPD_tile),
1408- "UNROLL" >> pure(llvm::omp::Directive::OMPD_unroll)))))
1409-
1410- TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>(
1411- sourced(Parser<OmpLoopDirective>{}), Parser<OmpClauseList>{})))
1412-
14131371static inline constexpr auto IsDirective(llvm::omp::Directive dir) {
14141372 return [dir](const OmpDirectiveName &name) -> bool { return dir == name.v; };
14151373}
14161374
1375+ static inline constexpr auto IsMemberOf(const DirectiveSet &dirs) {
1376+ return [&dirs](const OmpDirectiveName &name) -> bool {
1377+ return dirs.test(llvm::to_underlying(name.v));
1378+ };
1379+ }
1380+
14171381struct OmpBeginDirectiveParser {
14181382 using resultType = OmpDirectiveSpecification;
14191383
1420- constexpr OmpBeginDirectiveParser(llvm::omp::Directive dir) : dir_(dir) {}
1384+ constexpr OmpBeginDirectiveParser(DirectiveSet dirs) : dirs_(dirs) {}
1385+ constexpr OmpBeginDirectiveParser(llvm::omp::Directive dir) {
1386+ dirs_.set(llvm::to_underlying(dir));
1387+ }
14211388
14221389 std::optional<resultType> Parse(ParseState &state) const {
1423- auto &&p{predicated(Parser<OmpDirectiveName>{}, IsDirective(dir_ )) >=
1390+ auto &&p{predicated(Parser<OmpDirectiveName>{}, IsMemberOf(dirs_ )) >=
14241391 Parser<OmpDirectiveSpecification>{}};
14251392 return p.Parse(state);
14261393 }
14271394
14281395private:
1429- llvm::omp::Directive dir_ ;
1396+ DirectiveSet dirs_ ;
14301397};
14311398
14321399struct OmpEndDirectiveParser {
14331400 using resultType = OmpDirectiveSpecification;
14341401
1435- constexpr OmpEndDirectiveParser(llvm::omp::Directive dir) : dir_(dir) {}
1402+ constexpr OmpEndDirectiveParser(DirectiveSet dirs) : dirs_(dirs) {}
1403+ constexpr OmpEndDirectiveParser(llvm::omp::Directive dir) {
1404+ dirs_.set(llvm::to_underlying(dir));
1405+ }
14361406
14371407 std::optional<resultType> Parse(ParseState &state) const {
14381408 if (startOmpLine.Parse(state)) {
14391409 if (auto endToken{verbatim("END"_sptok).Parse(state)}) {
1440- if (auto &&dirSpec{OmpBeginDirectiveParser(dir_ ).Parse(state)}) {
1410+ if (auto &&dirSpec{OmpBeginDirectiveParser(dirs_ ).Parse(state)}) {
14411411 // Extend the "source" on both the OmpDirectiveName and the
14421412 // OmpDirectiveNameSpecification.
14431413 CharBlock &nameSource{std::get<OmpDirectiveName>(dirSpec->t).source};
@@ -1451,7 +1421,7 @@ struct OmpEndDirectiveParser {
14511421 }
14521422
14531423private:
1454- llvm::omp::Directive dir_ ;
1424+ DirectiveSet dirs_ ;
14551425};
14561426
14571427struct OmpStatementConstructParser {
@@ -1946,11 +1916,56 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
19461916 construct<OpenMPConstruct>(Parser<OpenMPAssumeConstruct>{}),
19471917 construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{}))))
19481918
1919+ static constexpr DirectiveSet GetLoopDirectives() {
1920+ using Directive = llvm::omp::Directive;
1921+ constexpr DirectiveSet loopDirectives{
1922+ unsigned(Directive::OMPD_distribute),
1923+ unsigned(Directive::OMPD_distribute_parallel_do),
1924+ unsigned(Directive::OMPD_distribute_parallel_do_simd),
1925+ unsigned(Directive::OMPD_distribute_simd),
1926+ unsigned(Directive::OMPD_do),
1927+ unsigned(Directive::OMPD_do_simd),
1928+ unsigned(Directive::OMPD_loop),
1929+ unsigned(Directive::OMPD_masked_taskloop),
1930+ unsigned(Directive::OMPD_masked_taskloop_simd),
1931+ unsigned(Directive::OMPD_master_taskloop),
1932+ unsigned(Directive::OMPD_master_taskloop_simd),
1933+ unsigned(Directive::OMPD_parallel_do),
1934+ unsigned(Directive::OMPD_parallel_do_simd),
1935+ unsigned(Directive::OMPD_parallel_masked_taskloop),
1936+ unsigned(Directive::OMPD_parallel_masked_taskloop_simd),
1937+ unsigned(Directive::OMPD_parallel_master_taskloop),
1938+ unsigned(Directive::OMPD_parallel_master_taskloop_simd),
1939+ unsigned(Directive::OMPD_simd),
1940+ unsigned(Directive::OMPD_target_loop),
1941+ unsigned(Directive::OMPD_target_parallel_do),
1942+ unsigned(Directive::OMPD_target_parallel_do_simd),
1943+ unsigned(Directive::OMPD_target_parallel_loop),
1944+ unsigned(Directive::OMPD_target_simd),
1945+ unsigned(Directive::OMPD_target_teams_distribute),
1946+ unsigned(Directive::OMPD_target_teams_distribute_parallel_do),
1947+ unsigned(Directive::OMPD_target_teams_distribute_parallel_do_simd),
1948+ unsigned(Directive::OMPD_target_teams_distribute_simd),
1949+ unsigned(Directive::OMPD_target_teams_loop),
1950+ unsigned(Directive::OMPD_taskloop),
1951+ unsigned(Directive::OMPD_taskloop_simd),
1952+ unsigned(Directive::OMPD_teams_distribute),
1953+ unsigned(Directive::OMPD_teams_distribute_parallel_do),
1954+ unsigned(Directive::OMPD_teams_distribute_parallel_do_simd),
1955+ unsigned(Directive::OMPD_teams_distribute_simd),
1956+ unsigned(Directive::OMPD_teams_loop),
1957+ unsigned(Directive::OMPD_tile),
1958+ unsigned(Directive::OMPD_unroll),
1959+ };
1960+ return loopDirectives;
1961+ }
1962+
1963+ TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>(
1964+ sourced(OmpBeginDirectiveParser(GetLoopDirectives())))))
1965+
19491966// END OMP Loop directives
1950- TYPE_PARSER(
1951- startOmpLine >> sourced(construct<OmpEndLoopDirective>(
1952- sourced("END"_tok >> Parser<OmpLoopDirective>{}),
1953- Parser<OmpClauseList>{})))
1967+ TYPE_PARSER(sourced(construct<OmpEndLoopDirective>(
1968+ sourced(OmpEndDirectiveParser(GetLoopDirectives())))))
19541969
19551970TYPE_PARSER(construct<OpenMPLoopConstruct>(
19561971 Parser<OmpBeginLoopDirective>{} / endOmpLine))
0 commit comments