Skip to content

Commit a75f428

Browse files
authored
[acc] Change acc declare_action recipe (#157764)
Change the declare_action recipe from using acc.update_device to acc.declare_enter for prealloc/postalloc, and acc.declare_exit for predealloc/postdealloc, since update_device is not meant for accomodating acc declare allocatables.
1 parent 9a6bdfd commit a75f428

File tree

4 files changed

+183
-107
lines changed

4 files changed

+183
-107
lines changed

flang/include/flang/Lower/OpenACC.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ struct Evaluation;
6666
} // namespace pft
6767

6868
static constexpr llvm::StringRef declarePostAllocSuffix =
69-
"_acc_declare_update_desc_post_alloc";
69+
"_acc_declare_post_alloc";
7070
static constexpr llvm::StringRef declarePreDeallocSuffix =
71-
"_acc_declare_update_desc_pre_dealloc";
71+
"_acc_declare_pre_dealloc";
7272
static constexpr llvm::StringRef declarePostDeallocSuffix =
73-
"_acc_declare_update_desc_post_dealloc";
73+
"_acc_declare_post_dealloc";
7474

7575
static constexpr llvm::StringRef privatizationRecipePrefix = "privatization";
7676

flang/lib/Lower/OpenACC.cpp

Lines changed: 140 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -249,17 +249,29 @@ static void createDeclareAllocFuncWithArg(mlir::OpBuilder &modBuilder,
249249
if (unwrapFirBox)
250250
asFortranDesc << accFirDescriptorPostfix.str();
251251

252-
// Updating descriptor must occur before the mapping of the data so that
253-
// attached data pointer is not overwritten.
254-
mlir::acc::UpdateDeviceOp updateDeviceOp =
255-
createDataEntryOp<mlir::acc::UpdateDeviceOp>(
256-
builder, loc, registerFuncOp.getArgument(0), asFortranDesc, bounds,
257-
/*structured=*/false, /*implicit=*/true,
258-
mlir::acc::DataClause::acc_update_device, descTy,
259-
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
260-
llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 1};
261-
llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
262-
createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
252+
// For descriptor, preserve old behavior when unwrapping FIR box: update.
253+
if (unwrapFirBox) {
254+
mlir::acc::UpdateDeviceOp updateDeviceOp =
255+
createDataEntryOp<mlir::acc::UpdateDeviceOp>(
256+
builder, loc, registerFuncOp.getArgument(0), asFortranDesc, bounds,
257+
/*structured=*/false, /*implicit=*/true,
258+
mlir::acc::DataClause::acc_update_device, descTy,
259+
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
260+
llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 1};
261+
llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
262+
createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands,
263+
operandSegments);
264+
} else {
265+
// New behavior: start a structured region with declare_enter.
266+
EntryOp descEntryOp = createDataEntryOp<EntryOp>(
267+
builder, loc, registerFuncOp.getArgument(0), asFortranDesc, bounds,
268+
/*structured=*/false, /*implicit=*/true, clause, descTy,
269+
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
270+
mlir::acc::DeclareEnterOp::create(
271+
builder, loc,
272+
mlir::acc::DeclareTokenType::get(descEntryOp.getContext()),
273+
mlir::ValueRange(descEntryOp.getAccVar()));
274+
}
263275

264276
if (unwrapFirBox) {
265277
mlir::Value desc =
@@ -304,30 +316,58 @@ static void createDeclareDeallocFuncWithArg(
304316
}
305317

306318
llvm::SmallVector<mlir::Value> bounds;
307-
mlir::acc::GetDevicePtrOp entryOp =
308-
createDataEntryOp<mlir::acc::GetDevicePtrOp>(
309-
builder, loc, var, asFortran, bounds,
310-
/*structured=*/false, /*implicit=*/false, clause, var.getType(),
311-
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
312-
mlir::acc::DeclareExitOp::create(builder, loc, mlir::Value{},
313-
mlir::ValueRange(entryOp.getAccVar()));
314-
315-
if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
316-
std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>)
317-
ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
318-
entryOp.getVar(), entryOp.getVarType(), entryOp.getBounds(),
319-
entryOp.getAsyncOperands(),
320-
entryOp.getAsyncOperandsDeviceTypeAttr(),
321-
entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
322-
/*structured=*/false, /*implicit=*/false,
323-
builder.getStringAttr(*entryOp.getName()));
324-
else
325-
ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
326-
entryOp.getBounds(), entryOp.getAsyncOperands(),
327-
entryOp.getAsyncOperandsDeviceTypeAttr(),
328-
entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
329-
/*structured=*/false, /*implicit=*/false,
330-
builder.getStringAttr(*entryOp.getName()));
319+
if (unwrapFirBox) {
320+
// Unwrap: delete device payload using getdeviceptr + declare_exit + ExitOp
321+
mlir::acc::GetDevicePtrOp entryOp =
322+
createDataEntryOp<mlir::acc::GetDevicePtrOp>(
323+
builder, loc, var, asFortran, bounds,
324+
/*structured=*/false, /*implicit=*/false, clause, var.getType(),
325+
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
326+
mlir::acc::DeclareExitOp::create(builder, loc, mlir::Value{},
327+
mlir::ValueRange(entryOp.getAccVar()));
328+
329+
if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
330+
std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>)
331+
ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
332+
entryOp.getVar(), entryOp.getVarType(),
333+
entryOp.getBounds(), entryOp.getAsyncOperands(),
334+
entryOp.getAsyncOperandsDeviceTypeAttr(),
335+
entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
336+
/*structured=*/false, /*implicit=*/false,
337+
builder.getStringAttr(*entryOp.getName()));
338+
else
339+
ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
340+
entryOp.getBounds(), entryOp.getAsyncOperands(),
341+
entryOp.getAsyncOperandsDeviceTypeAttr(),
342+
entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
343+
/*structured=*/false, /*implicit=*/false,
344+
builder.getStringAttr(*entryOp.getName()));
345+
} else {
346+
mlir::acc::GetDevicePtrOp entryOp =
347+
createDataEntryOp<mlir::acc::GetDevicePtrOp>(
348+
builder, loc, var, asFortran, bounds,
349+
/*structured=*/false, /*implicit=*/false, clause, var.getType(),
350+
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
351+
mlir::acc::DeclareExitOp::create(builder, loc, mlir::Value{},
352+
mlir::ValueRange(entryOp.getAccVar()));
353+
354+
if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
355+
std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>)
356+
ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
357+
entryOp.getVar(), entryOp.getVarType(),
358+
entryOp.getBounds(), entryOp.getAsyncOperands(),
359+
entryOp.getAsyncOperandsDeviceTypeAttr(),
360+
entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
361+
/*structured=*/false, /*implicit=*/false,
362+
builder.getStringAttr(*entryOp.getName()));
363+
else
364+
ExitOp::create(builder, entryOp.getLoc(), entryOp.getAccVar(),
365+
entryOp.getBounds(), entryOp.getAsyncOperands(),
366+
entryOp.getAsyncOperandsDeviceTypeAttr(),
367+
entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
368+
/*structured=*/false, /*implicit=*/false,
369+
builder.getStringAttr(*entryOp.getName()));
370+
}
331371

