Skip to content

Commit be90dc5

Browse files
committed
[OpenMP]Update use_device_clause lowering
This patch updates the use_device_ptr and use_device_addr clauses to use the mapInfoOps for lowering. This allows all the types that are handle by the map clauses such as derived types to also be supported by the use_device_clauses. This is patch 1/2 in a series of patches. Co-authored-by: Raghu Maddhipatla [email protected]
1 parent f0f5afe commit be90dc5

File tree

6 files changed

+276
-108
lines changed

6 files changed

+276
-108
lines changed

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 116 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,27 +1076,133 @@ bool ClauseProcessor::processEnter(
10761076
}
10771077

10781078
bool ClauseProcessor::processUseDeviceAddr(
1079+
Fortran::lower::StatementContext &stmtCtx,
10791080
mlir::omp::UseDeviceAddrClauseOps &result,
10801081
llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes,
10811082
llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs,
1082-
llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) const {
1083-
return findRepeatableClause<omp::clause::UseDeviceAddr>(
1084-
[&](const omp::clause::UseDeviceAddr &clause, const parser::CharBlock &) {
1085-
addUseDeviceClause(converter, clause.v, result.useDeviceAddrVars,
1086-
useDeviceTypes, useDeviceLocs, useDeviceSyms);
1083+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &useDeviceSyms)
1084+
const {
1085+
std::map<const Fortran::semantics::Symbol *,
1086+
llvm::SmallVector<OmpMapMemberIndicesData>>
1087+
parentMemberIndices;
1088+
bool clauseFound = findRepeatableClause<omp::clause::UseDeviceAddr>(
1089+
[&](const omp::clause::UseDeviceAddr &clause,
1090+
const Fortran::parser::CharBlock &) {
1091+
const Fortran::parser::CharBlock source;
1092+
mlir::Location location = converter.genLocation(source);
1093+
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
1094+
llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
1095+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
1096+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
1097+
for (const omp::Object &object : clause.v) {
1098+
llvm::SmallVector<mlir::Value> bounds;
1099+
std::stringstream asFortran;
1100+
1101+
Fortran::lower::AddrAndBoundsInfo info =
1102+
Fortran::lower::gatherDataOperandAddrAndBounds<
1103+
mlir::omp::MapBoundsOp, mlir::omp::MapBoundsType>(
1104+
converter, firOpBuilder, semaCtx, stmtCtx, *object.sym(),
1105+
object.ref(), location, asFortran, bounds,
1106+
treatIndexAsSection);
1107+
1108+
auto origSymbol = converter.getSymbolAddress(*object.sym());
1109+
mlir::Value symAddr = info.addr;
1110+
if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
1111+
symAddr = origSymbol;
1112+
1113+
// Explicit map captures are captured ByRef by default,
1114+
// optimisation passes may alter this to ByCopy or other capture
1115+
// types to optimise
1116+
mlir::omp::MapInfoOp mapOp = createMapInfoOp(
1117+
firOpBuilder, location, symAddr,
1118+
/*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds,
1119+
/*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{},
1120+
static_cast<
1121+
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
1122+
mapTypeBits),
1123+
mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());
1124+
1125+
if (object.sym()->owner().IsDerivedType()) {
1126+
addChildIndexAndMapToParent(object, parentMemberIndices, mapOp,
1127+
semaCtx);
1128+
} else {
1129+
useDeviceSyms.push_back(object.sym());
1130+
useDeviceTypes.push_back(symAddr.getType());
1131+
useDeviceLocs.push_back(symAddr.getLoc());
1132+
result.useDeviceAddrVars.push_back(mapOp);
1133+
}
1134+
}
10871135
});
1136+
1137+
insertChildMapInfoIntoParent(converter, parentMemberIndices,
1138+
result.useDeviceAddrVars, useDeviceSyms,
1139+
&useDeviceTypes, &useDeviceLocs);
1140+
return clauseFound;
10881141
}
10891142

10901143
bool ClauseProcessor::processUseDevicePtr(
1144+
Fortran::lower::StatementContext &stmtCtx,
10911145
mlir::omp::UseDevicePtrClauseOps &result,
10921146
llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes,
10931147
llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs,
1094-
llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) const {
1095-
return findRepeatableClause<omp::clause::UseDevicePtr>(
1096-
[&](const omp::clause::UseDevicePtr &clause, const parser::CharBlock &) {
1097-
addUseDeviceClause(converter, clause.v, result.useDevicePtrVars,
1098-
useDeviceTypes, useDeviceLocs, useDeviceSyms);
1148+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &useDeviceSyms)
1149+
const {
1150+
std::map<const Fortran::semantics::Symbol *,
1151+
llvm::SmallVector<OmpMapMemberIndicesData>>
1152+
parentMemberIndices;
1153+
bool clauseFound = findRepeatableClause<omp::clause::UseDevicePtr>(
1154+
[&](const omp::clause::UseDevicePtr &clause,
1155+
const Fortran::parser::CharBlock &) {
1156+
const Fortran::parser::CharBlock source;
1157+
mlir::Location location = converter.genLocation(source);
1158+
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
1159+
llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
1160+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
1161+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
1162+
for (const omp::Object &object : clause.v) {
1163+
llvm::SmallVector<mlir::Value> bounds;
1164+
std::stringstream asFortran;
1165+
1166+
Fortran::lower::AddrAndBoundsInfo info =
1167+
Fortran::lower::gatherDataOperandAddrAndBounds<
1168+
mlir::omp::MapBoundsOp, mlir::omp::MapBoundsType>(
1169+
converter, firOpBuilder, semaCtx, stmtCtx, *object.sym(),
1170+
object.ref(), location, asFortran, bounds,
1171+
treatIndexAsSection);
1172+
1173+
auto origSymbol = converter.getSymbolAddress(*object.sym());
1174+
mlir::Value symAddr = info.addr;
1175+
if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
1176+
symAddr = origSymbol;
1177+
1178+
// Explicit map captures are captured ByRef by default,
1179+
// optimisation passes may alter this to ByCopy or other capture
1180+
// types to optimise
1181+
mlir::omp::MapInfoOp mapOp = createMapInfoOp(
1182+
firOpBuilder, location, symAddr,
1183+
/*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds,
1184+
/*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{},
1185+
static_cast<
1186+
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
1187+
mapTypeBits),
1188+
mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());
1189+
1190+
if (object.sym()->owner().IsDerivedType()) {
1191+
addChildIndexAndMapToParent(object, parentMemberIndices, mapOp,
1192+
semaCtx);
1193+
} else {
1194+
useDeviceSyms.push_back(object.sym());
1195+
useDeviceTypes.push_back(symAddr.getType());
1196+
useDeviceLocs.push_back(symAddr.getLoc());
1197+
result.useDevicePtrVars.push_back(mapOp);
1198+
}
1199+
}
10991200
});
1201+
1202+
insertChildMapInfoIntoParent(converter, parentMemberIndices,
1203+
result.useDevicePtrVars, useDeviceSyms,
1204+
&useDeviceTypes, &useDeviceLocs);
1205+
return clauseFound;
11001206
}
11011207

11021208
} // namespace omp

flang/lib/Lower/OpenMP/ClauseProcessor.h

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,20 @@ class ClauseProcessor {
128128
llvm::SmallVectorImpl<const semantics::Symbol *> *reductionSyms =
129129
nullptr) const;
130130
bool processTo(llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const;
131-
bool processUseDeviceAddr(
132-
mlir::omp::UseDeviceAddrClauseOps &result,
133-
llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes,
134-
llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs,
135-
llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) const;
136-
bool processUseDevicePtr(
137-
mlir::omp::UseDevicePtrClauseOps &result,
138-
llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes,
139-
llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs,
140-
llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) const;
131+
bool
132+
processUseDeviceAddr(Fortran::lower::StatementContext &stmtCtx,
133+
mlir::omp::UseDeviceAddrClauseOps &result,
134+
llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes,
135+
llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs,
136+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
137+
&useDeviceSyms) const;
138+
bool
139+
processUseDevicePtr(Fortran::lower::StatementContext &stmtCtx,
140+
mlir::omp::UseDevicePtrClauseOps &result,
141+
llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes,
142+
llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs,
143+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
144+
&useDeviceSyms) const;
141145

142146
template <typename T>
143147
bool processMotionClauses(lower::StatementContext &stmtCtx,

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -703,32 +703,73 @@ static void genBodyOfTargetDataOp(
703703
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
704704
mlir::Region &region = dataOp.getRegion();
705705

706-
firOpBuilder.createBlock(&region, {}, useDeviceTypes, useDeviceLocs);
706+
auto *regionBlock =
707+
firOpBuilder.createBlock(&region, {}, useDeviceTypes, useDeviceLocs);
708+
709+
// Clones the `bounds` placing them inside the target region and returns them.
710+
auto cloneBound = [&](mlir::Value bound) {
711+
if (mlir::isMemoryEffectFree(bound.getDefiningOp())) {
712+
mlir::Operation *clonedOp = bound.getDefiningOp()->clone();
713+
regionBlock->push_back(clonedOp);
714+
return clonedOp->getResult(0);
715+
}
716+
TODO(converter.getCurrentLocation(),
717+
"target map clause operand unsupported bound type");
718+
};
719+
720+
auto cloneBounds = [cloneBound](llvm::ArrayRef<mlir::Value> bounds) {
721+
llvm::SmallVector<mlir::Value> clonedBounds;
722+
for (mlir::Value bound : bounds)
723+
clonedBounds.emplace_back(cloneBound(bound));
724+
return clonedBounds;
725+
};
707726

708727
for (auto [argIndex, argSymbol] : llvm::enumerate(useDeviceSymbols)) {
709728
const mlir::BlockArgument &arg = region.front().getArgument(argIndex);
710729
fir::ExtendedValue extVal = converter.getSymbolExtendedValue(*argSymbol);
711-
if (auto refType = mlir::dyn_cast<fir::ReferenceType>(arg.getType())) {
712-
if (fir::isa_builtin_cptr_type(refType.getElementType())) {
713-
converter.bindSymbol(*argSymbol, arg);
714-
} else {
715-
// Avoid capture of a reference to a structured binding.
716-
const semantics::Symbol *sym = argSymbol;
717-
extVal.match(
718-
[&](const fir::MutableBoxValue &mbv) {
719-
converter.bindSymbol(
720-
*sym,
721-
fir::MutableBoxValue(
722-
arg, fir::factory::getNonDeferredLenParams(extVal), {}));
723-
},
724-
[&](const auto &) {
725-
TODO(converter.getCurrentLocation(),
726-
"use_device clause operand unsupported type");
727-
});
728-
}
730+
auto refType = mlir::dyn_cast<fir::ReferenceType>(arg.getType());
731+
if (refType && fir::isa_builtin_cptr_type(refType.getElementType())) {
732+
converter.bindSymbol(*argSymbol, arg);
729733
} else {
730-
TODO(converter.getCurrentLocation(),
731-
"use_device clause operand unsupported type");
734+
// Avoid capture of a reference to a structured binding.
735+
const Fortran::semantics::Symbol *sym = argSymbol;
736+
// Structure component symbols don't have bindings.
737+
if (sym->owner().IsDerivedType())
738+
continue;
739+
fir::ExtendedValue extVal = converter.getSymbolExtendedValue(*sym);
740+
extVal.match(
741+
[&](const fir::BoxValue &v) {
742+
converter.bindSymbol(*sym,
743+
fir::BoxValue(arg, cloneBounds(v.getLBounds()),
744+
v.getExplicitParameters(),
745+
v.getExplicitExtents()));
746+
},
747+
[&](const fir::MutableBoxValue &v) {
748+
converter.bindSymbol(
749+
*sym, fir::MutableBoxValue(arg, cloneBounds(v.getLBounds()),
750+
v.getMutableProperties()));
751+
},
752+
[&](const fir::ArrayBoxValue &v) {
753+
converter.bindSymbol(
754+
*sym, fir::ArrayBoxValue(arg, cloneBounds(v.getExtents()),
755+
cloneBounds(v.getLBounds()),
756+
v.getSourceBox()));
757+
},
758+
[&](const fir::CharArrayBoxValue &v) {
759+
converter.bindSymbol(
760+
*sym, fir::CharArrayBoxValue(arg, cloneBound(v.getLen()),
761+
cloneBounds(v.getExtents()),
762+
cloneBounds(v.getLBounds())));
763+
},
764+
[&](const fir::CharBoxValue &v) {
765+
converter.bindSymbol(
766+
*sym, fir::CharBoxValue(arg, cloneBound(v.getLen())));
767+
},
768+
[&](const fir::UnboxedValue &v) { converter.bindSymbol(*sym, arg); },
769+
[&](const auto &) {
770+
TODO(converter.getCurrentLocation(),
771+
"target map clause operand unsupported type");
772+
});
732773
}
733774
}
734775

@@ -1193,9 +1234,9 @@ static void genTargetDataClauses(
11931234
cp.processDevice(stmtCtx, clauseOps);
11941235
cp.processIf(llvm::omp::Directive::OMPD_target_data, clauseOps);
11951236
cp.processMap(loc, stmtCtx, clauseOps);
1196-
cp.processUseDeviceAddr(clauseOps, useDeviceTypes, useDeviceLocs,
1237+
cp.processUseDeviceAddr(stmtCtx, clauseOps, useDeviceTypes, useDeviceLocs,
11971238
useDeviceSyms);
1198-
cp.processUseDevicePtr(clauseOps, useDeviceTypes, useDeviceLocs,
1239+
cp.processUseDevicePtr(stmtCtx, clauseOps, useDeviceTypes, useDeviceLocs,
11991240
useDeviceSyms);
12001241

12011242
// This function implements the deprecated functionality of use_device_ptr

flang/lib/Optimizer/Transforms/OMPMapInfoFinalization.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -106,27 +106,42 @@ class OMPMapInfoFinalizationPass
106106
// TODO: map the addendum segment of the descriptor, similarly to the
107107
// above base address/data pointer member.
108108

109-
if (auto mapClauseOwner =
110-
llvm::dyn_cast<mlir::omp::MapClauseOwningOpInterface>(target)) {
109+
auto addOperands = [&](mlir::OperandRange &operandsArr,
110+
mlir::MutableOperandRange &mutableOpRange,
111+
auto directiveOp) {
111112
llvm::SmallVector<mlir::Value> newMapOps;
112-
mlir::OperandRange mapVarsArr = mapClauseOwner.getMapVars();
113-
114-
for (size_t i = 0; i < mapVarsArr.size(); ++i) {
115-
if (mapVarsArr[i] == op) {
113+
for (size_t i = 0; i < operandsArr.size(); ++i) {
114+
if (operandsArr[i] == op) {
116115
// Push new implicit maps generated for the descriptor.
117116
newMapOps.push_back(baseAddr);
118117

119118
// for TargetOp's which have IsolatedFromAbove we must align the
120119
// new additional map operand with an appropriate BlockArgument,
121120
// as the printing and later processing currently requires a 1:1
122121
// mapping of BlockArgs to MapInfoOp's at the same placement in
123-
// each array (BlockArgs and MapVars).
124-
if (auto targetOp = llvm::dyn_cast<mlir::omp::TargetOp>(target))
125-
targetOp.getRegion().insertArgument(i, baseAddr.getType(), loc);
122+
// each array (BlockArgs and MapOperands).
123+
if (directiveOp) {
124+
directiveOp.getRegion().insertArgument(i, baseAddr.getType(), loc);
125+
}
126126
}
127-
newMapOps.push_back(mapVarsArr[i]);
127+
newMapOps.push_back(operandsArr[i]);
128128
}
129-
mapClauseOwner.getMapVarsMutable().assign(newMapOps);
129+
mutableOpRange.assign(newMapOps);
130+
};
131+
if (auto mapClauseOwner =
132+
llvm::dyn_cast<mlir::omp::MapClauseOwningOpInterface>(target)) {
133+
mlir::OperandRange mapOperandsArr = mapClauseOwner.getMapVars();
134+
mlir::MutableOperandRange mapMutableOpRange =
135+
mapClauseOwner.getMapVarsMutable();
136+
mlir::omp::TargetOp targetOp =
137+
llvm::dyn_cast<mlir::omp::TargetOp>(target);
138+
addOperands(mapOperandsArr, mapMutableOpRange, targetOp);
139+
}
140+
if (auto targetDataOp = llvm::dyn_cast<mlir::omp::TargetDataOp>(target)) {
141+
mlir::OperandRange useDevAddrArr = targetDataOp.getUseDeviceAddrVars();
142+
mlir::MutableOperandRange useDevAddrMutableOpRange =
143+
targetDataOp.getUseDeviceAddrVarsMutable();
144+
addOperands(useDevAddrArr, useDevAddrMutableOpRange, targetDataOp);
130145
}
131146

132147
mlir::Value newDescParentMapOp = builder.create<mlir::omp::MapInfoOp>(

flang/test/Lower/OpenMP/target.f90

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -527,21 +527,23 @@ end subroutine omp_target_device_ptr
527527
!===============================================================================
528528

529529
!CHECK-LABEL: func.func @_QPomp_target_device_addr() {
530-
subroutine omp_target_device_addr
530+
subroutine omp_target_device_addr
531531
integer, pointer :: a
532532
!CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "a", uniq_name = "_QFomp_target_device_addrEa"}
533533
!CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
534534
!CHECK: %[[MAP_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
535535
!CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBERS]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"}
536-
!CHECK: omp.target_data map_entries(%[[MAP_MEMBERS]], %[[MAP]] : {{.*}}) use_device_addr(%[[VAL_0_DECL]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>) {
536+
!CHECK: %[[DEV_ADDR_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
537+
!CHECK: %[[DEV_ADDR:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(tofrom) capture(ByRef) members(%[[DEV_ADDR_MEMBERS]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"}
538+
!CHECK: omp.target_data map_entries(%[[MAP_MEMBERS]], %[[MAP]] : {{.*}}) use_device_addr(%[[DEV_ADDR_MEMBERS]], %[[DEV_ADDR]] : {{.*}}) {
537539
!$omp target data map(tofrom: a) use_device_addr(a)
538-
!CHECK: ^bb0(%[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>>):
539-
!CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
540+
!CHECK: ^bb0(%[[ARG_0:.*]]: !fir.llvm_ptr<!fir.ref<i32>>, %[[ARG_1:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>>):
541+
!CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[ARG_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
540542
!CHECK: %[[C10:.*]] = arith.constant 10 : i32
541543
!CHECK: %[[A_BOX:.*]] = fir.load %[[VAL_1_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
542544
!CHECK: %[[A_ADDR:.*]] = fir.box_addr %[[A_BOX]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
543545
!CHECK: hlfir.assign %[[C10]] to %[[A_ADDR]] : i32, !fir.ptr<i32>
544-
a = 10
546+
a = 10
545547
!CHECK: omp.terminator
546548
!$omp end target data
547549
!CHECK: }

0 commit comments

Comments
 (0)