mirror of
https://github.com/intel/llvm.git
synced 2026-01-19 09:31:59 +08:00
[flang][OpenMP] Parse lastprivate modifier, add TODO to lowering (#110568)
Parse the lastprivate clause with a modifier. Codegen for it is not yet implemented.
This commit is contained in:
committed by
GitHub
parent
36dff0d011
commit
f98244392b
@@ -522,6 +522,8 @@ public:
|
||||
NODE(parser, OmpEndSectionsDirective)
|
||||
NODE(parser, OmpIfClause)
|
||||
NODE_ENUM(OmpIfClause, DirectiveNameModifier)
|
||||
NODE_ENUM(OmpLastprivateClause, LastprivateModifier)
|
||||
NODE(parser, OmpLastprivateClause)
|
||||
NODE(parser, OmpLinearClause)
|
||||
NODE(OmpLinearClause, WithModifier)
|
||||
NODE(OmpLinearClause, WithoutModifier)
|
||||
|
||||
@@ -3648,6 +3648,15 @@ struct OmpAtomicDefaultMemOrderClause {
|
||||
OmpAtomicDefaultMemOrderClause, common::OmpAtomicDefaultMemOrderType);
|
||||
};
|
||||
|
||||
// OMP 5.0 2.19.4.5 lastprivate-clause ->
|
||||
// LASTPRIVATE ([lastprivate-modifier :] list)
|
||||
// lastprivate-modifier -> CONDITIONAL
|
||||
struct OmpLastprivateClause {
|
||||
TUPLE_CLASS_BOILERPLATE(OmpLastprivateClause);
|
||||
ENUM_CLASS(LastprivateModifier, Conditional);
|
||||
std::tuple<std::optional<LastprivateModifier>, OmpObjectList> t;
|
||||
};
|
||||
|
||||
// OpenMP Clauses
|
||||
struct OmpClause {
|
||||
UNION_CLASS_BOILERPLATE(OmpClause);
|
||||
|
||||
@@ -783,9 +783,22 @@ IsDevicePtr make(const parser::OmpClause::IsDevicePtr &inp,
|
||||
|
||||
Lastprivate make(const parser::OmpClause::Lastprivate &inp,
|
||||
semantics::SemanticsContext &semaCtx) {
|
||||
// inp.v -> parser::OmpObjectList
|
||||
return Lastprivate{{/*LastprivateModifier=*/std::nullopt,
|
||||
/*List=*/makeObjects(inp.v, semaCtx)}};
|
||||
// inp.v -> parser::OmpLastprivateClause
|
||||
using wrapped = parser::OmpLastprivateClause;
|
||||
|
||||
CLAUSET_ENUM_CONVERT( //
|
||||
convert, parser::OmpLastprivateClause::LastprivateModifier,
|
||||
Lastprivate::LastprivateModifier,
|
||||
// clang-format off
|
||||
MS(Conditional, Conditional)
|
||||
// clang-format on
|
||||
);
|
||||
|
||||
auto &t0 = std::get<std::optional<wrapped::LastprivateModifier>>(inp.v.t);
|
||||
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
|
||||
|
||||
return Lastprivate{{/*LastprivateModifier=*/maybeApply(convert, t0),
|
||||
/*List=*/makeObjects(t1, semaCtx)}};
|
||||
}
|
||||
|
||||
Linear make(const parser::OmpClause::Linear &inp,
|
||||
|
||||
@@ -151,6 +151,8 @@ void DataSharingProcessor::collectSymbolsForPrivatization() {
|
||||
explicitlyPrivatizedSymbols);
|
||||
} else if (const auto &lastPrivateClause =
|
||||
std::get_if<omp::clause::Lastprivate>(&clause.u)) {
|
||||
lastprivateModifierNotSupported(*lastPrivateClause,
|
||||
converter.getCurrentLocation());
|
||||
const ObjectList &objects = std::get<ObjectList>(lastPrivateClause->t);
|
||||
collectOmpObjectListSymbol(objects, explicitlyPrivatizedSymbols);
|
||||
}
|
||||
|
||||
@@ -1563,7 +1563,9 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
|
||||
|
||||
for (const Clause &clause : item->clauses) {
|
||||
if (clause.id == llvm::omp::Clause::OMPC_lastprivate) {
|
||||
lastprivates.push_back(&std::get<clause::Lastprivate>(clause.u));
|
||||
auto &lastp = std::get<clause::Lastprivate>(clause.u);
|
||||
lastprivateModifierNotSupported(lastp, converter.getCurrentLocation());
|
||||
lastprivates.push_back(&lastp);
|
||||
} else {
|
||||
switch (clause.id) {
|
||||
case llvm::omp::Clause::OMPC_firstprivate:
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <flang/Lower/ConvertType.h>
|
||||
#include <flang/Lower/PFTBuilder.h>
|
||||
#include <flang/Optimizer/Builder/FIRBuilder.h>
|
||||
#include <flang/Optimizer/Builder/Todo.h>
|
||||
#include <flang/Parser/parse-tree.h>
|
||||
#include <flang/Parser/tools.h>
|
||||
#include <flang/Semantics/tools.h>
|
||||
@@ -356,6 +357,18 @@ semantics::Symbol *getOmpObjectSymbol(const parser::OmpObject &ompObject) {
|
||||
return sym;
|
||||
}
|
||||
|
||||
void lastprivateModifierNotSupported(const omp::clause::Lastprivate &lastp,
|
||||
mlir::Location loc) {
|
||||
using Lastprivate = omp::clause::Lastprivate;
|
||||
auto &maybeMod =
|
||||
std::get<std::optional<Lastprivate::LastprivateModifier>>(lastp.t);
|
||||
if (maybeMod) {
|
||||
assert(*maybeMod == Lastprivate::LastprivateModifier::Conditional &&
|
||||
"Unexpected lastprivate modifier");
|
||||
TODO(loc, "lastprivate clause with CONDITIONAL modifier");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace omp
|
||||
} // namespace lower
|
||||
} // namespace Fortran
|
||||
|
||||
@@ -100,6 +100,9 @@ void genObjectList(const ObjectList &objects,
|
||||
lower::AbstractConverter &converter,
|
||||
llvm::SmallVectorImpl<mlir::Value> &operands);
|
||||
|
||||
void lastprivateModifierNotSupported(const omp::clause::Lastprivate &lastp,
|
||||
mlir::Location loc);
|
||||
|
||||
} // namespace omp
|
||||
} // namespace lower
|
||||
} // namespace Fortran
|
||||
|
||||
@@ -232,6 +232,12 @@ TYPE_PARSER(construct<OmpOrderClause>(
|
||||
TYPE_PARSER(
|
||||
construct<OmpObject>(designator) || construct<OmpObject>("/" >> name / "/"))
|
||||
|
||||
// OMP 5.0 2.19.4.5 LASTPRIVATE ([lastprivate-modifier :] list)
|
||||
TYPE_PARSER(construct<OmpLastprivateClause>(
|
||||
maybe("CONDITIONAL" >>
|
||||
pure(OmpLastprivateClause::LastprivateModifier::Conditional) / ":"),
|
||||
Parser<OmpObjectList>{}))
|
||||
|
||||
TYPE_PARSER(
|
||||
"ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
|
||||
"ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
|
||||
@@ -289,7 +295,7 @@ TYPE_PARSER(
|
||||
"IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>(
|
||||
parenthesized(Parser<OmpObjectList>{}))) ||
|
||||
"LASTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Lastprivate>(
|
||||
parenthesized(Parser<OmpObjectList>{}))) ||
|
||||
parenthesized(Parser<OmpLastprivateClause>{}))) ||
|
||||
"LINEAR" >> construct<OmpClause>(construct<OmpClause::Linear>(
|
||||
parenthesized(Parser<OmpLinearClause>{}))) ||
|
||||
"LINK" >> construct<OmpClause>(construct<OmpClause::Link>(
|
||||
|
||||
@@ -2067,6 +2067,12 @@ public:
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const OmpLastprivateClause &x) {
|
||||
Walk(
|
||||
std::get<std::optional<OmpLastprivateClause::LastprivateModifier>>(x.t),
|
||||
":");
|
||||
Walk(std::get<OmpObjectList>(x.t));
|
||||
}
|
||||
void Unparse(const OmpMapType::Always &) { Word("ALWAYS,"); }
|
||||
void Unparse(const OmpMapClause &x) {
|
||||
Walk(std::get<std::optional<OmpMapType>>(x.t), ":");
|
||||
@@ -2764,6 +2770,8 @@ public:
|
||||
WALK_NESTED_ENUM(OmpDefaultClause, Type) // OMP DEFAULT
|
||||
WALK_NESTED_ENUM(OmpDefaultmapClause, ImplicitBehavior) // OMP DEFAULTMAP
|
||||
WALK_NESTED_ENUM(OmpDefaultmapClause, VariableCategory) // OMP DEFAULTMAP
|
||||
WALK_NESTED_ENUM(
|
||||
OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
|
||||
WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
|
||||
WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier
|
||||
WALK_NESTED_ENUM(OmpDependenceType, Type) // OMP dependence-type
|
||||
|
||||
@@ -3170,11 +3170,13 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
|
||||
void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
|
||||
CheckAllowedClause(llvm::omp::Clause::OMPC_lastprivate);
|
||||
|
||||
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "LASTPRIVATE");
|
||||
const auto &objectList{std::get<parser::OmpObjectList>(x.v.t)};
|
||||
CheckIsVarPartOfAnotherVar(
|
||||
GetContext().clauseSource, objectList, "LASTPRIVATE");
|
||||
|
||||
DirectivesClauseTriple dirClauseTriple;
|
||||
SymbolSourceMap currSymbols;
|
||||
GetSymbolsInObjectList(x.v, currSymbols);
|
||||
GetSymbolsInObjectList(objectList, currSymbols);
|
||||
CheckDefinableObjects(currSymbols, GetClauseKindForParserClass(x));
|
||||
CheckCopyingPolymorphicAllocatable(
|
||||
currSymbols, llvm::omp::Clause::OMPC_lastprivate);
|
||||
@@ -3189,6 +3191,21 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
|
||||
|
||||
CheckPrivateSymbolsInOuterCxt(
|
||||
currSymbols, dirClauseTriple, GetClauseKindForParserClass(x));
|
||||
|
||||
using LastprivateModifier = parser::OmpLastprivateClause::LastprivateModifier;
|
||||
const auto &maybeMod{std::get<std::optional<LastprivateModifier>>(x.v.t)};
|
||||
if (maybeMod) {
|
||||
unsigned version{context_.langOptions().OpenMPVersion};
|
||||
unsigned allowedInVersion = 50;
|
||||
if (version < allowedInVersion) {
|
||||
std::string thisVersion{
|
||||
std::to_string(version / 10) + "." + std::to_string(version % 10)};
|
||||
context_.Say(GetContext().clauseSource,
|
||||
"LASTPRIVATE clause with CONDITIONAL modifier is not "
|
||||
"allowed in OpenMP v%s, try -fopenmp-version=%d"_err_en_US,
|
||||
thisVersion, allowedInVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) {
|
||||
@@ -3608,18 +3625,17 @@ const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList(
|
||||
const parser::OmpClause &clause) {
|
||||
|
||||
// Clauses with OmpObjectList as its data member
|
||||
using MemberObjectListClauses =
|
||||
std::tuple<parser::OmpClause::Copyprivate, parser::OmpClause::Copyin,
|
||||
parser::OmpClause::Firstprivate, parser::OmpClause::From,
|
||||
parser::OmpClause::Lastprivate, parser::OmpClause::Link,
|
||||
parser::OmpClause::Private, parser::OmpClause::Shared,
|
||||
parser::OmpClause::To, parser::OmpClause::Enter,
|
||||
parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>;
|
||||
using MemberObjectListClauses = std::tuple<parser::OmpClause::Copyprivate,
|
||||
parser::OmpClause::Copyin, parser::OmpClause::Firstprivate,
|
||||
parser::OmpClause::From, parser::OmpClause::Link,
|
||||
parser::OmpClause::Private, parser::OmpClause::Shared,
|
||||
parser::OmpClause::To, parser::OmpClause::Enter,
|
||||
parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>;
|
||||
|
||||
// Clauses with OmpObjectList in the tuple
|
||||
using TupleObjectListClauses =
|
||||
std::tuple<parser::OmpClause::Allocate, parser::OmpClause::Map,
|
||||
parser::OmpClause::Reduction, parser::OmpClause::Aligned>;
|
||||
using TupleObjectListClauses = std::tuple<parser::OmpClause::Allocate,
|
||||
parser::OmpClause::Lastprivate, parser::OmpClause::Map,
|
||||
parser::OmpClause::Reduction, parser::OmpClause::Aligned>;
|
||||
|
||||
// TODO:: Generate the tuples using TableGen.
|
||||
// Handle other constructs with OmpObjectList such as OpenMPThreadprivate.
|
||||
|
||||
@@ -455,7 +455,8 @@ public:
|
||||
return false;
|
||||
}
|
||||
bool Pre(const parser::OmpClause::Lastprivate &x) {
|
||||
ResolveOmpObjectList(x.v, Symbol::Flag::OmpLastPrivate);
|
||||
const auto &objList{std::get<parser::OmpObjectList>(x.v.t)};
|
||||
ResolveOmpObjectList(objList, Symbol::Flag::OmpLastPrivate);
|
||||
return false;
|
||||
}
|
||||
bool Pre(const parser::OmpClause::Copyin &x) {
|
||||
|
||||
12
flang/test/Lower/OpenMP/Todo/lastprivate-conditional.f90
Normal file
12
flang/test/Lower/OpenMP/Todo/lastprivate-conditional.f90
Normal file
@@ -0,0 +1,12 @@
|
||||
! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
|
||||
! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
|
||||
|
||||
! CHECK: not yet implemented: lastprivate clause with CONDITIONAL modifier
|
||||
subroutine foo()
|
||||
integer :: x, i
|
||||
x = 1
|
||||
!$omp parallel do lastprivate(conditional: x)
|
||||
do i = 1, 100
|
||||
x = x + 1
|
||||
enddo
|
||||
end
|
||||
54
flang/test/Parser/OpenMP/lastprivate-clause.f90
Normal file
54
flang/test/Parser/OpenMP/lastprivate-clause.f90
Normal file
@@ -0,0 +1,54 @@
|
||||
! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=50 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
|
||||
! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=50 %s | FileCheck --check-prefix="PARSE-TREE" %s
|
||||
|
||||
subroutine foo1()
|
||||
integer :: x, i
|
||||
x = 1
|
||||
!$omp parallel do lastprivate(x)
|
||||
do i = 1, 100
|
||||
x = x + 1
|
||||
enddo
|
||||
end
|
||||
|
||||
!UNPARSE: SUBROUTINE foo1
|
||||
!UNPARSE: INTEGER x, i
|
||||
!UNPARSE: x=1_4
|
||||
!UNPARSE: !$OMP PARALLEL DO LASTPRIVATE(x)
|
||||
!UNPARSE: DO i=1_4,100_4
|
||||
!UNPARSE: x=x+1_4
|
||||
!UNPARSE: END DO
|
||||
!UNPARSE: END SUBROUTINE
|
||||
|
||||
!PARSE-TREE: SubroutineStmt
|
||||
!PARSE-TREE: Name = 'foo1'
|
||||
!PARSE-TREE: OmpLoopDirective -> llvm::omp::Directive = parallel do
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Lastprivate -> OmpLastprivateClause
|
||||
!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
|
||||
!PARSE-TREE: EndSubroutineStmt
|
||||
|
||||
|
||||
subroutine foo2()
|
||||
integer :: x, i
|
||||
x = 1
|
||||
!$omp parallel do lastprivate(conditional: x)
|
||||
do i = 1, 100
|
||||
x = x + 1
|
||||
enddo
|
||||
end
|
||||
|
||||
!UNPARSE: SUBROUTINE foo2
|
||||
!UNPARSE: INTEGER x, i
|
||||
!UNPARSE: x=1_4
|
||||
!UNPARSE: !$OMP PARALLEL DO LASTPRIVATE(CONDITIONAL:x)
|
||||
!UNPARSE: DO i=1_4,100_4
|
||||
!UNPARSE: x=x+1_4
|
||||
!UNPARSE: END DO
|
||||
!UNPARSE: END SUBROUTINE
|
||||
|
||||
!PARSE-TREE: SubroutineStmt
|
||||
!PARSE-TREE: Name = 'foo2'
|
||||
!PARSE-TREE: OmpLoopDirective -> llvm::omp::Directive = parallel do
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Lastprivate -> OmpLastprivateClause
|
||||
!PARSE-TREE: LastprivateModifier = Conditional
|
||||
!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
|
||||
!PARSE-TREE: EndSubroutineStmt
|
||||
@@ -229,7 +229,7 @@ def OMPC_IsDevicePtr : Clause<"is_device_ptr"> {
|
||||
}
|
||||
def OMPC_LastPrivate : Clause<"lastprivate"> {
|
||||
let clangClass = "OMPLastprivateClause";
|
||||
let flangClass = "OmpObjectList";
|
||||
let flangClass = "OmpLastprivateClause";
|
||||
}
|
||||
def OMPC_Linear : Clause<"linear"> {
|
||||
let clangClass = "OMPLinearClause";
|
||||
|
||||
Reference in New Issue
Block a user