Skip to content

Commit 8035d38

Browse files
[Flang][OpenMP]Add parsing support for DISPATCH construct (#121982)
This allows the Flang parser to accept the !$OMP DISPATCH and related clauses. Lowering is currently not implemented. Tests for unparse and parse-tree dump is provided, and one for checking that the lowering ends in a "not yet implemented" --------- Co-authored-by: Kiran Chandramohan <[email protected]>
1 parent 850852e commit 8035d38

File tree

11 files changed

+192
-3
lines changed

11 files changed

+192
-3
lines changed

flang/include/flang/Parser/dump-parse-tree.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,9 @@ class ParseTreeDumper {
679679
NODE_ENUM(common, OmpAtomicDefaultMemOrderType)
680680
NODE(parser, OpenMPDepobjConstruct)
681681
NODE(parser, OpenMPUtilityConstruct)
682+
NODE(parser, OpenMPDispatchConstruct)
683+
NODE(parser, OmpDispatchDirective)
684+
NODE(parser, OmpEndDispatchDirective)
682685
NODE(parser, OpenMPFlushConstruct)
683686
NODE(parser, OpenMPLoopConstruct)
684687
NODE(parser, OpenMPExecutableAllocate)

flang/include/flang/Parser/parse-tree.h

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4685,6 +4685,31 @@ struct OpenMPDepobjConstruct {
46854685
std::tuple<Verbatim, OmpObject, OmpClause> t;
46864686
};
46874687

4688+
// Ref: [5.2: 200-201]
4689+
//
4690+
// dispatch-construct -> DISPATCH dispatch-clause
4691+
// dispatch-clause -> depend-clause |
4692+
// device-clause |
4693+
// is_device_ptr-clause |
4694+
// nocontext-clause |
4695+
// novariants-clause |
4696+
// nowait-clause
4697+
struct OmpDispatchDirective {
4698+
TUPLE_CLASS_BOILERPLATE(OmpDispatchDirective);
4699+
CharBlock source;
4700+
std::tuple<Verbatim, OmpClauseList> t;
4701+
};
4702+
4703+
EMPTY_CLASS(OmpEndDispatchDirective);
4704+
4705+
struct OpenMPDispatchConstruct {
4706+
TUPLE_CLASS_BOILERPLATE(OpenMPDispatchConstruct);
4707+
CharBlock source;
4708+
std::tuple<OmpDispatchDirective, Block,
4709+
std::optional<OmpEndDispatchDirective>>
4710+
t;
4711+
};
4712+
46884713
// 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)]
46894714
struct OpenMPFlushConstruct {
46904715
TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct);
@@ -4757,9 +4782,9 @@ struct OpenMPConstruct {
47574782
UNION_CLASS_BOILERPLATE(OpenMPConstruct);
47584783
std::variant<OpenMPStandaloneConstruct, OpenMPSectionsConstruct,
47594784
OpenMPSectionConstruct, OpenMPLoopConstruct, OpenMPBlockConstruct,
4760-
OpenMPAtomicConstruct, OpenMPDeclarativeAllocate, OpenMPUtilityConstruct,
4761-
OpenMPExecutableAllocate, OpenMPAllocatorsConstruct,
4762-
OpenMPCriticalConstruct>
4785+
OpenMPAtomicConstruct, OpenMPDeclarativeAllocate, OpenMPDispatchConstruct,
4786+
OpenMPUtilityConstruct, OpenMPExecutableAllocate,
4787+
OpenMPAllocatorsConstruct, OpenMPCriticalConstruct>
47634788
u;
47644789
};
47654790

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,9 @@ extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) {
381381
[](const parser::OpenMPDeclarativeAllocate &c) {
382382
return llvm::omp::OMPD_allocate;
383383
},
384+
[](const parser::OpenMPDispatchConstruct &c) {
385+
return llvm::omp::OMPD_dispatch;
386+
},
384387
[](const parser::OpenMPExecutableAllocate &c) {
385388
return llvm::omp::OMPD_allocate;
386389
},
@@ -3388,6 +3391,13 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
33883391
TODO(converter.getCurrentLocation(), "OpenMPUtilityConstruct");
33893392
}
33903393

3394+
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
3395+
semantics::SemanticsContext &semaCtx,
3396+
lower::pft::Evaluation &eval,
3397+
const parser::OpenMPDispatchConstruct &) {
3398+
TODO(converter.getCurrentLocation(), "OpenMPDispatchConstruct");
3399+
}
3400+
33913401
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
33923402
semantics::SemanticsContext &semaCtx,
33933403
lower::pft::Evaluation &eval,

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,11 +740,15 @@ TYPE_PARSER(
740740
"MERGEABLE" >> construct<OmpClause>(construct<OmpClause::Mergeable>()) ||
741741
"MESSAGE" >> construct<OmpClause>(construct<OmpClause::Message>(
742742
parenthesized(Parser<OmpMessageClause>{}))) ||
743+
"NOCONTEXT" >> construct<OmpClause>(construct<OmpClause::Nocontext>(
744+
parenthesized(scalarLogicalExpr))) ||
743745
"NOGROUP" >> construct<OmpClause>(construct<OmpClause::Nogroup>()) ||
744746
"NONTEMPORAL" >> construct<OmpClause>(construct<OmpClause::Nontemporal>(
745747
parenthesized(nonemptyList(name)))) ||
746748
"NOTINBRANCH" >>
747749
construct<OmpClause>(construct<OmpClause::Notinbranch>()) ||
750+
"NOVARIANTS" >> construct<OmpClause>(construct<OmpClause::Novariants>(
751+
parenthesized(scalarLogicalExpr))) ||
748752
"NOWAIT" >> construct<OmpClause>(construct<OmpClause::Nowait>()) ||
749753
"NUM_TASKS" >> construct<OmpClause>(construct<OmpClause::NumTasks>(
750754
parenthesized(Parser<OmpNumTasksClause>{}))) ||
@@ -1119,6 +1123,16 @@ TYPE_PARSER(sourced(construct<OmpCriticalDirective>(verbatim("CRITICAL"_tok),
11191123
TYPE_PARSER(construct<OpenMPCriticalConstruct>(
11201124
Parser<OmpCriticalDirective>{}, block, Parser<OmpEndCriticalDirective>{}))
11211125

1126+
TYPE_PARSER(sourced(construct<OmpDispatchDirective>(
1127+
verbatim("DISPATCH"_tok), Parser<OmpClauseList>{})))
1128+
1129+
TYPE_PARSER(
1130+
construct<OmpEndDispatchDirective>(startOmpLine >> "END DISPATCH"_tok))
1131+
1132+
TYPE_PARSER(sourced(construct<OpenMPDispatchConstruct>(
1133+
Parser<OmpDispatchDirective>{} / endOmpLine, block,
1134+
maybe(Parser<OmpEndDispatchDirective>{} / endOmpLine))))
1135+
11221136
// 2.11.3 Executable Allocate directive
11231137
TYPE_PARSER(
11241138
sourced(construct<OpenMPExecutableAllocate>(verbatim("ALLOCATE"_tok),
@@ -1219,6 +1233,7 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
12191233
construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
12201234
construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}),
12211235
construct<OpenMPConstruct>(Parser<OpenMPUtilityConstruct>{}),
1236+
construct<OpenMPConstruct>(Parser<OpenMPDispatchConstruct>{}),
12221237
construct<OpenMPConstruct>(Parser<OpenMPExecutableAllocate>{}),
12231238
construct<OpenMPConstruct>(Parser<OpenMPAllocatorsConstruct>{}),
12241239
construct<OpenMPConstruct>(Parser<OpenMPDeclarativeAllocate>{}),

flang/lib/Parser/unparse.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2725,6 +2725,15 @@ class UnparseVisitor {
27252725
Walk(x.v);
27262726
return false;
27272727
}
2728+
void Unparse(const OmpDispatchDirective &x) {
2729+
Word("!$OMP DISPATCH");
2730+
Walk(x.t);
2731+
Put("\n");
2732+
}
2733+
void Unparse(const OmpEndDispatchDirective &) {
2734+
Word("!$OMP END DISPATCH");
2735+
Put("\n");
2736+
}
27282737
void Unparse(const OmpErrorDirective &x) {
27292738
Word("!$OMP ERROR ");
27302739
Walk(x.t);

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,6 +1748,36 @@ void OmpStructureChecker::Enter(const parser::OmpErrorDirective &x) {
17481748
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_error);
17491749
}
17501750

1751+
void OmpStructureChecker::Enter(const parser::OpenMPDispatchConstruct &x) {
1752+
PushContextAndClauseSets(x.source, llvm::omp::Directive::OMPD_dispatch);
1753+
const auto &block{std::get<parser::Block>(x.t)};
1754+
if (block.empty() || block.size() > 1) {
1755+
context_.Say(x.source,
1756+
"The DISPATCH construct is empty or contains more than one statement"_err_en_US);
1757+
return;
1758+
}
1759+
1760+
auto it{block.begin()};
1761+
bool passChecks{false};
1762+
if (const parser::AssignmentStmt *
1763+
assignStmt{parser::Unwrap<parser::AssignmentStmt>(*it)}) {
1764+
if (parser::Unwrap<parser::FunctionReference>(assignStmt->t)) {
1765+
passChecks = true;
1766+
}
1767+
} else if (parser::Unwrap<parser::CallStmt>(*it)) {
1768+
passChecks = true;
1769+
}
1770+
1771+
if (!passChecks) {
1772+
context_.Say(x.source,
1773+
"The DISPATCH construct does not contain a SUBROUTINE or FUNCTION"_err_en_US);
1774+
}
1775+
}
1776+
1777+
void OmpStructureChecker::Leave(const parser::OpenMPDispatchConstruct &x) {
1778+
dirContext_.pop_back();
1779+
}
1780+
17511781
void OmpStructureChecker::Leave(const parser::OmpErrorDirective &x) {
17521782
dirContext_.pop_back();
17531783
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ class OmpStructureChecker
105105
void Enter(const parser::OmpDeclareTargetWithList &);
106106
void Enter(const parser::OmpDeclareTargetWithClause &);
107107
void Leave(const parser::OmpDeclareTargetWithClause &);
108+
void Enter(const parser::OpenMPDispatchConstruct &);
109+
void Leave(const parser::OpenMPDispatchConstruct &);
108110
void Enter(const parser::OmpErrorDirective &);
109111
void Leave(const parser::OmpErrorDirective &);
110112
void Enter(const parser::OpenMPExecutableAllocate &);

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,9 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
441441
bool Pre(const parser::OpenMPDeclarativeAllocate &);
442442
void Post(const parser::OpenMPDeclarativeAllocate &) { PopContext(); }
443443

444+
bool Pre(const parser::OpenMPDispatchConstruct &);
445+
void Post(const parser::OpenMPDispatchConstruct &) { PopContext(); }
446+
444447
bool Pre(const parser::OpenMPExecutableAllocate &);
445448
void Post(const parser::OpenMPExecutableAllocate &);
446449

@@ -1976,6 +1979,11 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclarativeAllocate &x) {
19761979
return false;
19771980
}
19781981

1982+
bool OmpAttributeVisitor::Pre(const parser::OpenMPDispatchConstruct &x) {
1983+
PushContext(x.source, llvm::omp::Directive::OMPD_dispatch);
1984+
return true;
1985+
}
1986+
19791987
bool OmpAttributeVisitor::Pre(const parser::OpenMPExecutableAllocate &x) {
19801988
PushContext(x.source, llvm::omp::Directive::OMPD_allocate);
19811989
const auto &list{std::get<std::optional<parser::OmpObjectList>>(x.t)};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
2+
3+
! CHECK: not yet implemented: OpenMPDispatchConstruct
4+
program p
5+
integer r
6+
r = 1
7+
!$omp dispatch nowait
8+
call foo()
9+
contains
10+
subroutine foo
11+
end subroutine
12+
end program p

flang/test/Parser/OpenMP/dispatch.f90

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
! RUN: %flang_fc1 -fopenmp -fdebug-dump-parse-tree %s | FileCheck %s
2+
! RUN: %flang_fc1 -fopenmp -fdebug-unparse %s | FileCheck %s --check-prefix="UNPARSE"
3+
4+
integer function func(a, b, c)
5+
integer :: a, b, c
6+
func = a + b + c
7+
end function func
8+
9+
subroutine sub(x)
10+
use iso_c_binding
11+
integer :: func
12+
integer :: r
13+
type(c_ptr) :: x
14+
integer :: a = 14, b = 7, c = 21
15+
!UNPARSE: !$OMP DISPATCH DEVICE(3_4) NOWAIT NOCONTEXT(.false._4) NOVARIANTS(.true._4)
16+
!CHECK: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPDispatchConstruct
17+
!CHECK-NEXT: | | | OmpDispatchDirective
18+
!CHECK: | | | | OmpClauseList -> OmpClause -> Device -> OmpDeviceClause
19+
!CHECK-NEXT: | | | | | Scalar -> Integer -> Expr = '3_4'
20+
!CHECK-NEXT: | | | | | | LiteralConstant -> IntLiteralConstant = '3'
21+
!CHECK-NEXT: | | | | OmpClause -> Nowait
22+
!CHECK-NEXT: | | | | OmpClause -> Nocontext -> Scalar -> Logical -> Expr = '.false._4'
23+
!CHECK-NEXT: | | | | | LiteralConstant -> LogicalLiteralConstant
24+
!CHECK-NEXT: | | | | | | bool = 'false'
25+
!CHECK-NEXT: | | | | OmpClause -> Novariants -> Scalar -> Logical -> Expr = '.true._4'
26+
!CHECK-NEXT: | | | | | EQ
27+
!CHECK-NEXT: | | | | | | Expr = '1_4'
28+
!CHECK-NEXT: | | | | | | | LiteralConstant -> IntLiteralConstant = '1'
29+
!CHECK-NEXT: | | | | | | Expr = '1_4'
30+
!CHECK-NEXT: | | | | | | | LiteralConstant -> IntLiteralConstant = '1'
31+
!CHECK-NEXT: | | | Block
32+
33+
!$omp dispatch device(3) nowait nocontext(.false.) novariants(1.eq.1)
34+
r = func(a, b, c)
35+
!UNPARSE: !$OMP END DISPATCH
36+
!CHECK: | | | OmpEndDispatchDirective
37+
!$omp end dispatch
38+
39+
!! Test the "no end dispatch" option.
40+
!UNPARSE: !$OMP DISPATCH DEVICE(3_4) IS_DEVICE_PTR(x)
41+
!CHECK: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPDispatchConstruct
42+
!CHECK-NEXT: | | | OmpDispatchDirective
43+
!CHECK: | | | | OmpClause -> IsDevicePtr -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
44+
!$omp dispatch device(3) is_device_ptr(x)
45+
r = func(a+1, b+2, c+3)
46+
!CHECK-NOT: | | | OmpEndDispatchDirective
47+
48+
end subroutine sub
49+
50+
51+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
! RUN: %python %S/../test_errors.py %s %flang -fopenmp
2+
3+
subroutine sb1
4+
integer :: r
5+
r = 1
6+
!ERROR: The DISPATCH construct does not contain a SUBROUTINE or FUNCTION
7+
!$omp dispatch nowait
8+
print *,r
9+
end subroutine
10+
subroutine sb2
11+
integer :: r
12+
!ERROR: The DISPATCH construct is empty or contains more than one statement
13+
!$omp dispatch
14+
call foo()
15+
r = bar()
16+
!$omp end dispatch
17+
contains
18+
subroutine foo
19+
end subroutine foo
20+
function bar
21+
integer :: bar
22+
bar = 2
23+
end function
24+
end subroutine

0 commit comments

Comments
 (0)