332372
// Generate the post dealloc function.
333373
modBuilder.setInsertionPointAfter(preDeallocOp);
@@ -343,15 +383,28 @@ static void createDeclareDeallocFuncWithArg(
343383
asFortran << accFirDescriptorPostfix.str();
344384
}
345385

346-
mlir::acc::UpdateDeviceOp updateDeviceOp =
347-
createDataEntryOp<mlir::acc::UpdateDeviceOp>(
348-
builder, loc, var, asFortran, bounds,
349-
/*structured=*/false, /*implicit=*/true,
350-
mlir::acc::DataClause::acc_update_device, var.getType(),
351-
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
352-
llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 1};
353-
llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
354-
createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
386+
if (unwrapFirBox) {
387+
// Old behavior: update descriptor after deallocation.
388+
mlir::acc::UpdateDeviceOp updateDeviceOp =
389+
createDataEntryOp<mlir::acc::UpdateDeviceOp>(
390+
builder, loc, var, asFortran, bounds,
391+
/*structured=*/false, /*implicit=*/true,
392+
mlir::acc::DataClause::acc_update_device, var.getType(),
393+
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
394+
llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 1};
395+
llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
396+
createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands,
397+
operandSegments);
398+
} else {
399+
// New behavior: end structured region with declare_exit.
400+
mlir::acc::GetDevicePtrOp postEntryOp =
401+
createDataEntryOp<mlir::acc::GetDevicePtrOp>(
402+
builder, loc, var, asFortran, bounds,
403+
/*structured=*/false, /*implicit=*/true, clause, var.getType(),
404+
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
405+
mlir::acc::DeclareExitOp::create(builder, loc, mlir::Value{},
406+
mlir::ValueRange(postEntryOp.getAccVar()));
407+
}
355408
modBuilder.setInsertionPointAfter(postDeallocOp);
356409
builder.restoreInsertionPoint(crtInsPt);
357410
}
@@ -3994,17 +4047,28 @@ static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder,
39944047
asFortranDesc << accFirDescriptorPostfix.str();
39954048
llvm::SmallVector<mlir::Value> bounds;
39964049

