Skip to content

Commit 96134b2

Browse files
committed
[Flang][MLIR][OpenMP] Align map clause generation and fix issue with non-shared allocations for assumed shape/size descriptor types
This PR aims unify the map argument generation across both the implicit capture (captured in a target region) and the explicit capture (process map), currently the varPtr field of the MapInfo for the same variable will be different depending on how it's captured. This PR tries to align that across the generations of MapInfoOp in the OpenMP lowering. Currently, I have opted to utilise the rawInput (input memref to a HLFIR DeclareInfoOp) as opposed to the addr field which includes more information. The side affect of this is that we have to deal with BoxTypes less often, which will result in simpler maps in these cases. The negative side affect of this is that we don't have access to the bounds information through the resulting value, however, I believe the bounds information we require in our case is still appropriately stored in the map bounds, and this seems to be the case from testing so far. The other fix is for cases where we end up with a BoxType argument into a function (certain assumed shape and sizes cases do this) that has no fir.ref wrapping it. As we need the Box to be a reference type to actually utilise the operation to access the base address stored inside and create the correct mappings we currently generate an intermediate allocation in these cases, and then store into it, and utilise this as the map argument, as opposed to the original. However, as we were not sharing the same intermediate allocation across all of the maps for a variable, this resulted in errors in certain cases when detatching/attatching the data e.g. via enter and exit. This PR adjusts this for cases Currently we only maintain tracking of all intermediate allocations for the current function scope, as opposed to module. Primarily as the only case I am aware of that this is required is in cases where we pass certain types of arguments to functions (so I opted to minimize the overhead of the pass for now). It could likely be extended to module scope if required if we find other cases where it's applicable and causing issues.
1 parent 6bd0a22 commit 96134b2

File tree

9 files changed

+147
-149
lines changed

9 files changed

+147
-149
lines changed

flang/include/flang/Optimizer/Transforms/Passes.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,11 +342,11 @@ def LoopVersioning : Pass<"loop-versioning", "mlir::func::FuncOp"> {
342342
}
343343

