@@ -1700,11 +1700,13 @@ static void genTargetClauses(
1700
1700
lower::SymMap &symTable, lower::StatementContext &stmtCtx,
1701
1701
lower::pft::Evaluation &eval, const List<Clause> &clauses,
1702
1702
mlir::Location loc, mlir::omp::TargetOperands &clauseOps,
1703
+ DefaultMapsTy &defaultMaps,
1703
1704
llvm::SmallVectorImpl<const semantics::Symbol *> &hasDeviceAddrSyms,
1704
1705
llvm::SmallVectorImpl<const semantics::Symbol *> &isDevicePtrSyms,
1705
1706
llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms) {
1706
1707
ClauseProcessor cp (converter, semaCtx, clauses);
1707
1708
cp.processBare (clauseOps);
1709
+ cp.processDefaultMap (stmtCtx, defaultMaps);
1708
1710
cp.processDepend (symTable, stmtCtx, clauseOps);
1709
1711
cp.processDevice (stmtCtx, clauseOps);
1710
1712
cp.processHasDeviceAddr (stmtCtx, clauseOps, hasDeviceAddrSyms);
@@ -1719,9 +1721,8 @@ static void genTargetClauses(
1719
1721
cp.processNowait (clauseOps);
1720
1722
cp.processThreadLimit (stmtCtx, clauseOps);
1721
1723
1722
- cp.processTODO <clause::Allocate, clause::Defaultmap, clause::InReduction,
1723
- clause::UsesAllocators>(loc,
1724
- llvm::omp::Directive::OMPD_target);
1724
+ cp.processTODO <clause::Allocate, clause::InReduction, clause::UsesAllocators>(
1725
+ loc, llvm::omp::Directive::OMPD_target);
1725
1726
1726
1727
// `target private(..)` is only supported in delayed privatization mode.
1727
1728
if (!enableDelayedPrivatizationStaging)
@@ -2231,6 +2232,146 @@ genSingleOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
2231
2232
queue, item, clauseOps);
2232
2233
}
2233
2234
2235
+ static clause::Defaultmap::ImplicitBehavior
2236
+ getDefaultmapIfPresent (DefaultMapsTy &defaultMaps, mlir::Type varType) {
2237
+ using DefMap = clause::Defaultmap;
2238
+
2239
+ if (defaultMaps.empty ())
2240
+ return DefMap::ImplicitBehavior::Default;
2241
+
2242
+ if (llvm::is_contained (defaultMaps, DefMap::VariableCategory::All))
2243
+ return defaultMaps[DefMap::VariableCategory::All];
2244
+
2245
+ // NOTE: Unsure if complex and/or vector falls into a scalar type
2246
+ // or aggregate, but the current default implicit behaviour is to
2247
+ // treat them as such (c_ptr has its own behaviour, so perhaps
2248
+ // being lumped in as a scalar isn't the right thing).
2249
+ if ((fir::isa_trivial (varType) || fir::isa_char (varType) ||
2250
+ fir::isa_builtin_cptr_type (varType)) &&
2251
+ llvm::is_contained (defaultMaps, DefMap::VariableCategory::Scalar))
2252
+ return defaultMaps[DefMap::VariableCategory::Scalar];
2253
+
2254
+ if (fir::isPointerType (varType) &&
2255
+ llvm::is_contained (defaultMaps, DefMap::VariableCategory::Pointer))
2256
+ return defaultMaps[DefMap::VariableCategory::Pointer];
2257
+
2258
+ if (fir::isAllocatableType (varType) &&
2259
+ llvm::is_contained (defaultMaps, DefMap::VariableCategory::Allocatable))
2260
+ return defaultMaps[DefMap::VariableCategory::Allocatable];
2261
+
2262
+ if (fir::isa_aggregate (varType) &&
2263
+ llvm::is_contained (defaultMaps, DefMap::VariableCategory::Aggregate)) {
2264
+ return defaultMaps[DefMap::VariableCategory::Aggregate];
2265
+ }
2266
+
2267
+ return DefMap::ImplicitBehavior::Default;
2268
+ }
2269
+
2270
+ static std::pair<llvm::omp::OpenMPOffloadMappingFlags,
2271
+ mlir::omp::VariableCaptureKind>
2272
+ getImplicitMapTypeAndKind (fir::FirOpBuilder &firOpBuilder,
2273
+ lower::AbstractConverter &converter,
2274
+ DefaultMapsTy &defaultMaps, mlir::Type varType,
2275
+ mlir::Location loc, const semantics::Symbol &sym) {
2276
+ using DefMap = clause::Defaultmap;
2277
+ // Check if a value of type `type` can be passed to the kernel by value.
2278
+ // All kernel parameters are of pointer type, so if the value can be
2279
+ // represented inside of a pointer, then it can be passed by value.
2280
+ auto isLiteralType = [&](mlir::Type type) {
2281
+ const mlir::DataLayout &dl = firOpBuilder.getDataLayout ();
2282
+ mlir::Type ptrTy =
2283
+ mlir::LLVM::LLVMPointerType::get (&converter.getMLIRContext ());
2284
+ uint64_t ptrSize = dl.getTypeSize (ptrTy);
2285
+ uint64_t ptrAlign = dl.getTypePreferredAlignment (ptrTy);
2286
+
2287
+ auto [size, align] = fir::getTypeSizeAndAlignmentOrCrash (
2288
+ loc, type, dl, converter.getKindMap ());
2289
+ return size <= ptrSize && align <= ptrAlign;
2290
+ };
2291
+
2292
+ llvm::omp::OpenMPOffloadMappingFlags mapFlag =
2293
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
2294
+
2295
+ auto implicitBehaviour = getDefaultmapIfPresent (defaultMaps, varType);
2296
+ if (implicitBehaviour == DefMap::ImplicitBehavior::Default) {
2297
+ mlir::omp::VariableCaptureKind captureKind =
2298
+ mlir::omp::VariableCaptureKind::ByRef;
2299
+
2300
+ // If a variable is specified in declare target link and if device
2301
+ // type is not specified as `nohost`, it needs to be mapped tofrom
2302
+ mlir::ModuleOp mod = firOpBuilder.getModule ();
2303
+ mlir::Operation *op = mod.lookupSymbol (converter.mangleName (sym));
2304
+ auto declareTargetOp =
2305
+ llvm::dyn_cast_if_present<mlir::omp::DeclareTargetInterface>(op);
2306
+ if (declareTargetOp && declareTargetOp.isDeclareTarget ()) {
2307
+ if (declareTargetOp.getDeclareTargetCaptureClause () ==
2308
+ mlir::omp::DeclareTargetCaptureClause::link &&
2309
+ declareTargetOp.getDeclareTargetDeviceType () !=
2310
+ mlir::omp::DeclareTargetDeviceType::nohost) {
2311
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2312
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2313
+ }
2314
+ } else if (fir::isa_trivial (varType) || fir::isa_char (varType)) {
2315
+ // Scalars behave as if they were "firstprivate".
2316
+ // TODO: Handle objects that are shared/lastprivate or were listed
2317
+ // in an in_reduction clause.
2318
+ if (isLiteralType (varType)) {
2319
+ captureKind = mlir::omp::VariableCaptureKind::ByCopy;
2320
+ } else {
2321
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2322
+ }
2323
+ } else if (!fir::isa_builtin_cptr_type (varType)) {
2324
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2325
+ mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2326
+ }
2327
+ return std::make_pair (mapFlag, captureKind);
2328
+ }
2329
+
2330
+ switch (implicitBehaviour) {
2331
+ case DefMap::ImplicitBehavior::Alloc:
2332
+ return std::make_pair (llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE,
2333
+ mlir::omp::VariableCaptureKind::ByRef);
2334
+ break ;
2335
+ case DefMap::ImplicitBehavior::Firstprivate:
2336
+ case DefMap::ImplicitBehavior::None:
2337
+ TODO (loc, " Firstprivate and None are currently unsupported defaultmap "
2338
+ " behaviour" );
2339
+ break ;
2340
+ case DefMap::ImplicitBehavior::From:
2341
+ return std::make_pair (mapFlag |=
2342
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM,
2343
+ mlir::omp::VariableCaptureKind::ByRef);
2344
+ break ;
2345
+ case DefMap::ImplicitBehavior::Present:
2346
+ return std::make_pair (mapFlag |=
2347
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT,
2348
+ mlir::omp::VariableCaptureKind::ByRef);
2349
+ break ;
2350
+ case DefMap::ImplicitBehavior::To:
2351
+ return std::make_pair (mapFlag |=
2352
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
2353
+ (fir::isa_trivial (varType) || fir::isa_char (varType))
2354
+ ? mlir::omp::VariableCaptureKind::ByCopy
2355
+ : mlir::omp::VariableCaptureKind::ByRef);
2356
+ break ;
2357
+ case DefMap::ImplicitBehavior::Tofrom:
2358
+ return std::make_pair (mapFlag |=
2359
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM |
2360
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
2361
+ mlir::omp::VariableCaptureKind::ByRef);
2362
+ break ;
2363
+ case DefMap::ImplicitBehavior::Default:
2364
+ llvm_unreachable (
2365
+ " Implicit None Behaviour Should Have Been Handled Earlier" );
2366
+ break ;
2367
+ }
2368
+
2369
+ return std::make_pair (mapFlag |=
2370
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM |
2371
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO,
2372
+ mlir::omp::VariableCaptureKind::ByRef);
2373
+ }
2374
+
2234
2375
static mlir::omp::TargetOp
2235
2376
genTargetOp (lower::AbstractConverter &converter, lower::SymMap &symTable,
2236
2377
lower::StatementContext &stmtCtx,
@@ -2247,32 +2388,19 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
2247
2388
hostEvalInfo.emplace_back ();
2248
2389
2249
2390
mlir::omp::TargetOperands clauseOps;
2391
+ DefaultMapsTy defaultMaps;
2250
2392
llvm::SmallVector<const semantics::Symbol *> mapSyms, isDevicePtrSyms,
2251
2393
hasDeviceAddrSyms;
2252
2394
genTargetClauses (converter, semaCtx, symTable, stmtCtx, eval, item->clauses ,
2253
- loc, clauseOps, hasDeviceAddrSyms, isDevicePtrSyms, mapSyms);
2395
+ loc, clauseOps, defaultMaps, hasDeviceAddrSyms,
2396
+ isDevicePtrSyms, mapSyms);
2254
2397
2255
2398
DataSharingProcessor dsp (converter, semaCtx, item->clauses , eval,
2256
2399
/* shouldCollectPreDeterminedSymbols=*/
2257
2400
lower::omp::isLastItemInQueue (item, queue),
2258
2401
/* useDelayedPrivatization=*/ true , symTable);
2259
2402
dsp.processStep1 (&clauseOps);
2260
2403
2261
- // Check if a value of type `type` can be passed to the kernel by value.
2262
- // All kernel parameters are of pointer type, so if the value can be
2263
- // represented inside of a pointer, then it can be passed by value.
2264
- auto isLiteralType = [&](mlir::Type type) {
2265
- const mlir::DataLayout &dl = firOpBuilder.getDataLayout ();
2266
- mlir::Type ptrTy =
2267
- mlir::LLVM::LLVMPointerType::get (&converter.getMLIRContext ());
2268
- uint64_t ptrSize = dl.getTypeSize (ptrTy);
2269
- uint64_t ptrAlign = dl.getTypePreferredAlignment (ptrTy);
2270
-
2271
- auto [size, align] = fir::getTypeSizeAndAlignmentOrCrash (
2272
- loc, type, dl, converter.getKindMap ());
2273
- return size <= ptrSize && align <= ptrAlign;
2274
- };
2275
-
2276
2404
// 5.8.1 Implicit Data-Mapping Attribute Rules
2277
2405
// The following code follows the implicit data-mapping rules to map all the
2278
2406
// symbols used inside the region that do not have explicit data-environment
@@ -2334,56 +2462,25 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
2334
2462
firOpBuilder, info, dataExv,
2335
2463
semantics::IsAssumedSizeArray (sym.GetUltimate ()),
2336
2464
converter.getCurrentLocation ());
2337
-
2338
- llvm::omp::OpenMPOffloadMappingFlags mapFlag =
2339
- llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
2340
- mlir::omp::VariableCaptureKind captureKind =
2341
- mlir::omp::VariableCaptureKind::ByRef;
2342
-
2343
2465
mlir::Value baseOp = info.rawInput ;
2344
2466
mlir::Type eleType = baseOp.getType ();
2345
2467
if (auto refType = mlir::dyn_cast<fir::ReferenceType>(baseOp.getType ()))
2346
2468
eleType = refType.getElementType ();
2347
2469
2348
- // If a variable is specified in declare target link and if device
2349
- // type is not specified as `nohost`, it needs to be mapped tofrom
2350
- mlir::ModuleOp mod = firOpBuilder.getModule ();
2351
- mlir::Operation *op = mod.lookupSymbol (converter.mangleName (sym));
2352
- auto declareTargetOp =
2353
- llvm::dyn_cast_if_present<mlir::omp::DeclareTargetInterface>(op);
2354
- if (declareTargetOp && declareTargetOp.isDeclareTarget ()) {
2355
- if (declareTargetOp.getDeclareTargetCaptureClause () ==
2356
- mlir::omp::DeclareTargetCaptureClause::link &&
2357
- declareTargetOp.getDeclareTargetDeviceType () !=
2358
- mlir::omp::DeclareTargetDeviceType::nohost) {
2359
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2360
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2361
- }
2362
- } else if (fir::isa_trivial (eleType) || fir::isa_char (eleType)) {
2363
- // Scalars behave as if they were "firstprivate".
2364
- // TODO: Handle objects that are shared/lastprivate or were listed
2365
- // in an in_reduction clause.
2366
- if (isLiteralType (eleType)) {
2367
- captureKind = mlir::omp::VariableCaptureKind::ByCopy;
2368
- } else {
2369
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2370
- }
2371
- } else if (!fir::isa_builtin_cptr_type (eleType)) {
2372
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2373
- mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2374
- }
2375
- auto location =
2376
- mlir::NameLoc::get (mlir::StringAttr::get (firOpBuilder.getContext (),
2377
- sym.name ().ToString ()),
2378
- baseOp.getLoc ());
2470
+ std::pair<llvm::omp::OpenMPOffloadMappingFlags,
2471
+ mlir::omp::VariableCaptureKind>
2472
+ mapFlagAndKind = getImplicitMapTypeAndKind (
2473
+ firOpBuilder, converter, defaultMaps, eleType, loc, sym);
2474
+
2379
2475
mlir::Value mapOp = createMapInfoOp (
2380
- firOpBuilder, location , baseOp, /* varPtrPtr= */ mlir::Value{} ,
2381
- name.str (), bounds, /* members=*/ {},
2476
+ firOpBuilder, converter. getCurrentLocation () , baseOp,
2477
+ /* varPtrPtr= */ mlir::Value{}, name.str (), bounds, /* members=*/ {},
2382
2478
/* membersIndex=*/ mlir::ArrayAttr{},
2383
2479
static_cast <
2384
2480
std::underlying_type_t <llvm::omp::OpenMPOffloadMappingFlags>>(
2385
- mapFlag),
2386
- captureKind, baseOp.getType (), /* partialMap=*/ false , mapperId);
2481
+ std::get<0 >(mapFlagAndKind)),
2482
+ std::get<1 >(mapFlagAndKind), baseOp.getType (),
2483
+ /* partialMap=*/ false , mapperId);
2387
2484
2388
2485
clauseOps.mapVars .push_back (mapOp);
2389
2486
mapSyms.push_back (&sym);
@@ -4062,6 +4159,7 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
4062
4159
!std::holds_alternative<clause::Copyin>(clause.u ) &&
4063
4160
!std::holds_alternative<clause::Copyprivate>(clause.u ) &&
4064
4161
!std::holds_alternative<clause::Default>(clause.u ) &&
4162
+ !std::holds_alternative<clause::Defaultmap>(clause.u ) &&
4065
4163
!std::holds_alternative<clause::Depend>(clause.u ) &&
4066
4164
!std::holds_alternative<clause::Filter>(clause.u ) &&
4067
4165
!std::holds_alternative<clause::Final>(clause.u ) &&
0 commit comments