Skip to content

Commit 8f339cd

Browse files
committed
[Flang][OpenMP] Initial defaultmap implementation
This aims to implement most of the initial arguments for defaultmap aside from firstprivate and none, and some of the more recent OpenMP 6 additions which will come in subsequent updates.
1 parent 50428fb commit 8f339cd

File tree

13 files changed

+523
-63
lines changed

13 files changed

+523
-63
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4133,8 +4133,8 @@ struct OmpDefaultClause {
41334133
// PRESENT // since 5.1
41344134
struct OmpDefaultmapClause {
41354135
TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause);
4136-
ENUM_CLASS(
4137-
ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default)
4136+
ENUM_CLASS(ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None,
4137+
Default, Present)
41384138
MODIFIER_BOILERPLATE(OmpVariableCategory);
41394139
std::tuple<ImplicitBehavior, MODIFIERS()> t;
41404140
};

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,26 @@ static bool isVectorSubscript(const evaluate::Expr<T> &expr) {
856856
return false;
857857
}
858858

859+
bool ClauseProcessor::processDefaultMap(
860+
DefaultMapsTy &result, lower::StatementContext &stmtCtx) const {
861+
auto process = [&](const omp::clause::Defaultmap &clause,
862+
const parser::CharBlock &) {
863+
using Defmap = omp::clause::Defaultmap;
864+
clause::Defaultmap::VariableCategory variableCategory =
865+
Defmap::VariableCategory::All;
866+
// Variable Category is optional, if not specified defaults to all.
867+
// Multiples of the same category are illegal as are any other
868+
// defaultmaps being specified when a user specified all is in place,
869+
// however, this should be handled earlier during semantics.
870+
if (auto varCat =
871+
std::get<std::optional<Defmap::VariableCategory>>(clause.t))
872+
variableCategory = varCat.value_or(Defmap::VariableCategory::All);
873+
auto behaviour = std::get<Defmap::ImplicitBehavior>(clause.t);
874+
result.insert({variableCategory, behaviour});
875+
};
876+
return findRepeatableClause<omp::clause::Defaultmap>(process);
877+
}
878+
859879
bool ClauseProcessor::processDepend(lower::SymMap &symMap,
860880
lower::StatementContext &stmtCtx,
861881
mlir::omp::DependClauseOps &result) const {

flang/lib/Lower/OpenMP/ClauseProcessor.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ namespace Fortran {
3232
namespace lower {
3333
namespace omp {
3434

35+
// Container type for tracking user specified Defaultmaps for a target region
36+
using DefaultMapsTy = std::map<clause::Defaultmap::VariableCategory,
37+
clause::Defaultmap::ImplicitBehavior>;
38+
3539
/// Class that handles the processing of OpenMP clauses.
3640
///
3741
/// Its `process<ClauseName>()` methods perform MLIR code generation for their
@@ -106,6 +110,8 @@ class ClauseProcessor {
106110
bool processCopyin() const;
107111
bool processCopyprivate(mlir::Location currentLocation,
108112
mlir::omp::CopyprivateClauseOps &result) const;
113+
bool processDefaultMap(DefaultMapsTy &result,
114+
lower::StatementContext &stmtCtx) const;
109115
bool processDepend(lower::SymMap &symMap, lower::StatementContext &stmtCtx,
110116
mlir::omp::DependClauseOps &result) const;
111117
bool

flang/lib/Lower/OpenMP/Clauses.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ Defaultmap make(const parser::OmpClause::Defaultmap &inp,
611611
MS(Firstprivate, Firstprivate)
612612
MS(None, None)
613613
MS(Default, Default)
614-
// MS(, Present) missing-in-parser
614+
MS(Present, Present)
615615
// clang-format on
616616
);
617617

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 148 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,6 +1700,7 @@ static void genTargetClauses(
17001700
lower::SymMap &symTable, lower::StatementContext &stmtCtx,
17011701
lower::pft::Evaluation &eval, const List<Clause> &clauses,
17021702
mlir::Location loc, mlir::omp::TargetOperands &clauseOps,
1703+
DefaultMapsTy &defaultMaps,
17031704
llvm::SmallVectorImpl<const semantics::Symbol *> &hasDeviceAddrSyms,
17041705
llvm::SmallVectorImpl<const semantics::Symbol *> &isDevicePtrSyms,
17051706
llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms) {
@@ -1718,10 +1719,11 @@ static void genTargetClauses(
17181719
cp.processMap(loc, stmtCtx, clauseOps, &mapSyms);
17191720
cp.processNowait(clauseOps);
17201721
cp.processThreadLimit(stmtCtx, clauseOps);
1722+
cp.processDefaultMap(defaultMaps, stmtCtx);
17211723

1722-
cp.processTODO<clause::Allocate, clause::Defaultmap, clause::Firstprivate,
1723-
clause::InReduction, clause::UsesAllocators>(
1724-
loc, llvm::omp::Directive::OMPD_target);
1724+
cp.processTODO<clause::Allocate, clause::Firstprivate, clause::InReduction,
1725+
clause::UsesAllocators>(loc,
1726+
llvm::omp::Directive::OMPD_target);
17251727

17261728
// `target private(..)` is only supported in delayed privatization mode.
17271729
if (!enableDelayedPrivatizationStaging)
@@ -2246,10 +2248,12 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
22462248
hostEvalInfo.emplace_back();
22472249

22482250
mlir::omp::TargetOperands clauseOps;
2251+
DefaultMapsTy defaultMaps;
22492252
llvm::SmallVector<const semantics::Symbol *> mapSyms, isDevicePtrSyms,
22502253
hasDeviceAddrSyms;
22512254
genTargetClauses(converter, semaCtx, symTable, stmtCtx, eval, item->clauses,
2252-
loc, clauseOps, hasDeviceAddrSyms, isDevicePtrSyms, mapSyms);
2255+
loc, clauseOps, defaultMaps, hasDeviceAddrSyms,
2256+
isDevicePtrSyms, mapSyms);
22532257

22542258
DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
22552259
/*shouldCollectPreDeterminedSymbols=*/
@@ -2272,6 +2276,129 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
22722276
return size <= ptrSize && align <= ptrAlign;
22732277
};
22742278

2279+
auto getDefaultmapIfPresent = [&](mlir::Type varType) {
2280+
using defMap = clause::Defaultmap;
2281+
auto exists = [&](defMap::VariableCategory varCat) {
2282+
return defaultMaps.find(varCat) != defaultMaps.end();
2283+
};
2284+
2285+
if (defaultMaps.empty())
2286+
return defMap::ImplicitBehavior::Default;
2287+
2288+
if (exists(defMap::VariableCategory::All))
2289+
return defaultMaps[defMap::VariableCategory::All];
2290+
2291+
// NOTE: Unsure if complex and/or vector falls into a scalar type
2292+
// or aggregate, but the current default implicit behaviour is to
2293+
// treat them as such (c_ptr has its own behaviour, so perhaps
2294+
// being lumped in as a scalar isn't the right thing).
2295+
if ((fir::isa_trivial(varType) || fir::isa_char(varType) ||
2296+
fir::isa_builtin_cptr_type(varType)) &&
2297+
exists(defMap::VariableCategory::Scalar))
2298+
return defaultMaps[defMap::VariableCategory::Scalar];
2299+
2300+
if (fir::isPointerType(varType) &&
2301+
exists(defMap::VariableCategory::Pointer))
2302+
return defaultMaps[defMap::VariableCategory::Pointer];
2303+
2304+
if (fir::isAllocatableType(varType) &&
2305+
exists(defMap::VariableCategory::Allocatable))
2306+
return defaultMaps[defMap::VariableCategory::Allocatable];
2307+
2308+
if (fir::isa_aggregate(varType) &&
2309+
exists(defMap::VariableCategory::Aggregate)) {
2310+
return defaultMaps[defMap::VariableCategory::Aggregate];
2311+
}
2312+
2313+
return defMap::ImplicitBehavior::Default;
2314+
};
2315+
2316+
auto getImplicitMapTypeAndKind = [&](mlir::Type varType,
2317+
const semantics::Symbol &sym) {
2318+
using defMap = clause::Defaultmap;
2319+
llvm::omp::OpenMPOffloadMappingFlags mapFlag =
2320+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
2321+
2322+
auto implicitBehaviour = getDefaultmapIfPresent(varType);
2323+
if (implicitBehaviour == defMap::ImplicitBehavior::Default) {
2324+
mlir::omp::VariableCaptureKind captureKind =
2325+
mlir::omp::VariableCaptureKind::ByRef;
2326+
2327+
// If a variable is specified in declare target link and if device
2328+
// type is not specified as `nohost`, it needs to be mapped tofrom
2329+
mlir::ModuleOp mod = firOpBuilder.getModule();
2330+
mlir::Operation *op = mod.lookupSymbol(converter.mangleName(sym));
2331+
auto declareTargetOp =
2332+
llvm::dyn_cast_if_present<mlir::omp::DeclareTargetInterface>(op);
2333+
if (declareTargetOp && declareTargetOp.isDeclareTarget()) {
2334+
if (declareTargetOp.getDeclareTargetCaptureClause() ==
2335+
mlir::omp::DeclareTargetCaptureClause::link &&
2336+
declareTargetOp.getDeclareTargetDeviceType() !=
2337+
mlir::omp::DeclareTargetDeviceType::nohost) {
2338+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2339+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2340+
}
2341+
} else if (fir::isa_trivial(varType) || fir::isa_char(varType)) {
2342+
// Scalars behave as if they were "firstprivate".
2343+
// TODO: Handle objects that are shared/lastprivate or were listed
2344+
// in an in_reduction clause.
2345+
if (isLiteralType(varType)) {
2346+
captureKind = mlir::omp::VariableCaptureKind::ByCopy;
2347+
} else {
2348+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2349+
}
2350+
} else if (!fir::isa_builtin_cptr_type(varType)) {
2351+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2352+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2353+
}
2354+
return std::make_pair(mapFlag, captureKind);
2355+
}
2356+
2357+
switch (implicitBehaviour) {
2358+
case defMap::ImplicitBehavior::Alloc:
2359+
return std::make_pair(llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
2360+
mlir::omp::VariableCaptureKind::ByRef);
2361+
break;
2362+
case defMap::ImplicitBehavior::Firstprivate:
2363+
case defMap::ImplicitBehavior::None:
2364+
TODO(loc, "Firstprivate and None are currently unsupported defaultmap "
2365+
"behaviour");
2366+
break;
2367+
case defMap::ImplicitBehavior::From:
2368+
return std::make_pair(mapFlag |=
2369+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM,
2370+
mlir::omp::VariableCaptureKind::ByRef);
2371+
break;
2372+
case defMap::ImplicitBehavior::Present:
2373+
return std::make_pair(
2374+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT,
2375+
mlir::omp::VariableCaptureKind::ByRef);
2376+
break;
2377+
case defMap::ImplicitBehavior::To:
2378+
return std::make_pair(
2379+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
2380+
(fir::isa_trivial(varType) || fir::isa_char(varType))
2381+
? mlir::omp::VariableCaptureKind::ByCopy
2382+
: mlir::omp::VariableCaptureKind::ByRef);
2383+
break;
2384+
case defMap::ImplicitBehavior::Tofrom:
2385+
return std::make_pair(mapFlag |=
2386+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM |
2387+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
2388+
mlir::omp::VariableCaptureKind::ByRef);
2389+
break;
2390+
case defMap::ImplicitBehavior::Default:
2391+
llvm_unreachable(
2392+
"Implicit None Behaviour Should Have Been Handled Earlier");
2393+
break;
2394+
}
2395+
2396+
return std::make_pair(mapFlag |=
2397+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM |
2398+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
2399+
mlir::omp::VariableCaptureKind::ByRef);
2400+
};
2401+
22752402
// 5.8.1 Implicit Data-Mapping Attribute Rules
22762403
// The following code follows the implicit data-mapping rules to map all the
22772404
// symbols used inside the region that do not have explicit data-environment
@@ -2327,62 +2454,32 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
23272454
fir::factory::AddrAndBoundsInfo info =
23282455
Fortran::lower::getDataOperandBaseAddr(
23292456
converter, firOpBuilder, sym, converter.getCurrentLocation());
2330-
llvm::SmallVector<mlir::Value> bounds =
2331-
fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
2332-
mlir::omp::MapBoundsType>(
2333-
firOpBuilder, info, dataExv,
2334-
semantics::IsAssumedSizeArray(sym.GetUltimate()),
2335-
converter.getCurrentLocation());
2336-
2337-
llvm::omp::OpenMPOffloadMappingFlags mapFlag =
2338-
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
2339-
mlir::omp::VariableCaptureKind captureKind =
2340-
mlir::omp::VariableCaptureKind::ByRef;
23412457

23422458
mlir::Value baseOp = info.rawInput;
23432459
mlir::Type eleType = baseOp.getType();
23442460
if (auto refType = mlir::dyn_cast<fir::ReferenceType>(baseOp.getType()))
23452461
eleType = refType.getElementType();
23462462

2347-
// If a variable is specified in declare target link and if device
2348-
// type is not specified as `nohost`, it needs to be mapped tofrom
2349-
mlir::ModuleOp mod = firOpBuilder.getModule();
2350-
mlir::Operation *op = mod.lookupSymbol(converter.mangleName(sym));
2351-
auto declareTargetOp =
2352-
llvm::dyn_cast_if_present<mlir::omp::DeclareTargetInterface>(op);
2353-
if (declareTargetOp && declareTargetOp.isDeclareTarget()) {
2354-
if (declareTargetOp.getDeclareTargetCaptureClause() ==
2355-
mlir::omp::DeclareTargetCaptureClause::link &&
2356-
declareTargetOp.getDeclareTargetDeviceType() !=
2357-
mlir::omp::DeclareTargetDeviceType::nohost) {
2358-
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2359-
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2360-
}
2361-
} else if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) {
2362-
// Scalars behave as if they were "firstprivate".
2363-
// TODO: Handle objects that are shared/lastprivate or were listed
2364-
// in an in_reduction clause.
2365-
if (isLiteralType(eleType)) {
2366-
captureKind = mlir::omp::VariableCaptureKind::ByCopy;
2367-
} else {
2368-
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2369-
}
2370-
} else if (!fir::isa_builtin_cptr_type(eleType)) {
2371-
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2372-
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2373-
}
2374-
auto location =
2375-
mlir::NameLoc::get(mlir::StringAttr::get(firOpBuilder.getContext(),
2376-
sym.name().ToString()),
2377-
baseOp.getLoc());
2463+
auto mapFlagAndKind = getImplicitMapTypeAndKind(eleType, sym);
2464+
2465+
llvm::SmallVector<mlir::Value> bounds =
2466+
fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
2467+
mlir::omp::MapBoundsType>(
2468+
firOpBuilder, info, dataExv,
2469+
semantics::IsAssumedSizeArray(sym.GetUltimate()),
2470+
converter.getCurrentLocation());
2471+
mlir::NameLoc::get(mlir::StringAttr::get(firOpBuilder.getContext(),
2472+
sym.name().ToString()),
2473+
baseOp.getLoc());
23782474
mlir::Value mapOp = createMapInfoOp(
2379-
firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{},
2380-
name.str(), bounds, /*members=*/{},
2475+
firOpBuilder, converter.getCurrentLocation(), baseOp,
2476+
/*varPtrPtr=*/mlir::Value{}, name.str(), bounds, /*members=*/{},
23812477
/*membersIndex=*/mlir::ArrayAttr{},
23822478
static_cast<
23832479
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
2384-
mapFlag),
2385-
captureKind, baseOp.getType(), /*partialMap=*/false, mapperId);
2480+
std::get<0>(mapFlagAndKind)),
2481+
std::get<1>(mapFlagAndKind), baseOp.getType(),
2482+
/*partialMap=*/false, mapperId);
23862483

23872484
clauseOps.mapVars.push_back(mapOp);
23882485
mapSyms.push_back(&sym);
@@ -3539,6 +3636,7 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
35393636
!std::holds_alternative<clause::Copyin>(clause.u) &&
35403637
!std::holds_alternative<clause::Copyprivate>(clause.u) &&
35413638
!std::holds_alternative<clause::Default>(clause.u) &&
3639+
!std::holds_alternative<clause::Defaultmap>(clause.u) &&
35423640
!std::holds_alternative<clause::Depend>(clause.u) &&
35433641
!std::holds_alternative<clause::Filter>(clause.u) &&
35443642
!std::holds_alternative<clause::Final>(clause.u) &&

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ TYPE_PARSER(construct<OmpMapClause>(
668668
// [OpenMP 5.0]
669669
// 2.19.7.2 defaultmap(implicit-behavior[:variable-category])
670670
// implicit-behavior -> ALLOC | TO | FROM | TOFROM | FIRSRTPRIVATE | NONE |
671-
// DEFAULT
671+
// DEFAULT | PRESENT
672672
// variable-category -> ALL | SCALAR | AGGREGATE | ALLOCATABLE | POINTER
673673
TYPE_PARSER(construct<OmpDefaultmapClause>(
674674
construct<OmpDefaultmapClause::ImplicitBehavior>(
@@ -679,7 +679,8 @@ TYPE_PARSER(construct<OmpDefaultmapClause>(
679679
"FIRSTPRIVATE" >>
680680
pure(OmpDefaultmapClause::ImplicitBehavior::Firstprivate) ||
681681
"NONE" >> pure(OmpDefaultmapClause::ImplicitBehavior::None) ||
682-
"DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)),
682+
"DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default) ||
683+
"PRESENT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Present)),
683684
maybe(":" >> nonemptyList(Parser<OmpDefaultmapClause::Modifier>{}))))
684685

685686
TYPE_PARSER(construct<OmpScheduleClause::Kind>(
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
2+
!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
3+
4+
subroutine f00
5+
implicit none
6+
integer :: i
7+
!CHECK: not yet implemented: Firstprivate and None are currently unsupported defaultmap behaviour
8+
!$omp target defaultmap(firstprivate)
9+
i = 10
10+
!$omp end target
11+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
2+
!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
3+
4+
subroutine f00
5+
implicit none
6+
integer :: i
7+
!CHECK: not yet implemented: Firstprivate and None are currently unsupported defaultmap behaviour
8+
!$omp target defaultmap(none)
9+
i = 10
10+
!$omp end target
11+
end

flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)