344344
def OMPMapInfoFinalizationPass
345-
: Pass<"omp-map-info-finalization"> {
345+
: Pass<"omp-map-info-finalization", "mlir::func::FuncOp"> {
346346
let summary = "expands OpenMP MapInfo operations containing descriptors";
347347
let description = [{
348-
Expands MapInfo operations containing descriptor types into multiple
349-
MapInfo's for each pointer element in the descriptor that requires
348+
Expands MapInfo operations containing descriptor types into multiple
349+
MapInfo's for each pointer element in the descriptor that requires
350350
explicit individual mapping by the OpenMP runtime.
351351
}];
352352
let dependentDialects = ["mlir::omp::OpenMPDialect"];

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -970,25 +970,21 @@ bool ClauseProcessor::processMap(
970970
object.ref(), clauseLocation, asFortran, bounds,
971971
treatIndexAsSection);
972972

973-
auto origSymbol = converter.getSymbolAddress(*object.sym());
974-
mlir::Value symAddr = info.addr;
975-
if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
976-
symAddr = origSymbol;
977-
978973
// Explicit map captures are captured ByRef by default,
979974
// optimisation passes may alter this to ByCopy or other capture
980975
// types to optimise
976+
mlir::Value baseOp = info.rawInput;
981977
auto location = mlir::NameLoc::get(
982978
mlir::StringAttr::get(firOpBuilder.getContext(), asFortran.str()),
983-
symAddr.getLoc());
979+
baseOp.getLoc());
984980
mlir::omp::MapInfoOp mapOp = createMapInfoOp(
985-
firOpBuilder, location, symAddr,
981+
firOpBuilder, location, baseOp,
986982
/*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds,
987983
/*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{},
988984
static_cast<
989985
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
990986
mapTypeBits),
991-
mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());
987+
mlir::omp::VariableCaptureKind::ByRef, baseOp.getType());
992988

993989
if (object.sym()->owner().IsDerivedType()) {
994990
addChildIndexAndMapToParent(object, parentMemberIndices, mapOp,
@@ -997,9 +993,9 @@ bool ClauseProcessor::processMap(
997993
result.mapVars.push_back(mapOp);
998994
ptrMapSyms->push_back(object.sym());
999995
if (mapSymTypes)
1000-
mapSymTypes->push_back(symAddr.getType());
996+
mapSymTypes->push_back(baseOp.getType());
1001997
if (mapSymLocs)
1002-
mapSymLocs->push_back(symAddr.getLoc());
998+
mapSymLocs->push_back(baseOp.getLoc());
1003999
}
10041000
}
10051001
});
@@ -1102,30 +1098,26 @@ bool ClauseProcessor::processUseDeviceAddr(
11021098
object.ref(), location, asFortran, bounds,
11031099
treatIndexAsSection);
11041100

1105-
auto origSymbol = converter.getSymbolAddress(*object.sym());
1106-
mlir::Value symAddr = info.addr;
1107-
if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
1108-
symAddr = origSymbol;
1109-
11101101
// Explicit map captures are captured ByRef by default,
11111102
// optimisation passes may alter this to ByCopy or other capture
11121103
// types to optimise
1104+
mlir::Value baseOp = info.rawInput;
11131105
mlir::omp::MapInfoOp mapOp = createMapInfoOp(
1114-
firOpBuilder, location, symAddr,
1106+
firOpBuilder, location, baseOp,
11151107
/*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds,
11161108
/*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{},
11171109
static_cast<
11181110
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
11191111
mapTypeBits),
1120-
mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());
1112+
mlir::omp::VariableCaptureKind::ByRef, baseOp.getType());
11211113

11221114
if (object.sym()->owner().IsDerivedType()) {
11231115
addChildIndexAndMapToParent(object, parentMemberIndices, mapOp,
11241116
semaCtx);
11251117
} else {
11261118
useDeviceSyms.push_back(object.sym());
1127-
useDeviceTypes.push_back(symAddr.getType());
1128-
useDeviceLocs.push_back(symAddr.getLoc());
1119+
useDeviceTypes.push_back(baseOp.getType());
1120+
useDeviceLocs.push_back(baseOp.getLoc());
11291121
result.useDeviceAddrVars.push_back(mapOp);
11301122
}
11311123
}
@@ -1167,30 +1159,26 @@ bool ClauseProcessor::processUseDevicePtr(
11671159
object.ref(), location, asFortran, bounds,
11681160
treatIndexAsSection);
11691161

1170-
auto origSymbol = converter.getSymbolAddress(*object.sym());
1171-
mlir::Value symAddr = info.addr;
1172-
if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
1173-
symAddr = origSymbol;
1174-
11751162
// Explicit map captures are captured ByRef by default,
11761163
// optimisation passes may alter this to ByCopy or other capture
11771164
// types to optimise
1165+
mlir::Value baseOp = info.rawInput;
11781166
mlir::omp::MapInfoOp mapOp = createMapInfoOp(
1179-
firOpBuilder, location, symAddr,
1167+
firOpBuilder, location, baseOp,
11801168
/*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds,
11811169
/*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{},
11821170
static_cast<
11831171
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
11841172
mapTypeBits),
1185-
mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());
1173+
mlir::omp::VariableCaptureKind::ByRef, baseOp.getType());
11861174

11871175
if (object.sym()->owner().IsDerivedType()) {
11881176
addChildIndexAndMapToParent(object, parentMemberIndices, mapOp,
11891177
semaCtx);
11901178
} else {
11911179
useDeviceSyms.push_back(object.sym());
1192-
useDeviceTypes.push_back(symAddr.getType());
1193-
useDeviceLocs.push_back(symAddr.getLoc());
1180+
useDeviceTypes.push_back(baseOp.getType());
1181+
useDeviceLocs.push_back(baseOp.getLoc());
11941182
result.useDevicePtrVars.push_back(mapOp);
11951183
}
11961184
}

flang/lib/Lower/OpenMP/ClauseProcessor.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,22 +215,18 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
215215
object.ref(), clauseLocation, asFortran, bounds,
216216
treatIndexAsSection);
217217

218-
auto origSymbol = converter.getSymbolAddress(*object.sym());
219-
mlir::Value symAddr = info.addr;
220-
if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
221-
symAddr = origSymbol;
222-
223218
// Explicit map captures are captured ByRef by default,
224219
// optimisation passes may alter this to ByCopy or other capture
225220
// types to optimise
221+
mlir::Value baseOp = info.rawInput;
226222
mlir::omp::MapInfoOp mapOp = createMapInfoOp(
227-
firOpBuilder, clauseLocation, symAddr,
223+
firOpBuilder, clauseLocation, baseOp,
228224
/*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds,
229225
/*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{},
230226
static_cast<
231227
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
232228
mapTypeBits),
233-
mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());
229+
mlir::omp::VariableCaptureKind::ByRef, baseOp.getType());
234230

235231
if (object.sym()->owner().IsDerivedType()) {
236232
addChildIndexAndMapToParent(object, parentMemberIndices, mapOp,

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 74 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,90 +2024,88 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
20242024
if (llvm::find(mapSyms, common) != mapSyms.end())
20252025
return;
20262026

2027-
if (llvm::find(mapSyms, &sym) == mapSyms.end()) {
2028-
mlir::Value baseOp = converter.getSymbolAddress(sym);
2029-
if (!baseOp)
2030-
if (const auto *details =
2031-
sym.template detailsIf<semantics::HostAssocDetails>()) {
2032-
baseOp = converter.getSymbolAddress(details->symbol());
2033-
converter.copySymbolBinding(details->symbol(), sym);
2034-
}
2027+
// If we come across a symbol without a symbol address, we return as we
2028+
// cannot process it, this is intended as a catch all early exit for
2029+
// symbols that do not have a corresponding extended value. Such as
2030+
// subroutines, interfaces and named blocks.
2031+
if (!converter.getSymbolAddress(sym))
2032+
return;
20352033

2036-
if (baseOp) {
2037-
llvm::SmallVector<mlir::Value> bounds;
2038-
std::stringstream name;
2039-
fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(sym);
2040-
name << sym.name().ToString();
2041-
2042-
lower::AddrAndBoundsInfo info = getDataOperandBaseAddr(
2043-
converter, firOpBuilder, sym, converter.getCurrentLocation());
2044-
if (mlir::isa<fir::BaseBoxType>(
2045-
fir::unwrapRefType(info.addr.getType())))
2046-
bounds = lower::genBoundsOpsFromBox<mlir::omp::MapBoundsOp,
2047-
mlir::omp::MapBoundsType>(
2048-
firOpBuilder, converter.getCurrentLocation(), dataExv, info);
2049-
if (mlir::isa<fir::SequenceType>(
2050-
fir::unwrapRefType(info.addr.getType()))) {
2051-
bool dataExvIsAssumedSize =
2052-
semantics::IsAssumedSizeArray(sym.GetUltimate());
2053-
bounds = lower::genBaseBoundsOps<mlir::omp::MapBoundsOp,
2054-
mlir::omp::MapBoundsType>(
2055-
firOpBuilder, converter.getCurrentLocation(), dataExv,
2056-
dataExvIsAssumedSize);
2057-
}
2034+
if (llvm::find(mapSyms, &sym) != mapSyms.end())
2035+
return;
20582036

2059-
llvm::omp::OpenMPOffloadMappingFlags mapFlag =
2060-
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
2061-
mlir::omp::VariableCaptureKind captureKind =
2062-
mlir::omp::VariableCaptureKind::ByRef;
2063-
2064-
mlir::Type eleType = baseOp.getType();
2065-
if (auto refType = mlir::dyn_cast<fir::ReferenceType>(baseOp.getType()))
2066-
eleType = refType.getElementType();
2067-
2068-
// If a variable is specified in declare target link and if device
2069-
// type is not specified as `nohost`, it needs to be mapped tofrom
2070-
mlir::ModuleOp mod = firOpBuilder.getModule();
2071-
mlir::Operation *op = mod.lookupSymbol(converter.mangleName(sym));
2072-
auto declareTargetOp =
2073-
llvm::dyn_cast_if_present<mlir::omp::DeclareTargetInterface>(op);
2074-
if (declareTargetOp && declareTargetOp.isDeclareTarget()) {
2075-
if (declareTargetOp.getDeclareTargetCaptureClause() ==
2076-
mlir::omp::DeclareTargetCaptureClause::link &&
2077-
declareTargetOp.getDeclareTargetDeviceType() !=
2078-
mlir::omp::DeclareTargetDeviceType::nohost) {
2079-
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2080-
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2081-
}
2082-
} else if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) {
2083-
captureKind = mlir::omp::VariableCaptureKind::ByCopy;
2084-
} else if (!fir::isa_builtin_cptr_type(eleType)) {
2085-
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2086-
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
2087-
}
2088-
auto location =
2089-
mlir::NameLoc::get(mlir::StringAttr::get(firOpBuilder.getContext(),
2090-
sym.name().ToString()),
2091-
baseOp.getLoc());
2092-
mlir::Value mapOp = createMapInfoOp(
2093-
firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{},
2094-
name.str(), bounds, /*members=*/{},
2095-
/*membersIndex=*/mlir::DenseIntElementsAttr{},
2096-
static_cast<
2097-
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
2098-
mapFlag),
2099-
captureKind, baseOp.getType());
2037+
if (const auto *details =
2038+
sym.template detailsIf<semantics::HostAssocDetails>())
2039+
converter.copySymbolBinding(details->symbol(), sym);
2040+
llvm::SmallVector<mlir::Value> bounds;
2041+
std::stringstream name;
2042+
fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(sym);
2043+
name << sym.name().ToString();
2044+
2045+
lower::AddrAndBoundsInfo info = getDataOperandBaseAddr(
2046+
converter, firOpBuilder, sym, converter.getCurrentLocation());
2047+
mlir::Value baseOp = info.rawInput;
2048+
if (mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(baseOp.getType())))
2049+
bounds = lower::genBoundsOpsFromBox<mlir::omp::MapBoundsOp,
2050+
mlir::omp::MapBoundsType>(
2051+
firOpBuilder, converter.getCurrentLocation(), dataExv, info);
2052+
if (mlir::isa<fir::SequenceType>(fir::unwrapRefType(baseOp.getType()))) {
2053+
bool dataExvIsAssumedSize =
2054+
semantics::IsAssumedSizeArray(sym.GetUltimate());
2055+
bounds = lower::genBaseBoundsOps<mlir::omp::MapBoundsOp,
2056+
mlir::omp::MapBoundsType>(
2057+
firOpBuilder, converter.getCurrentLocation(), dataExv,
2058+
dataExvIsAssumedSize);
2059+
}
21002060

