Skip to content

Commit 0e13a2d

Browse files
agozillonronlieb
authored andcommitted
Reland/fix conflicts for PR: d679471
1 parent 97d1f92 commit 0e13a2d

File tree

23 files changed

+398
-90
lines changed

23 files changed

+398
-90
lines changed

flang/include/flang/Support/OpenMP-utils.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct EntryBlockArgsEntry {
3434
/// Structure holding the information needed to create and bind entry block
3535
/// arguments associated to all clauses that can define them.
3636
struct EntryBlockArgs {
37+
EntryBlockArgsEntry hasDeviceAddr;
3738
llvm::ArrayRef<mlir::Value> hostEvalVars;
3839
EntryBlockArgsEntry inReduction;
3940
EntryBlockArgsEntry map;
@@ -44,21 +45,21 @@ struct EntryBlockArgs {
4445
EntryBlockArgsEntry useDevicePtr;
4546

4647
bool isValid() const {
47-
return inReduction.isValid() && map.isValid() && priv.isValid() &&
48-
reduction.isValid() && taskReduction.isValid() &&
48+
return hasDeviceAddr.isValid() && inReduction.isValid() && map.isValid() &&
49+
priv.isValid() && reduction.isValid() && taskReduction.isValid() &&
4950
useDeviceAddr.isValid() && useDevicePtr.isValid();
5051
}
5152

5253
auto getSyms() const {
53-
return llvm::concat<const semantics::Symbol *const>(inReduction.syms,
54-
map.syms, priv.syms, reduction.syms, taskReduction.syms,
55-
useDeviceAddr.syms, useDevicePtr.syms);
54+
return llvm::concat<const semantics::Symbol *const>(hasDeviceAddr.syms,
55+
inReduction.syms, map.syms, priv.syms, reduction.syms,
56+
taskReduction.syms, useDeviceAddr.syms, useDevicePtr.syms);
5657
}
5758

5859
auto getVars() const {
59-
return llvm::concat<const mlir::Value>(hostEvalVars, inReduction.vars,
60-
map.vars, priv.vars, reduction.vars, taskReduction.vars,
61-
useDeviceAddr.vars, useDevicePtr.vars);
60+
return llvm::concat<const mlir::Value>(hasDeviceAddr.vars, hostEvalVars,
61+
inReduction.vars, map.vars, priv.vars, reduction.vars,
62+
taskReduction.vars, useDeviceAddr.vars, useDevicePtr.vars);
6263
}
6364
};
6465

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -849,14 +849,34 @@ bool ClauseProcessor::processDepend(mlir::omp::DependClauseOps &result) const {
849849
}
850850

851851
bool ClauseProcessor::processHasDeviceAddr(
852-
mlir::omp::HasDeviceAddrClauseOps &result,
853-
llvm::SmallVectorImpl<const semantics::Symbol *> &isDeviceSyms) const {
854-
return findRepeatableClause<omp::clause::HasDeviceAddr>(
855-
[&](const omp::clause::HasDeviceAddr &devAddrClause,
856-
const parser::CharBlock &) {
857-
addUseDeviceClause(converter, devAddrClause.v, result.hasDeviceAddrVars,
858-
isDeviceSyms);
852+
lower::StatementContext &stmtCtx, mlir::omp::HasDeviceAddrClauseOps &result,
853+
llvm::SmallVectorImpl<const semantics::Symbol *> &hasDeviceSyms) const {
854+
// For HAS_DEVICE_ADDR objects, implicitly map the top-level entities.
855+
// Their address (or the whole descriptor, if the entity had one) will be
856+
// passed to the target region.
857+
std::map<Object, OmpMapParentAndMemberData> parentMemberIndices;
858+
bool clauseFound = findRepeatableClause<omp::clause::HasDeviceAddr>(
859+
[&](const omp::clause::HasDeviceAddr &clause,
860+
const parser::CharBlock &source) {
861+
mlir::Location location = converter.genLocation(source);
862+
llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
863+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
864+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
865+
omp::ObjectList baseObjects;
866+
llvm::transform(clause.v, std::back_inserter(baseObjects),
867+
[&](const omp::Object &object) {
868+
if (auto maybeBase = getBaseObject(object, semaCtx))
869+
return *maybeBase;
870+
return object;
871+
});
872+
processMapObjects(stmtCtx, location, baseObjects, mapTypeBits,
873+
parentMemberIndices, result.hasDeviceAddrVars,
874+
hasDeviceSyms);
859875
});
876+
877+
insertChildMapInfoIntoParent(converter, semaCtx, stmtCtx, parentMemberIndices,
878+
result.hasDeviceAddrVars, hasDeviceSyms);
879+
return clauseFound;
860880
}
861881

862882
bool ClauseProcessor::processIf(

flang/lib/Lower/OpenMP/ClauseProcessor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ class ClauseProcessor {
7272
bool processFinal(lower::StatementContext &stmtCtx,
7373
mlir::omp::FinalClauseOps &result) const;
7474
bool processHasDeviceAddr(
75+
lower::StatementContext &stmtCtx,
7576
mlir::omp::HasDeviceAddrClauseOps &result,
76-
llvm::SmallVectorImpl<const semantics::Symbol *> &isDeviceSyms) const;
77+
llvm::SmallVectorImpl<const semantics::Symbol *> &hasDeviceSyms) const;
7778
bool processHint(mlir::omp::HintClauseOps &result) const;
7879
bool processInclusive(mlir::Location currentLocation,
7980
mlir::omp::InclusiveClauseOps &result) const;

flang/lib/Lower/OpenMP/Clauses.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,12 @@ std::optional<Object> getBaseObject(const Object &object,
159159
return Object{SymbolAndDesignatorExtractor::symbol_addr(comp->symbol()),
160160
ea.Designate(evaluate::DataRef{
161161
SymbolAndDesignatorExtractor::AsRvalueRef(*comp)})};
162-
} else if (base.UnwrapSymbolRef()) {
162+
} else if (auto *symRef = base.UnwrapSymbolRef()) {
163+
// This is the base symbol of the array reference, which is the same
164+
// as the symbol in the input object,
165+
// e.g. A(i) is represented as {Symbol(A), Designator(ArrayRef(A, i))}.
166+
// Here we have the Symbol(A), which is what we started with.
167+
assert(&**symRef == object.sym());
163168
return std::nullopt;
164169
}
165170
} else {

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ static void bindEntryBlockArgs(lower::AbstractConverter &converter,
321321
// Process in clause name alphabetical order to match block arguments order.
322322
// Do not bind host_eval variables because they cannot be used inside of the
323323
// corresponding region, except for very specific cases handled separately.
324+
bindMapLike(args.hasDeviceAddr.syms, op.getHasDeviceAddrBlockArgs());
324325
bindPrivateLike(args.inReduction.syms, args.inReduction.vars,
325326
op.getInReductionBlockArgs());
326327
bindMapLike(args.map.syms, op.getMapBlockArgs());
@@ -1665,7 +1666,7 @@ static void genTargetClauses(
16651666
cp.processBare(clauseOps);
16661667
cp.processDepend(clauseOps);
16671668
cp.processDevice(stmtCtx, clauseOps);
1668-
cp.processHasDeviceAddr(clauseOps, hasDeviceAddrSyms);
1669+
cp.processHasDeviceAddr(stmtCtx, clauseOps, hasDeviceAddrSyms);
16691670
if (!hostEvalInfo.empty()) {
16701671
// Only process host_eval if compiling for the host device.
16711672
processHostEvalClauses(converter, semaCtx, stmtCtx, eval, loc);
@@ -2218,6 +2219,10 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
22182219
if (dsp.getAllSymbolsToPrivatize().contains(&sym))
22192220
return;
22202221

2222+
// These symbols are mapped individually in processHasDeviceAddr.
2223+
if (llvm::is_contained(hasDeviceAddrSyms, &sym))
2224+
return;
2225+
22212226
// Structure component symbols don't have bindings, and can only be
22222227
// explicitly mapped individually. If a member is captured implicitly
22232228
// we map the entirety of the derived type when we find its symbol.
@@ -2307,10 +2312,13 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
23072312

23082313
auto targetOp = firOpBuilder.create<mlir::omp::TargetOp>(loc, clauseOps);
23092314

2310-
llvm::SmallVector<mlir::Value> mapBaseValues;
2315+
llvm::SmallVector<mlir::Value> hasDeviceAddrBaseValues, mapBaseValues;
2316+
extractMappedBaseValues(clauseOps.hasDeviceAddrVars, hasDeviceAddrBaseValues);
23112317
extractMappedBaseValues(clauseOps.mapVars, mapBaseValues);
23122318

23132319
EntryBlockArgs args;
2320+
args.hasDeviceAddr.syms = hasDeviceAddrSyms;
2321+
args.hasDeviceAddr.vars = hasDeviceAddrBaseValues;
23142322
args.hostEvalVars = clauseOps.hostEvalVars;
23152323
// TODO: Add in_reduction syms and vars.
23162324
args.map.syms = mapSyms;

flang/lib/Lower/OpenMP/Utils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ mlir::Value createParentSymAndGenIntermediateMaps(
308308
/// Checks if an omp::Object is an array expression with a subscript, e.g.
309309
/// array(1,2).
310310
auto isArrayExprWithSubscript = [](omp::Object obj) {
311-
if (auto maybeRef = evaluate::ExtractDataRef(*obj.ref())) {
311+
if (auto maybeRef = evaluate::ExtractDataRef(obj.ref())) {
312312
evaluate::DataRef ref = *maybeRef;
313313
if (auto *arr = std::get_if<evaluate::ArrayRef>(&ref.u))
314314
return !arr->subscript().empty();
@@ -459,7 +459,7 @@ getComponentObject(std::optional<Object> object,
459459
if (!object)
460460
return std::nullopt;
461461

462-
auto ref = evaluate::ExtractDataRef(*object.value().ref());
462+
auto ref = evaluate::ExtractDataRef(object.value().ref());
463463
if (!ref)
464464
return std::nullopt;
465465

flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -241,26 +241,44 @@ class MapInfoFinalizationPass
241241
/// allowing `to` mappings, and `target update` not allowing both `to` and
242242
/// `from` simultaneously. We currently try to maintain the `implicit` flag
243243
/// where necessary, although it does not seem strictly required.
244-
unsigned long getDescriptorMapType(mlir::omp::MapInfoOp op,
244+
unsigned long getDescriptorMapType(unsigned long mapTypeFlag,
245245
mlir::Operation *target) {
246246
using mapFlags = llvm::omp::OpenMPOffloadMappingFlags;
247-
unsigned long mapType = op.getMapType().value_or(0);
248247
if (llvm::isa_and_nonnull<mlir::omp::TargetExitDataOp,
249248
mlir::omp::TargetUpdateOp>(target))
250-
return mapType;
249+
return mapTypeFlag;
251250
mapFlags flags = mapFlags::OMP_MAP_TO |
252-
(mapFlags(mapType) & mapFlags::OMP_MAP_IMPLICIT);
251+
(mapFlags(mapTypeFlag) & mapFlags::OMP_MAP_IMPLICIT);
252+
// Descriptors for objects will always be copied. This is because the
253+
// descriptor can be rematerialized by the compiler, and so the addres
254+
// of the descriptor for a given object at one place in the code may
255+
// differ from that address in another place. The contents of the
256+
// descriptor (the base address in particular) will remain unchanged
257+
// though.
253258
// TODO/FIXME: We currently cannot have MAP_CLOSE and MAP_ALWAYS on
254259
// the descriptor at once, these are mutually exclusive and when
255260
// both are applied the runtime will fail to map.
256-
flags |= ((mapFlags(mapType) & mapFlags::OMP_MAP_CLOSE) ==
261+
flags |= ((mapFlags(mapTypeFlag) & mapFlags::OMP_MAP_CLOSE) ==
257262
mapFlags::OMP_MAP_CLOSE)
258263
? mapFlags::OMP_MAP_CLOSE
259264
: mapFlags::OMP_MAP_ALWAYS;
260265
flags |= mapFlags::OMP_MAP_DESCRIPTOR;
261266
return llvm::to_underlying(flags);
262267
}
263268

269+
/// Check if the mapOp is present in the HasDeviceAddr clause on
270+
/// the userOp. Only applies to TargetOp.
271+
bool isHasDeviceAddr(mlir::omp::MapInfoOp mapOp, mlir::Operation *userOp) {
272+
assert(userOp && "Expecting non-null argument");
273+
if (auto targetOp = llvm::dyn_cast<mlir::omp::TargetOp>(userOp)) {
274+
for (mlir::Value hda : targetOp.getHasDeviceAddrVars()) {
275+
if (hda.getDefiningOp() == mapOp)
276+
return true;
277+
}
278+
}
279+
return false;
280+
}
281+
264282
mlir::omp::MapInfoOp genDescriptorMemberMaps(mlir::omp::MapInfoOp op,
265283
fir::FirOpBuilder &builder,
266284
mlir::Operation *target) {
@@ -270,11 +288,11 @@ class MapInfoFinalizationPass
270288
// TODO: map the addendum segment of the descriptor, similarly to the
271289
// base address/data pointer member.
272290
mlir::Value descriptor = getDescriptorFromBoxMap(op, builder);
273-
auto baseAddr = genBaseAddrMap(descriptor, op.getBounds(),
274-
op.getMapType().value_or(0), builder);
291+
275292
mlir::ArrayAttr newMembersAttr;
276293
mlir::SmallVector<mlir::Value> newMembers;
277294
llvm::SmallVector<llvm::SmallVector<int64_t>> memberIndices;
295+
bool IsHasDeviceAddr = isHasDeviceAddr(op, target);
278296

279297
if (!mapMemberUsers.empty() || !op.getMembers().empty())
280298
getMemberIndicesAsVectors(
@@ -288,6 +306,12 @@ class MapInfoFinalizationPass
288306
// member information to now have one new member for the base address, or
289307
// we are expanding a parent that is a descriptor and we have to adjust
290308
// all of its members to reflect the insertion of the base address.
309+
//
310+
// If we're expanding a top-level descriptor for a map operation that
311+
// resulted from "has_device_addr" clause, then we want the base pointer
312+
// from the descriptor to be used verbatim, i.e. without additional
313+
// remapping. To avoid this remapping, simply don't generate any map
314+
// information for the descriptor members.
291315
if (!mapMemberUsers.empty()) {
292316
// Currently, there should only be one user per map when this pass
293317
// is executed. Either a parent map, holding the current map in its
@@ -298,6 +322,8 @@ class MapInfoFinalizationPass
298322
assert(mapMemberUsers.size() == 1 &&
299323
"OMPMapInfoFinalization currently only supports single users of a "
300324
"MapInfoOp");
325+
auto baseAddr = genBaseAddrMap(descriptor, op.getBounds(),
326+
op.getMapType().value_or(0), builder);
301327
ParentAndPlacement mapUser = mapMemberUsers[0];
302328
adjustMemberIndices(memberIndices, mapUser.index);
303329
llvm::SmallVector<mlir::Value> newMemberOps;
@@ -309,7 +335,9 @@ class MapInfoFinalizationPass
309335
mapUser.parent.getMembersMutable().assign(newMemberOps);
310336
mapUser.parent.setMembersIndexAttr(
311337
builder.create2DI64ArrayAttr(memberIndices));
312-
} else {
338+
} else if (!IsHasDeviceAddr) {
339+
auto baseAddr = genBaseAddrMap(descriptor, op.getBounds(),
340+
op.getMapType().value_or(0), builder);
313341
newMembers.push_back(baseAddr);
314342
if (!op.getMembers().empty()) {
315343
for (auto &indices : memberIndices)
@@ -331,7 +359,7 @@ class MapInfoFinalizationPass
331359
/*bounds=*/mlir::SmallVector<mlir::Value>{},
332360
builder.getIntegerAttr(
333361
builder.getIntegerType(64, false),
334-
getDescriptorMapType(op, target)),
362+
getDescriptorMapType(op.getMapType().value_or(0), target)),
335363
/*mapperId*/ mlir::FlatSymbolRefAttr(), op.getMapCaptureTypeAttr(),
336364
op.getNameAttr(),
337365
/*partial_map=*/builder.getBoolAttr(false));
@@ -448,6 +476,12 @@ class MapInfoFinalizationPass
448476
addOperands(useDevPtrMutableOpRange, target,
449477
argIface.getUseDevicePtrBlockArgsStart() +
450478
argIface.numUseDevicePtrBlockArgs());
479+
} else if (auto targetOp = llvm::dyn_cast<mlir::omp::TargetOp>(target)) {
480+
mlir::MutableOperandRange hasDevAddrMutableOpRange =
481+
targetOp.getHasDeviceAddrVarsMutable();
482+
addOperands(hasDevAddrMutableOpRange, target,
483+
argIface.getHasDeviceAddrBlockArgsStart() +
484+
argIface.numHasDeviceAddrBlockArgs());
451485
}
452486
}
453487

flang/lib/Support/OpenMP-utils.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ mlir::Block *genEntryBlock(mlir::OpBuilder &builder, const EntryBlockArgs &args,
1818

1919
llvm::SmallVector<mlir::Type> types;
2020
llvm::SmallVector<mlir::Location> locs;
21-
unsigned numVars = args.hostEvalVars.size() + args.inReduction.vars.size() +
22-
args.map.vars.size() + args.priv.vars.size() +
23-
args.reduction.vars.size() + args.taskReduction.vars.size() +
24-
args.useDeviceAddr.vars.size() + args.useDevicePtr.vars.size();
21+
unsigned numVars = args.hasDeviceAddr.vars.size() + args.hostEvalVars.size() +
22+
args.inReduction.vars.size() + args.map.vars.size() +
23+
args.priv.vars.size() + args.reduction.vars.size() +
24+
args.taskReduction.vars.size() + args.useDeviceAddr.vars.size() +
25+
args.useDevicePtr.vars.size();
2526
types.reserve(numVars);
2627
locs.reserve(numVars);
2728

@@ -34,6 +35,7 @@ mlir::Block *genEntryBlock(mlir::OpBuilder &builder, const EntryBlockArgs &args,
3435

3536
// Populate block arguments in clause name alphabetical order to match
3637
// expected order by the BlockArgOpenMPOpInterface.
38+
extractTypeLoc(args.hasDeviceAddr.vars);
3739
extractTypeLoc(args.hostEvalVars);
3840
extractTypeLoc(args.inReduction.vars);
3941
extractTypeLoc(args.map.vars);

flang/test/Lower/OpenMP/array-bounds.f90

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes HOST
2-
!XFAIL: *
32

43
!HOST-LABEL: func.func @_QPread_write_section() {
54
!HOST: %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFread_write_sectionEi"}
@@ -52,7 +51,7 @@ module assumed_array_routines
5251
!HOST: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true}
5352
!HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %0 base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>
5453
!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, i32) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""}
55-
!HOST: %[[MAP:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
54+
!HOST: %[[MAP:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(always, descriptor, to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
5655
!HOST: omp.target map_entries(%[[MAP]] -> %{{.*}}, {{.*}} -> {{.*}}, %[[MAP_INFO_MEMBER]] -> %{{.*}} : !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) {
5756
subroutine assumed_shape_array(arr_read_write)
5857
integer, intent(inout) :: arr_read_write(:)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %s -mmlir -mlir-print-op-generic -o - | FileCheck %s
2+
!RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=51 %s -mlir-print-op-generic -o - | FileCheck %s
3+
4+
! Check that we don't generate member information for the descriptor of `a`
5+
! on entry to the target region.
6+
7+
integer function s(a)
8+
integer :: a(:)
9+
integer :: t
10+
!$omp target data map(to:a) use_device_addr(a)
11+
!$omp target map(from:t) has_device_addr(a)
12+
t = size(a, 1)
13+
!$omp end target
14+
!$omp end target data
15+
s = t
16+
end
17+
18+
! Check that the map.info for `a` only takes a single parameter.
19+
20+
!CHECK-DAG: %[[MAP_A:[0-9]+]] = "omp.map.info"(%[[STORAGE_A:[0-9#]+]]) <{map_capture_type = #omp<variable_capture_kind(ByRef)>, map_type = 16901 : ui64, name = "a", operandSegmentSizes = array<i32: 1, 0, 0, 0>, partial_map = false, var_type = !fir.box<!fir.array<?xi32>>}> : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>>
21+
!CHECK-DAG: %[[MAP_T:[0-9]+]] = "omp.map.info"(%[[STORAGE_T:[0-9#]+]]) <{map_capture_type = #omp<variable_capture_kind(ByRef)>, map_type = 2 : ui64, name = "t", operandSegmentSizes = array<i32: 1, 0, 0, 0>, partial_map = false, var_type = i32}> : (!fir.ref<i32>) -> !fir.ref<i32>
22+
23+
!CHECK: "omp.target"(%[[MAP_A]], %[[MAP_T]])

0 commit comments

Comments
 (0)