Skip to content

Commit bcdabc0

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 b69957f commit bcdabc0

File tree

13 files changed

+533
-73
lines changed

13 files changed

+533
-73
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(lower::StatementContext &stmtCtx,
860+
DefaultMapsTy &result) 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[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(lower::StatementContext &stmtCtx,
114+
DefaultMapsTy &result) 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
@@ -612,7 +612,7 @@ Defaultmap make(const parser::OmpClause::Defaultmap &inp,
612612
MS(Firstprivate, Firstprivate)
613613
MS(None, None)
614614
MS(Default, Default)
615-
// MS(, Present) missing-in-parser
615+
MS(Present, Present)
616616
// clang-format on
617617
);
618618

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 158 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
22342375
static mlir::omp::TargetOp
22352376
genTargetOp(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) &&

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ TYPE_PARSER(construct<OmpMapClause>(
689689
// [OpenMP 5.0]
690690
// 2.19.7.2 defaultmap(implicit-behavior[:variable-category])
691691
// implicit-behavior -> ALLOC | TO | FROM | TOFROM | FIRSRTPRIVATE | NONE |
692-
// DEFAULT
692+
// DEFAULT | PRESENT
693693
// variable-category -> ALL | SCALAR | AGGREGATE | ALLOCATABLE | POINTER
694694
TYPE_PARSER(construct<OmpDefaultmapClause>(
695695
construct<OmpDefaultmapClause::ImplicitBehavior>(
@@ -700,7 +700,8 @@ TYPE_PARSER(construct<OmpDefaultmapClause>(
700700
"FIRSTPRIVATE" >>
701701
pure(OmpDefaultmapClause::ImplicitBehavior::Firstprivate) ||
702702
"NONE" >> pure(OmpDefaultmapClause::ImplicitBehavior::None) ||
703-
"DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)),
703+
"DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default) ||
704+
"PRESENT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Present)),
704705
maybe(":" >> nonemptyList(Parser<OmpDefaultmapClause::Modifier>{}))))
705706

706707
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

0 commit comments

Comments
 (0)