Skip to content

Commit f982443

Browse files
authored
[flang][OpenMP] Parse lastprivate modifier, add TODO to lowering (#110568)
Parse the lastprivate clause with a modifier. Codegen for it is not yet implemented.
1 parent 36dff0d commit f982443

File tree

14 files changed

+160
-19
lines changed

14 files changed

+160
-19
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@ class ParseTreeDumper {
522522
NODE(parser, OmpEndSectionsDirective)
523523
NODE(parser, OmpIfClause)
524524
NODE_ENUM(OmpIfClause, DirectiveNameModifier)
525+
NODE_ENUM(OmpLastprivateClause, LastprivateModifier)
526+
NODE(parser, OmpLastprivateClause)
525527
NODE(parser, OmpLinearClause)
526528
NODE(OmpLinearClause, WithModifier)
527529
NODE(OmpLinearClause, WithoutModifier)

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3648,6 +3648,15 @@ struct OmpAtomicDefaultMemOrderClause {
36483648
OmpAtomicDefaultMemOrderClause, common::OmpAtomicDefaultMemOrderType);
36493649
};
36503650

3651+
// OMP 5.0 2.19.4.5 lastprivate-clause ->
3652+
// LASTPRIVATE ([lastprivate-modifier :] list)
3653+
// lastprivate-modifier -> CONDITIONAL
3654+
struct OmpLastprivateClause {
3655+
TUPLE_CLASS_BOILERPLATE(OmpLastprivateClause);
3656+
ENUM_CLASS(LastprivateModifier, Conditional);
3657+
std::tuple<std::optional<LastprivateModifier>, OmpObjectList> t;
3658+
};
3659+
36513660
// OpenMP Clauses
36523661
struct OmpClause {
36533662
UNION_CLASS_BOILERPLATE(OmpClause);

flang/lib/Lower/OpenMP/Clauses.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -783,9 +783,22 @@ IsDevicePtr make(const parser::OmpClause::IsDevicePtr &inp,
783783

784784
Lastprivate make(const parser::OmpClause::Lastprivate &inp,
785785
semantics::SemanticsContext &semaCtx) {
786-
// inp.v -> parser::OmpObjectList
787-
return Lastprivate{{/*LastprivateModifier=*/std::nullopt,
788-
/*List=*/makeObjects(inp.v, semaCtx)}};
786+
// inp.v -> parser::OmpLastprivateClause
787+
using wrapped = parser::OmpLastprivateClause;
788+
789+
CLAUSET_ENUM_CONVERT( //
790+
convert, parser::OmpLastprivateClause::LastprivateModifier,
791+
Lastprivate::LastprivateModifier,
792+
// clang-format off
793+
MS(Conditional, Conditional)
794+
// clang-format on
795+
);
796+
797+
auto &t0 = std::get<std::optional<wrapped::LastprivateModifier>>(inp.v.t);
798+
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
799+
800+
return Lastprivate{{/*LastprivateModifier=*/maybeApply(convert, t0),
801+
/*List=*/makeObjects(t1, semaCtx)}};
789802
}
790803

791804
Linear make(const parser::OmpClause::Linear &inp,

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ void DataSharingProcessor::collectSymbolsForPrivatization() {
151151
explicitlyPrivatizedSymbols);
152152
} else if (const auto &lastPrivateClause =
153153
std::get_if<omp::clause::Lastprivate>(&clause.u)) {
154+
lastprivateModifierNotSupported(*lastPrivateClause,
155+
converter.getCurrentLocation());
154156
const ObjectList &objects = std::get<ObjectList>(lastPrivateClause->t);
155157
collectOmpObjectListSymbol(objects, explicitlyPrivatizedSymbols);
156158
}

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1563,7 +1563,9 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
15631563

15641564
for (const Clause &clause : item->clauses) {
15651565
if (clause.id == llvm::omp::Clause::OMPC_lastprivate) {
1566-
lastprivates.push_back(&std::get<clause::Lastprivate>(clause.u));
1566+
auto &lastp = std::get<clause::Lastprivate>(clause.u);
1567+
lastprivateModifierNotSupported(lastp, converter.getCurrentLocation());
1568+
lastprivates.push_back(&lastp);
15671569
} else {
15681570
switch (clause.id) {
15691571
case llvm::omp::Clause::OMPC_firstprivate:

flang/lib/Lower/OpenMP/Utils.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <flang/Lower/ConvertType.h>
1818
#include <flang/Lower/PFTBuilder.h>
1919
#include <flang/Optimizer/Builder/FIRBuilder.h>
20+
#include <flang/Optimizer/Builder/Todo.h>
2021
#include <flang/Parser/parse-tree.h>
2122
#include <flang/Parser/tools.h>
2223
#include <flang/Semantics/tools.h>
@@ -356,6 +357,18 @@ semantics::Symbol *getOmpObjectSymbol(const parser::OmpObject &ompObject) {
356357
return sym;
357358
}
358359

360+
void lastprivateModifierNotSupported(const omp::clause::Lastprivate &lastp,
361+
mlir::Location loc) {
362+
using Lastprivate = omp::clause::Lastprivate;
363+
auto &maybeMod =
364+
std::get<std::optional<Lastprivate::LastprivateModifier>>(lastp.t);
365+
if (maybeMod) {
366+
assert(*maybeMod == Lastprivate::LastprivateModifier::Conditional &&
367+
"Unexpected lastprivate modifier");
368+
TODO(loc, "lastprivate clause with CONDITIONAL modifier");
369+
}
370+
}
371+
359372
} // namespace omp
360373
} // namespace lower
361374
} // namespace Fortran

flang/lib/Lower/OpenMP/Utils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ void genObjectList(const ObjectList &objects,
100100
lower::AbstractConverter &converter,
101101
llvm::SmallVectorImpl<mlir::Value> &operands);
102102

103+
void lastprivateModifierNotSupported(const omp::clause::Lastprivate &lastp,
104+
mlir::Location loc);
105+
103106
} // namespace omp
104107
} // namespace lower
105108
} // namespace Fortran

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,12 @@ TYPE_PARSER(construct<OmpOrderClause>(
232232
TYPE_PARSER(
233233
construct<OmpObject>(designator) || construct<OmpObject>("/" >> name / "/"))
234234

235+
// OMP 5.0 2.19.4.5 LASTPRIVATE ([lastprivate-modifier :] list)
236+
TYPE_PARSER(construct<OmpLastprivateClause>(
237+
maybe("CONDITIONAL" >>
238+
pure(OmpLastprivateClause::LastprivateModifier::Conditional) / ":"),
239+
Parser<OmpObjectList>{}))
240+
235241
TYPE_PARSER(
236242
"ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
237243
"ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
@@ -289,7 +295,7 @@ TYPE_PARSER(
289295
"IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>(
290296
parenthesized(Parser<OmpObjectList>{}))) ||
291297
"LASTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Lastprivate>(
292-
parenthesized(Parser<OmpObjectList>{}))) ||
298+
parenthesized(Parser<OmpLastprivateClause>{}))) ||
293299
"LINEAR" >> construct<OmpClause>(construct<OmpClause::Linear>(
294300
parenthesized(Parser<OmpLinearClause>{}))) ||
295301
"LINK" >> construct<OmpClause>(construct<OmpClause::Link>(

flang/lib/Parser/unparse.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,6 +2067,12 @@ class UnparseVisitor {
20672067
},
20682068
x.u);
20692069
}
2070+
void Unparse(const OmpLastprivateClause &x) {
2071+
Walk(
2072+
std::get<std::optional<OmpLastprivateClause::LastprivateModifier>>(x.t),
2073+
":");
2074+
Walk(std::get<OmpObjectList>(x.t));
2075+
}
20702076
void Unparse(const OmpMapType::Always &) { Word("ALWAYS,"); }
20712077
void Unparse(const OmpMapClause &x) {
20722078
Walk(std::get<std::optional<OmpMapType>>(x.t), ":");
@@ -2764,6 +2770,8 @@ class UnparseVisitor {
27642770
WALK_NESTED_ENUM(OmpDefaultClause, Type) // OMP DEFAULT
27652771
WALK_NESTED_ENUM(OmpDefaultmapClause, ImplicitBehavior) // OMP DEFAULTMAP
27662772
WALK_NESTED_ENUM(OmpDefaultmapClause, VariableCategory) // OMP DEFAULTMAP
2773+
WALK_NESTED_ENUM(
2774+
OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
27672775
WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
27682776
WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier
27692777
WALK_NESTED_ENUM(OmpDependenceType, Type) // OMP dependence-type

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

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3170,11 +3170,13 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
31703170
void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
31713171
CheckAllowedClause(llvm::omp::Clause::OMPC_lastprivate);
31723172

3173-
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "LASTPRIVATE");
3173+
const auto &objectList{std::get<parser::OmpObjectList>(x.v.t)};
3174+
CheckIsVarPartOfAnotherVar(
3175+
GetContext().clauseSource, objectList, "LASTPRIVATE");
31743176

31753177
DirectivesClauseTriple dirClauseTriple;
31763178
SymbolSourceMap currSymbols;
3177-
GetSymbolsInObjectList(x.v, currSymbols);
3179+
GetSymbolsInObjectList(objectList, currSymbols);
31783180
CheckDefinableObjects(currSymbols, GetClauseKindForParserClass(x));
31793181
CheckCopyingPolymorphicAllocatable(
31803182
currSymbols, llvm::omp::Clause::OMPC_lastprivate);
@@ -3189,6 +3191,21 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
31893191

31903192
CheckPrivateSymbolsInOuterCxt(
31913193
currSymbols, dirClauseTriple, GetClauseKindForParserClass(x));
3194+
3195+
using LastprivateModifier = parser::OmpLastprivateClause::LastprivateModifier;
3196+
const auto &maybeMod{std::get<std::optional<LastprivateModifier>>(x.v.t)};
3197+
if (maybeMod) {
3198+
unsigned version{context_.langOptions().OpenMPVersion};
3199+
unsigned allowedInVersion = 50;
3200+
if (version < allowedInVersion) {
3201+
std::string thisVersion{
3202+
std::to_string(version / 10) + "." + std::to_string(version % 10)};
3203+
context_.Say(GetContext().clauseSource,
3204+
"LASTPRIVATE clause with CONDITIONAL modifier is not "
3205+
"allowed in OpenMP v%s, try -fopenmp-version=%d"_err_en_US,
3206+
thisVersion, allowedInVersion);
3207+
}
3208+
}
31923209
}
31933210

31943211
void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) {
@@ -3608,18 +3625,17 @@ const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList(
36083625
const parser::OmpClause &clause) {
36093626

36103627
// Clauses with OmpObjectList as its data member
3611-
using MemberObjectListClauses =
3612-
std::tuple<parser::OmpClause::Copyprivate, parser::OmpClause::Copyin,
3613-
parser::OmpClause::Firstprivate, parser::OmpClause::From,
3614-
parser::OmpClause::Lastprivate, parser::OmpClause::Link,
3615-
parser::OmpClause::Private, parser::OmpClause::Shared,
3616-
parser::OmpClause::To, parser::OmpClause::Enter,
3617-
parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>;
3628+
using MemberObjectListClauses = std::tuple<parser::OmpClause::Copyprivate,
3629+
parser::OmpClause::Copyin, parser::OmpClause::Firstprivate,
3630+
parser::OmpClause::From, parser::OmpClause::Link,
3631+
parser::OmpClause::Private, parser::OmpClause::Shared,
3632+
parser::OmpClause::To, parser::OmpClause::Enter,
3633+
parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>;
36183634

36193635
// Clauses with OmpObjectList in the tuple
3620-
using TupleObjectListClauses =
3621-
std::tuple<parser::OmpClause::Allocate, parser::OmpClause::Map,
3622-
parser::OmpClause::Reduction, parser::OmpClause::Aligned>;
3636+
using TupleObjectListClauses = std::tuple<parser::OmpClause::Allocate,
3637+
parser::OmpClause::Lastprivate, parser::OmpClause::Map,
3638+
parser::OmpClause::Reduction, parser::OmpClause::Aligned>;
36233639

36243640
// TODO:: Generate the tuples using TableGen.
36253641
// Handle other constructs with OmpObjectList such as OpenMPThreadprivate.

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,8 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
455455
return false;
456456
}
457457
bool Pre(const parser::OmpClause::Lastprivate &x) {
458-
ResolveOmpObjectList(x.v, Symbol::Flag::OmpLastPrivate);
458+
const auto &objList{std::get<parser::OmpObjectList>(x.v.t)};
459+
ResolveOmpObjectList(objList, Symbol::Flag::OmpLastPrivate);
459460
return false;
460461
}
461462
bool Pre(const parser::OmpClause::Copyin &x) {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
2+
! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
3+
4+
! CHECK: not yet implemented: lastprivate clause with CONDITIONAL modifier
5+
subroutine foo()
6+
integer :: x, i
7+
x = 1
8+
!$omp parallel do lastprivate(conditional: x)
9+
do i = 1, 100
10+
x = x + 1
11+
enddo
12+
end
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=50 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
2+
! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=50 %s | FileCheck --check-prefix="PARSE-TREE" %s
3+
4+
subroutine foo1()
5+
integer :: x, i
6+
x = 1
7+
!$omp parallel do lastprivate(x)
8+
do i = 1, 100
9+
x = x + 1
10+
enddo
11+
end
12+
13+
!UNPARSE: SUBROUTINE foo1
14+
!UNPARSE: INTEGER x, i
15+
!UNPARSE: x=1_4
16+
!UNPARSE: !$OMP PARALLEL DO LASTPRIVATE(x)
17+
!UNPARSE: DO i=1_4,100_4
18+
!UNPARSE: x=x+1_4
19+
!UNPARSE: END DO
20+
!UNPARSE: END SUBROUTINE
21+
22+
!PARSE-TREE: SubroutineStmt
23+
!PARSE-TREE: Name = 'foo1'
24+
!PARSE-TREE: OmpLoopDirective -> llvm::omp::Directive = parallel do
25+
!PARSE-TREE: OmpClauseList -> OmpClause -> Lastprivate -> OmpLastprivateClause
26+
!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
27+
!PARSE-TREE: EndSubroutineStmt
28+
29+
30+
subroutine foo2()
31+
integer :: x, i
32+
x = 1
33+
!$omp parallel do lastprivate(conditional: x)
34+
do i = 1, 100
35+
x = x + 1
36+
enddo
37+
end
38+
39+
!UNPARSE: SUBROUTINE foo2
40+
!UNPARSE: INTEGER x, i
41+
!UNPARSE: x=1_4
42+
!UNPARSE: !$OMP PARALLEL DO LASTPRIVATE(CONDITIONAL:x)
43+
!UNPARSE: DO i=1_4,100_4
44+
!UNPARSE: x=x+1_4
45+
!UNPARSE: END DO
46+
!UNPARSE: END SUBROUTINE
47+
48+
!PARSE-TREE: SubroutineStmt
49+
!PARSE-TREE: Name = 'foo2'
50+
!PARSE-TREE: OmpLoopDirective -> llvm::omp::Directive = parallel do
51+
!PARSE-TREE: OmpClauseList -> OmpClause -> Lastprivate -> OmpLastprivateClause
52+
!PARSE-TREE: LastprivateModifier = Conditional
53+
!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
54+
!PARSE-TREE: EndSubroutineStmt

llvm/include/llvm/Frontend/OpenMP/OMP.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ def OMPC_IsDevicePtr : Clause<"is_device_ptr"> {
229229
}
230230
def OMPC_LastPrivate : Clause<"lastprivate"> {
231231
let clangClass = "OMPLastprivateClause";
232-
let flangClass = "OmpObjectList";
232+
let flangClass = "OmpLastprivateClause";
233233
}
234234
def OMPC_Linear : Clause<"linear"> {
235235
let clangClass = "OMPLinearClause";

0 commit comments

Comments
 (0)