2101-
clauseOps.mapVars.push_back(mapOp);
2102-
mapSyms.push_back(&sym);
2103-
mapLocs.push_back(baseOp.getLoc());
2104-
mapTypes.push_back(baseOp.getType());
2061+
llvm::omp::OpenMPOffloadMappingFlags mapFlag =
2062+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
2063+
mlir::omp::VariableCaptureKind captureKind =
2064+
mlir::omp::VariableCaptureKind::ByRef;
2065+
2066+
mlir::Type eleType = baseOp.getType();
2067+
if (auto refType = mlir::dyn_cast<fir::ReferenceType>(baseOp.getType()))
2068+
eleType = refType.getElementType();
2069+
2070+
// If a variable is specified in declare target link and if device
2071+
// type is not specified as `nohost`, it needs to be mapped tofrom
2072+
mlir::ModuleOp mod = firOpBuilder.getModule();
2073+
mlir::Operation *op = mod.lookupSymbol(converter.mangleName(sym));
2074+
auto declareTargetOp =
2075+
llvm::dyn_cast_if_present<mlir::omp::DeclareTargetInterface>(op);
2076+
if (declareTargetOp && declareTargetOp.isDeclareTarget()) {
2077+
if (declareTargetOp.getDeclareTargetCaptureClause() ==
2078+
mlir::omp::DeclareTargetCaptureClause::link &&
2079+
declareTargetOp.getDeclareTargetDeviceType() !=
2080+
mlir::omp::DeclareTargetDeviceType::nohost) {
2081+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2082+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
21052083
}
2084+
} else if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) {
2085+
captureKind = mlir::omp::VariableCaptureKind::ByCopy;
2086+
} else if (!fir::isa_builtin_cptr_type(eleType)) {
2087+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
2088+
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
21062089
}
2090+
auto location = mlir::NameLoc::get(
2091+
mlir::StringAttr::get(firOpBuilder.getContext(), sym.name().ToString()),
2092+
baseOp.getLoc());
2093+
mlir::Value mapOp = createMapInfoOp(
2094+
firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{}, name.str(),
2095+
bounds, /*members=*/{},
2096+
/*membersIndex=*/mlir::DenseIntElementsAttr{},
2097+
static_cast<
2098+
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
2099+
mapFlag),
2100+
captureKind, baseOp.getType());
2101+
2102+
clauseOps.mapVars.push_back(mapOp);
2103+
mapSyms.push_back(&sym);
2104+
mapLocs.push_back(baseOp.getLoc());
2105+
mapTypes.push_back(baseOp.getType());
21072106
};
21082107
lower::pft::visitAllSymbols(eval, captureImplicitMap);
21092108

