@@ -1700,11 +1700,13 @@ 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) {
17061707 ClauseProcessor cp (converter, semaCtx, clauses);
17071708 cp.processBare (clauseOps);
1709+ cp.processDefaultMap (stmtCtx, defaultMaps);
17081710 cp.processDepend (symTable, stmtCtx, clauseOps);
17091711 cp.processDevice (stmtCtx, clauseOps);
17101712 cp.processHasDeviceAddr (stmtCtx, clauseOps, hasDeviceAddrSyms);
@@ -1719,9 +1721,8 @@ static void genTargetClauses(
17191721 cp.processNowait (clauseOps);
17201722 cp.processThreadLimit (stmtCtx, clauseOps);
17211723
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);
17251726
17261727 // `target private(..)` is only supported in delayed privatization mode.
17271728 if (!enableDelayedPrivatizationStaging)
@@ -2231,6 +2232,146 @@ genSingleOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
22312232 queue, item, clauseOps);
22322233}
22332234
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+
22342375static mlir::omp::TargetOp
22352376genTargetOp (lower::AbstractConverter &converter, lower::SymMap &symTable,
22362377 lower::StatementContext &stmtCtx,
@@ -2247,32 +2388,19 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
22472388 hostEvalInfo.emplace_back ();
22482389
22492390 mlir::omp::TargetOperands clauseOps;
2391+ DefaultMapsTy defaultMaps;
22502392 llvm::SmallVector<const semantics::Symbol *> mapSyms, isDevicePtrSyms,
22512393 hasDeviceAddrSyms;
22522394 genTargetClauses (converter, semaCtx, symTable, stmtCtx, eval, item->clauses ,
2253- loc, clauseOps, hasDeviceAddrSyms, isDevicePtrSyms, mapSyms);
2395+ loc, clauseOps, defaultMaps, hasDeviceAddrSyms,
2396+ isDevicePtrSyms, mapSyms);
22542397
22552398 DataSharingProcessor dsp (converter, semaCtx, item->clauses , eval,
22562399 /* shouldCollectPreDeterminedSymbols=*/
22572400 lower::omp::isLastItemInQueue (item, queue),
22582401 /* useDelayedPrivatization=*/ true , symTable);
22592402 dsp.processStep1 (&clauseOps);
22602403
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-
22762404 // 5.8.1 Implicit Data-Mapping Attribute Rules
22772405 // The following code follows the implicit data-mapping rules to map all the
22782406 // symbols used inside the region that do not have explicit data-environment
@@ -2334,56 +2462,25 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
23342462 firOpBuilder, info, dataExv,
23352463 semantics::IsAssumedSizeArray (sym.GetUltimate ()),
23362464 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-
23432465 mlir::Value baseOp = info.rawInput ;
23442466 mlir::Type eleType = baseOp.getType ();
23452467 if (auto refType = mlir::dyn_cast<fir::ReferenceType>(baseOp.getType ()))
23462468 eleType = refType.getElementType ();
23472469
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+
23792475 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=*/ {},
23822478 /* membersIndex=*/ mlir::ArrayAttr{},
23832479 static_cast <
23842480 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);
23872484
23882485 clauseOps.mapVars .push_back (mapOp);
23892486 mapSyms.push_back (&sym);
@@ -4062,6 +4159,7 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
40624159 !std::holds_alternative<clause::Copyin>(clause.u ) &&
40634160 !std::holds_alternative<clause::Copyprivate>(clause.u ) &&
40644161 !std::holds_alternative<clause::Default>(clause.u ) &&
4162+ !std::holds_alternative<clause::Defaultmap>(clause.u ) &&
40654163 !std::holds_alternative<clause::Depend>(clause.u ) &&
40664164 !std::holds_alternative<clause::Filter>(clause.u ) &&
40674165 !std::holds_alternative<clause::Final>(clause.u ) &&
0 commit comments