3997-
// Updating descriptor must occur before the mapping of the data so that
3998-
// attached data pointer is not overwritten.
3999-
mlir::acc::UpdateDeviceOp updateDeviceOp =
4000-
createDataEntryOp<mlir::acc::UpdateDeviceOp>(
4001-
builder, loc, addrOp, asFortranDesc, bounds,
4002-
/*structured=*/false, /*implicit=*/true,
4003-
mlir::acc::DataClause::acc_update_device, addrOp.getType(),
4004-
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
4005-
llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 1};
4006-
llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
4007-
createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
4050+
// For unwrapFirBox=false this remains declare_enter; for unwrapFirBox=true,
4051+
// the descriptor post-alloc remains update behavior.
4052+
if (unwrapFirBox) {
4053+
mlir::acc::UpdateDeviceOp updDesc =
4054+
createDataEntryOp<mlir::acc::UpdateDeviceOp>(
4055+
builder, loc, addrOp, asFortranDesc, bounds,
4056+
/*structured=*/false, /*implicit=*/true,
4057+
mlir::acc::DataClause::acc_update_device, addrOp.getType(),
4058+
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
4059+
llvm::SmallVector<int32_t> seg{0, 0, 0, 1};
4060+
llvm::SmallVector<mlir::Value> ops{updDesc.getResult()};
4061+
createSimpleOp<mlir::acc::UpdateOp>(builder, loc, ops, seg);
4062+
} else {
4063+
EntryOp descEntryOp = createDataEntryOp<EntryOp>(
4064+
builder, loc, addrOp, asFortranDesc, bounds,
4065+
/*structured=*/false, /*implicit=*/true, clause, addrOp.getType(),
4066+
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
4067+
mlir::acc::DeclareEnterOp::create(
4068+
builder, loc,
4069+
mlir::acc::DeclareTokenType::get(descEntryOp.getContext()),
4070+
mlir::ValueRange(descEntryOp.getAccVar()));
4071+
}
40084072

40094073
if (unwrapFirBox) {
40104074
auto loadOp = fir::LoadOp::create(builder, loc, addrOp.getResult());
@@ -4097,15 +4161,27 @@ static void createDeclareDeallocFunc(mlir::OpBuilder &modBuilder,
40974161
if (unwrapFirBox)
40984162
asFortran << accFirDescriptorPostfix.str();
40994163
llvm::SmallVector<mlir::Value> bounds;
4100-
mlir::acc::UpdateDeviceOp updateDeviceOp =
4101-
createDataEntryOp<mlir::acc::UpdateDeviceOp>(
4102-
builder, loc, addrOp, asFortran, bounds,
4103-
/*structured=*/false, /*implicit=*/true,
4104-
mlir::acc::DataClause::acc_update_device, addrOp.getType(),
4105-
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
4106-
llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 1};
4107-
llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
4108-
createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
4164+
if (unwrapFirBox) {
4165+
// Unwrap mode: update the descriptor after deallocation (no declare_exit).
4166+
mlir::acc::UpdateDeviceOp updDesc =
4167+
createDataEntryOp<mlir::acc::UpdateDeviceOp>(
4168+
builder, loc, addrOp, asFortran, bounds,
4169+
/*structured=*/false, /*implicit=*/true,
4170+
mlir::acc::DataClause::acc_update_device, addrOp.getType(),
4171+
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
4172+
llvm::SmallVector<int32_t> seg{0, 0, 0, 1};
4173+
llvm::SmallVector<mlir::Value> ops{updDesc.getResult()};
4174+
createSimpleOp<mlir::acc::UpdateOp>(builder, loc, ops, seg);
4175+
} else {
4176+
// Default: end the structured declare region using declare_exit.
4177+
mlir::acc::GetDevicePtrOp descEntryOp =
4178+
createDataEntryOp<mlir::acc::GetDevicePtrOp>(
4179+
builder, loc, addrOp, asFortran, bounds,
4180+
/*structured=*/false, /*implicit=*/true, clause, addrOp.getType(),
4181+
/*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
4182+
mlir::acc::DeclareExitOp::create(builder, loc, mlir::Value{},
4183+
mlir::ValueRange(descEntryOp.getAccVar()));
4184+
}
41094185
modBuilder.setInsertionPointAfter(postDeallocOp);
41104186
}
41114187

0 commit comments

Comments
 (0)