2110-
21112109
auto targetOp = firOpBuilder.create<mlir::omp::TargetOp>(loc, clauseOps);
21122110
genBodyOfTargetOp(converter, symTable, semaCtx, eval, targetOp, mapSyms,
21132111
mapLocs, mapTypes, dsp, loc, queue, item);

flang/lib/Optimizer/Transforms/OMPMapInfoFinalization.cpp

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ class OMPMapInfoFinalizationPass
5151
: public fir::impl::OMPMapInfoFinalizationPassBase<
5252
OMPMapInfoFinalizationPass> {
5353

54+
/// Tracks any intermediate function/subroutine local allocations we
55+
/// generate for the descriptors of box type dummy arguments, so that
56+
/// we can retrieve it for subsequent reuses within the functions
57+
/// scope.
58+
std::map</*descriptor opaque pointer=*/void *,
59+
/*corresponding local alloca=*/fir::AllocaOp>
60+
localBoxAllocas;
61+
5462
void genDescriptorMemberMaps(mlir::omp::MapInfoOp op,
5563
fir::FirOpBuilder &builder,
5664
mlir::Operation *target) {
@@ -75,14 +83,26 @@ class OMPMapInfoFinalizationPass
7583
// perform an alloca and then store to it and retrieve the data from the new
7684
// alloca.
7785
if (mlir::isa<fir::BaseBoxType>(descriptor.getType())) {
78-
mlir::OpBuilder::InsertPoint insPt = builder.saveInsertionPoint();
79-
mlir::Block *allocaBlock = builder.getAllocaBlock();
80-
assert(allocaBlock && "No alloca block found for this top level op");
81-
builder.setInsertionPointToStart(allocaBlock);
82-
auto alloca = builder.create<fir::AllocaOp>(loc, descriptor.getType());
83-
builder.restoreInsertionPoint(insPt);
84-
builder.create<fir::StoreOp>(loc, descriptor, alloca);
85-
descriptor = alloca;
86+
// If we have already created a local allocation for this BoxType,
87+
// we must be sure to re-use it so that we end up with the same
88+
// allocations being utilised for the same descriptor across all map uses,
89+
// this prevents runtime issues such as not appropriately releasing or
90+
// deleting all mapped data.
91+
auto find = localBoxAllocas.find(descriptor.getAsOpaquePointer());
92+
if (find != localBoxAllocas.end()) {
93+
builder.create<fir::StoreOp>(loc, descriptor, find->second);
94+
descriptor = find->second;
95+
} else {
96+
mlir::OpBuilder::InsertPoint insPt = builder.saveInsertionPoint();
97+
mlir::Block *allocaBlock = builder.getAllocaBlock();
98+
assert(allocaBlock && "No alloca block found for this top level op");
99+
builder.setInsertionPointToStart(allocaBlock);
100+
auto alloca = builder.create<fir::AllocaOp>(loc, descriptor.getType());
101+
builder.restoreInsertionPoint(insPt);
102+
builder.create<fir::StoreOp>(loc, descriptor, alloca);
103+
localBoxAllocas[descriptor.getAsOpaquePointer()] = alloca;
104+
descriptor = alloca;
105+
}
86106
}
87107

88108
mlir::Value baseAddrAddr = builder.create<fir::BoxOffsetOp>(
@@ -243,14 +263,12 @@ class OMPMapInfoFinalizationPass
243263
// operation (usually function) containing the MapInfoOp because this pass
244264
// will mutate siblings of MapInfoOp.
245265
void runOnOperation() override {
246-
mlir::ModuleOp module =
247-
mlir::dyn_cast_or_null<mlir::ModuleOp>(getOperation());
248-
if (!module)
249-
module = getOperation()->getParentOfType<mlir::ModuleOp>();
266+
mlir::func::FuncOp func = getOperation();
267+
mlir::ModuleOp module = func->getParentOfType<mlir::ModuleOp>();
250268
fir::KindMapping kindMap = fir::getKindMapping(module);
251269
fir::FirOpBuilder builder{module, std::move(kindMap)};
252270

253-
getOperation()->walk([&](mlir::omp::MapInfoOp op) {
271+
func->walk([&](mlir::omp::MapInfoOp op) {
254272
// TODO: Currently only supports a single user for the MapInfoOp, this
255273
// is fine for the moment as the Fortran Frontend will generate a
256274
// new MapInfoOp per Target operation for the moment. However, when/if

0 commit comments

Comments
 (0)