@@ -980,6 +980,145 @@ static void genLoopVars(
980
980
firOpBuilder.setInsertionPointAfter (storeOp);
981
981
}
982
982
983
+ static clause::Defaultmap::ImplicitBehavior
984
+ getDefaultmapIfPresent (DefaultMapsTy &defaultMaps, mlir::Type varType) {
985
+ using DefMap = clause::Defaultmap;
986
+
987
+ if (defaultMaps.empty ())
988
+ return DefMap::ImplicitBehavior::Default;
989
+
990
+ if (llvm::is_contained (defaultMaps, DefMap::VariableCategory::All))
991
+ return defaultMaps[DefMap::VariableCategory::All];
992
+
993
+ // NOTE: Unsure if complex and/or vector falls into a scalar type
994
+ // or aggregate, but the current default implicit behaviour is to
995
+ // treat them as such (c_ptr has its own behaviour, so perhaps
996
+ // being lumped in as a scalar isn't the right thing).
997
+ if ((fir::isa_trivial (varType) || fir::isa_char (varType) ||
998
+ fir::isa_builtin_cptr_type (varType)) &&
999
+ llvm::is_contained (defaultMaps, DefMap::VariableCategory::Scalar))
1000
+ return defaultMaps[DefMap::VariableCategory::Scalar];
1001
+
1002
+ if (fir::isPointerType (varType) &&
1003
+ llvm::is_contained (defaultMaps, DefMap::VariableCategory::Pointer))
1004
+ return defaultMaps[DefMap::VariableCategory::Pointer];
1005
+
1006
+ if (fir::isAllocatableType (varType) &&
1007
+ llvm::is_contained (defaultMaps, DefMap::VariableCategory::Allocatable))
1008
+ return defaultMaps[DefMap::VariableCategory::Allocatable];
1009
+
1010
+ if (fir::isa_aggregate (varType) &&
1011
+ llvm::is_contained (defaultMaps, DefMap::VariableCategory::Aggregate))
1012
+ return defaultMaps[DefMap::VariableCategory::Aggregate];
1013
+
1014
+ return DefMap::ImplicitBehavior::Default;
1015
+ }
1016
+
1017
+ static std::pair<llvm::omp::OpenMPOffloadMappingFlags,
1018
+ mlir::omp::VariableCaptureKind>
1019
+ getImplicitMapTypeAndKind (fir::FirOpBuilder &firOpBuilder,
1020
+ lower::AbstractConverter &converter,
1021
+ DefaultMapsTy &defaultMaps, mlir::Type varType,
1022
+ mlir::Location loc, const semantics::Symbol &sym) {
1023
+ using DefMap = clause::Defaultmap;
1024
+ // Check if a value of type `type` can be passed to the kernel by value.
1025
+ // All kernel parameters are of pointer type, so if the value can be
1026
+ // represented inside of a pointer, then it can be passed by value.
1027
+ auto isLiteralType = [&](mlir::Type type) {
1028
+ const mlir::DataLayout &dl = firOpBuilder.getDataLayout ();
1029
+ mlir::Type ptrTy =
1030
+ mlir::LLVM::LLVMPointerType::get (&converter.getMLIRContext ());
1031
+ uint64_t ptrSize = dl.getTypeSize (ptrTy);
1032
+ uint64_t ptrAlign = dl.getTypePreferredAlignment (ptrTy);
1033
+
1034
+ auto [size, align] = fir::getTypeSizeAndAlignmentOrCrash (
1035
+ loc, type, dl, converter.getKindMap ());
1036
+ return size <= ptrSize && align <= ptrAlign;
1037
+ };
1038
+
1039
+ llvm::omp::OpenMPOffloadMappingFlags mapFlag =
1040
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
1041
+
1042
+ auto implicitBehaviour = getDefaultmapIfPresent (defaultMaps, varType);
1043
+ if (implicitBehaviour == DefMap::ImplicitBehavior::Default) {
1044
+ mlir::omp::VariableCaptureKind captureKind =
1045
+ mlir::omp::VariableCaptureKind::ByRef;
1046
+
1047
+ // If a variable is specified in declare target link and if device
1048
+ // type is not specified as `nohost`, it needs to be mapped tofrom
1049
+ mlir::ModuleOp mod = firOpBuilder.getModule ();
1050
+ mlir::Operation *op = mod.lookupSymbol (converter.mangleName (sym));
1051
+ auto declareTargetOp =
1052
+ llvm::dyn_cast_if_present<mlir::omp::DeclareTargetInterface>(op);
1053
+ if (declareTargetOp && declareTargetOp.isDeclareTarget ()) {
1054
+ if (declareTargetOp.getDeclareTargetCaptureClause () ==
1055
+ mlir::omp::DeclareTargetCaptureClause::link &&
1056
+ declareTargetOp.getDeclareTargetDeviceType () !=
1057
+ mlir::omp::DeclareTargetDeviceType::nohost) {
1058
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
1059
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
1060
+ }
1061
+ } else if (fir::isa_trivial (varType) || fir::isa_char (varType)) {
1062
+ // Scalars behave as if they were "firstprivate".
1063
+ // TODO: Handle objects that are shared/lastprivate or were listed
1064
+ // in an in_reduction clause.
1065
+ if (isLiteralType (varType)) {
1066
+ captureKind = mlir::omp::VariableCaptureKind::ByCopy;
1067
+ } else {
1068
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
1069
+ }
1070
+ } else if (!fir::isa_builtin_cptr_type (varType)) {
1071
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
1072
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
1073
+ }
1074
+ return std::make_pair (mapFlag, captureKind);
1075
+ }
1076
+
1077
+ switch (implicitBehaviour) {
1078
+ case DefMap::ImplicitBehavior::Alloc:
1079
+ return std::make_pair (llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
1080
+ mlir::omp::VariableCaptureKind::ByRef);
1081
+ break ;
1082
+ case DefMap::ImplicitBehavior::Firstprivate:
1083
+ case DefMap::ImplicitBehavior::None:
1084
+ TODO (loc, " Firstprivate and None are currently unsupported defaultmap "
1085
+ " behaviour" );
1086
+ break ;
1087
+ case DefMap::ImplicitBehavior::From:
1088
+ return std::make_pair (mapFlag |=
1089
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM,
1090
+ mlir::omp::VariableCaptureKind::ByRef);
1091
+ break ;
1092
+ case DefMap::ImplicitBehavior::Present:
1093
+ return std::make_pair (mapFlag |=
1094
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT,
1095
+ mlir::omp::VariableCaptureKind::ByRef);
1096
+ break ;
1097
+ case DefMap::ImplicitBehavior::To:
1098
+ return std::make_pair (mapFlag |=
1099
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
1100
+ (fir::isa_trivial (varType) || fir::isa_char (varType))
1101
+ ? mlir::omp::VariableCaptureKind::ByCopy
1102
+ : mlir::omp::VariableCaptureKind::ByRef);
1103
+ break ;
1104
+ case DefMap::ImplicitBehavior::Tofrom:
1105
+ return std::make_pair (mapFlag |=
1106
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM |
1107
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
1108
+ mlir::omp::VariableCaptureKind::ByRef);
1109
+ break ;
1110
+ case DefMap::ImplicitBehavior::Default:
1111
+ llvm_unreachable (
1112
+ " Implicit None Behaviour Should Have Been Handled Earlier" );
1113
+ break ;
1114
+ }
1115
+
1116
+ return std::make_pair (mapFlag |=
1117
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM |
1118
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
1119
+ mlir::omp::VariableCaptureKind::ByRef);
1120
+ }
1121
+
983
1122
static void
984
1123
markDeclareTarget (mlir::Operation *op, lower::AbstractConverter &converter,
985
1124
mlir::omp::DeclareTargetCaptureClause captureClause,
@@ -1677,11 +1816,13 @@ static void genTargetClauses(
1677
1816
lower::SymMap &symTable, lower::StatementContext &stmtCtx,
1678
1817
lower::pft::Evaluation &eval, const List<Clause> &clauses,
1679
1818
mlir::Location loc, mlir::omp::TargetOperands &clauseOps,
1819
+ DefaultMapsTy &defaultMaps,
1680
1820
llvm::SmallVectorImpl<const semantics::Symbol *> &hasDeviceAddrSyms,
1681
1821
llvm::SmallVectorImpl<const semantics::Symbol *> &isDevicePtrSyms,
1682
1822
llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms) {
1683
1823
ClauseProcessor cp (converter, semaCtx, clauses);
1684
1824
cp.processBare (clauseOps);
1825
+ cp.processDefaultMap (stmtCtx, defaultMaps);
1685
1826
cp.processDepend (symTable, stmtCtx, clauseOps);
1686
1827
cp.processDevice (stmtCtx, clauseOps);
1687
1828
cp.processHasDeviceAddr (stmtCtx, clauseOps, hasDeviceAddrSyms);
@@ -1696,9 +1837,8 @@ static void genTargetClauses(
1696
1837
cp.processNowait (clauseOps);
1697
1838
cp.processThreadLimit (stmtCtx, clauseOps);
1698
1839
1699
- cp.processTODO <clause::Allocate, clause::Defaultmap, clause::InReduction,
1700
- clause::UsesAllocators>(loc,
1701
- llvm::omp::Directive::OMPD_target);
1840
+ cp.processTODO <clause::Allocate, clause::InReduction, clause::UsesAllocators>(
1841
+ loc, llvm::omp::Directive::OMPD_target);
1702
1842
1703
1843
// `target private(..)` is only supported in delayed privatization mode.
1704
1844
if (!enableDelayedPrivatizationStaging)
@@ -2242,32 +2382,19 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
2242
2382
hostEvalInfo.emplace_back ();
2243
2383
2244
2384
mlir::omp::TargetOperands clauseOps;
2385
+ DefaultMapsTy defaultMaps;
2245
2386
llvm::SmallVector<const semantics::Symbol *> mapSyms, isDevicePtrSyms,
2246
2387
hasDeviceAddrSyms;
2247
2388
genTargetClauses (converter, semaCtx, symTable, stmtCtx, eval, item->clauses ,
2248
- loc, clauseOps, hasDeviceAddrSyms, isDevicePtrSyms, mapSyms);
2389
+ loc, clauseOps, defaultMaps, hasDeviceAddrSyms,
2390
+ isDevicePtrSyms, mapSyms);
2249
2391
2250
2392
DataSharingProcessor dsp (converter, semaCtx, item->clauses , eval,
2251
2393
/* shouldCollectPreDeterminedSymbols=*/
2252
2394
lower::omp::isLastItemInQueue (item, queue),
2253
2395
/* useDelayedPrivatization=*/ true , symTable);
2254
2396
dsp.processStep1 (&clauseOps);
2255
2397
2256
- // Check if a value of type `type` can be passed to the kernel by value.
2257
- // All kernel parameters are of pointer type, so if the value can be
2258
- // represented inside of a pointer, then it can be passed by value.
2259
- auto isLiteralType = [&](mlir::Type type) {
2260
- const mlir::DataLayout &dl = firOpBuilder.getDataLayout ();
2261
- mlir::Type ptrTy =
2262
- mlir::LLVM::LLVMPointerType::get (&converter.getMLIRContext ());
2263
- uint64_t ptrSize = dl.getTypeSize (ptrTy);
2264
- uint64_t ptrAlign = dl.getTypePreferredAlignment (ptrTy);
2265
-
2266
- auto [size, align] = fir::getTypeSizeAndAlignmentOrCrash (
2267
- loc, type, dl, converter.getKindMap ());
2268
- return size <= ptrSize && align <= ptrAlign;
2269
- };
2270
-
2271
2398
// 5.8.1 Implicit Data-Mapping Attribute Rules
2272
2399
// The following code follows the implicit data-mapping rules to map all the
2273
2400
// symbols used inside the region that do not have explicit data-environment
@@ -2330,56 +2457,25 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
2330
2457
firOpBuilder, info, dataExv,
2331
2458
semantics::IsAssumedSizeArray (sym.GetUltimate ()),
2332
2459
converter.getCurrentLocation ());
2333
-
2334
- llvm::omp::OpenMPOffloadMappingFlags mapFlag =
2335
- llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
2336
- mlir::omp::VariableCaptureKind captureKind =
2337
- mlir::omp::VariableCaptureKind::ByRef;
2338
-
2339
2460
mlir::Value baseOp = info.rawInput ;
2340
2461
mlir::Type eleType = baseOp.getType ();
2341
2462
if (auto refType = mlir::dyn_cast<fir::ReferenceType>(baseOp.getType ()))
2342
2463
eleType = refType.getElementType ();
2343
2464
2344
- // If a variable is specified in declare target link and if device
2345
- // type is not specified as `nohost`, it needs to be mapped tofrom
2346
- mlir::ModuleOp mod = firOpBuilder.getModule ();
2347
- mlir::Operation *op = mod.lookupSymbol (converter.mangleName (sym));
2348
- auto declareTargetOp =
2349
- llvm::dyn_cast_if_present<mlir::omp::DeclareTargetInterface>(op);
2350
- if (declareTargetOp && declareTargetOp.isDeclareTarget ()) {
2351
- if (declareTargetOp.getDeclareTargetCaptureClause () ==
2352
- mlir::omp::DeclareTargetCaptureClause::link &&
2353
- declareTargetOp.getDeclareTargetDeviceType () !=
2354
- mlir::omp::DeclareTargetDeviceType::nohost) {
2355
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2356
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2357
- }
2358
- } else if (fir::isa_trivial (eleType) || fir::isa_char (eleType)) {
2359
- // Scalars behave as if they were "firstprivate".
2360
- // TODO: Handle objects that are shared/lastprivate or were listed
2361
- // in an in_reduction clause.
2362
- if (isLiteralType (eleType)) {
2363
- captureKind = mlir::omp::VariableCaptureKind::ByCopy;
2364
- } else {
2365
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2366
- }
2367
- } else if (!fir::isa_builtin_cptr_type (eleType)) {
2368
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2369
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2370
- }
2371
- auto location =
2372
- mlir::NameLoc::get (mlir::StringAttr::get (firOpBuilder.getContext (),
2373
- sym.name ().ToString ()),
2374
- baseOp.getLoc ());
2465
+ std::pair<llvm::omp::OpenMPOffloadMappingFlags,
2466
+ mlir::omp::VariableCaptureKind>
2467
+ mapFlagAndKind = getImplicitMapTypeAndKind (
2468
+ firOpBuilder, converter, defaultMaps, eleType, loc, sym);
2469
+
2375
2470
mlir::Value mapOp = createMapInfoOp (
2376
- firOpBuilder, location , baseOp, /* varPtrPtr= */ mlir::Value{} ,
2377
- name.str (), bounds, /* members=*/ {},
2471
+ firOpBuilder, converter. getCurrentLocation () , baseOp,
2472
+ /* varPtrPtr= */ mlir::Value{}, name.str (), bounds, /* members=*/ {},
2378
2473
/* membersIndex=*/ mlir::ArrayAttr{},
2379
2474
static_cast <
2380
2475
std::underlying_type_t <llvm::omp::OpenMPOffloadMappingFlags>>(
2381
- mapFlag),
2382
- captureKind, baseOp.getType (), /* partialMap=*/ false , mapperId);
2476
+ std::get<0 >(mapFlagAndKind)),
2477
+ std::get<1 >(mapFlagAndKind), baseOp.getType (),
2478
+ /* partialMap=*/ false , mapperId);
2383
2479
2384
2480
clauseOps.mapVars .push_back (mapOp);
2385
2481
mapSyms.push_back (&sym);
@@ -4199,6 +4295,7 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
4199
4295
!std::holds_alternative<clause::Copyin>(clause.u ) &&
4200
4296
!std::holds_alternative<clause::Copyprivate>(clause.u ) &&
4201
4297
!std::holds_alternative<clause::Default>(clause.u ) &&
4298
+ !std::holds_alternative<clause::Defaultmap>(clause.u ) &&
4202
4299
!std::holds_alternative<clause::Depend>(clause.u ) &&
4203
4300
!std::holds_alternative<clause::Filter>(clause.u ) &&
4204
4301
!std::holds_alternative<clause::Final>(clause.u ) &&
0 commit comments