@@ -980,6 +980,145 @@ static void genLoopVars(
980980 firOpBuilder.setInsertionPointAfter (storeOp);
981981}
982982
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+
9831122static void
9841123markDeclareTarget (mlir::Operation *op, lower::AbstractConverter &converter,
9851124 mlir::omp::DeclareTargetCaptureClause captureClause,
@@ -1677,11 +1816,13 @@ static void genTargetClauses(
16771816 lower::SymMap &symTable, lower::StatementContext &stmtCtx,
16781817 lower::pft::Evaluation &eval, const List<Clause> &clauses,
16791818 mlir::Location loc, mlir::omp::TargetOperands &clauseOps,
1819+ DefaultMapsTy &defaultMaps,
16801820 llvm::SmallVectorImpl<const semantics::Symbol *> &hasDeviceAddrSyms,
16811821 llvm::SmallVectorImpl<const semantics::Symbol *> &isDevicePtrSyms,
16821822 llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms) {
16831823 ClauseProcessor cp (converter, semaCtx, clauses);
16841824 cp.processBare (clauseOps);
1825+ cp.processDefaultMap (stmtCtx, defaultMaps);
16851826 cp.processDepend (symTable, stmtCtx, clauseOps);
16861827 cp.processDevice (stmtCtx, clauseOps);
16871828 cp.processHasDeviceAddr (stmtCtx, clauseOps, hasDeviceAddrSyms);
@@ -1696,9 +1837,8 @@ static void genTargetClauses(
16961837 cp.processNowait (clauseOps);
16971838 cp.processThreadLimit (stmtCtx, clauseOps);
16981839
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);
17021842
17031843 // `target private(..)` is only supported in delayed privatization mode.
17041844 if (!enableDelayedPrivatizationStaging)
@@ -2242,32 +2382,19 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
22422382 hostEvalInfo.emplace_back ();
22432383
22442384 mlir::omp::TargetOperands clauseOps;
2385+ DefaultMapsTy defaultMaps;
22452386 llvm::SmallVector<const semantics::Symbol *> mapSyms, isDevicePtrSyms,
22462387 hasDeviceAddrSyms;
22472388 genTargetClauses (converter, semaCtx, symTable, stmtCtx, eval, item->clauses ,
2248- loc, clauseOps, hasDeviceAddrSyms, isDevicePtrSyms, mapSyms);
2389+ loc, clauseOps, defaultMaps, hasDeviceAddrSyms,
2390+ isDevicePtrSyms, mapSyms);
22492391
22502392 DataSharingProcessor dsp (converter, semaCtx, item->clauses , eval,
22512393 /* shouldCollectPreDeterminedSymbols=*/
22522394 lower::omp::isLastItemInQueue (item, queue),
22532395 /* useDelayedPrivatization=*/ true , symTable);
22542396 dsp.processStep1 (&clauseOps);
22552397
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-
22712398 // 5.8.1 Implicit Data-Mapping Attribute Rules
22722399 // The following code follows the implicit data-mapping rules to map all the
22732400 // symbols used inside the region that do not have explicit data-environment
@@ -2330,56 +2457,25 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
23302457 firOpBuilder, info, dataExv,
23312458 semantics::IsAssumedSizeArray (sym.GetUltimate ()),
23322459 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-
23392460 mlir::Value baseOp = info.rawInput ;
23402461 mlir::Type eleType = baseOp.getType ();
23412462 if (auto refType = mlir::dyn_cast<fir::ReferenceType>(baseOp.getType ()))
23422463 eleType = refType.getElementType ();
23432464
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+
23752470 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=*/ {},
23782473 /* membersIndex=*/ mlir::ArrayAttr{},
23792474 static_cast <
23802475 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);
23832479
23842480 clauseOps.mapVars .push_back (mapOp);
23852481 mapSyms.push_back (&sym);
@@ -4199,6 +4295,7 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
41994295 !std::holds_alternative<clause::Copyin>(clause.u ) &&
42004296 !std::holds_alternative<clause::Copyprivate>(clause.u ) &&
42014297 !std::holds_alternative<clause::Default>(clause.u ) &&
4298+ !std::holds_alternative<clause::Defaultmap>(clause.u ) &&
42024299 !std::holds_alternative<clause::Depend>(clause.u ) &&
42034300 !std::holds_alternative<clause::Filter>(clause.u ) &&
42044301 !std::holds_alternative<clause::Final>(clause.u ) &&
0 commit comments