[OpenACC][CIR] Implement 'exit data' construct + clauses (#146167)

Similar to 'enter data', except the data clauses have a 'getdeviceptr'
operation before, so that they can properly use the 'exit' operation
correctly. While this is a touch awkward, it fits perfectly into the
existing infrastructure.

Same as with 'enter data', we had to add some add-functions for async
and wait.
This commit is contained in:
Erich Keane
2025-06-30 06:19:43 -07:00
committed by GitHub
parent 51dfe28f87
commit a99fee6989
5 changed files with 260 additions and 14 deletions

View File

@@ -2083,6 +2083,26 @@ def OpenACC_ExitDataOp : OpenACC_Op<"exit_data",
/// The i-th data operand passed.
Value getDataOperand(unsigned i);
/// Add an entry to the 'async-only' attribute (clause spelled without
/// arguments). DeviceType array is supplied even though it should always be
/// empty, so this can mirror other versions of this function.
void addAsyncOnly(MLIRContext *, llvm::ArrayRef<DeviceType>);
/// Add a value to the 'async'. DeviceType array is supplied even though it
/// should always be empty, so this can mirror other versions of this
/// function.
void addAsyncOperand(MLIRContext *, mlir::Value,
llvm::ArrayRef<DeviceType>);
/// Add an entry to the 'wait-only' attribute (clause spelled without
/// arguments). DeviceType array is supplied even though it should always be
/// empty, so this can mirror other versions of this function.
void addWaitOnly(MLIRContext *, llvm::ArrayRef<DeviceType>);
/// Add an array-like entry to the 'wait'. DeviceType array is supplied
/// even though it should always be empty, so this can mirror other versions
/// of this function.
void addWaitOperands(MLIRContext *, bool hasDevnum, mlir::ValueRange,
llvm::ArrayRef<DeviceType>);
}];
let assemblyFormat = [{

View File

@@ -3169,6 +3169,53 @@ void ExitDataOp::getCanonicalizationPatterns(RewritePatternSet &results,
results.add<RemoveConstantIfCondition<ExitDataOp>>(context);
}
void ExitDataOp::addAsyncOnly(MLIRContext *context,
llvm::ArrayRef<DeviceType> effectiveDeviceTypes) {
assert(effectiveDeviceTypes.empty());
assert(!getAsyncAttr());
assert(!getAsyncOperand());
setAsyncAttr(mlir::UnitAttr::get(context));
}
void ExitDataOp::addAsyncOperand(
MLIRContext *context, mlir::Value newValue,
llvm::ArrayRef<DeviceType> effectiveDeviceTypes) {
assert(effectiveDeviceTypes.empty());
assert(!getAsyncAttr());
assert(!getAsyncOperand());
getAsyncOperandMutable().append(newValue);
}
void ExitDataOp::addWaitOnly(MLIRContext *context,
llvm::ArrayRef<DeviceType> effectiveDeviceTypes) {
assert(effectiveDeviceTypes.empty());
assert(!getWaitAttr());
assert(getWaitOperands().empty());
assert(!getWaitDevnum());
setWaitAttr(mlir::UnitAttr::get(context));
}
void ExitDataOp::addWaitOperands(
MLIRContext *context, bool hasDevnum, mlir::ValueRange newValues,
llvm::ArrayRef<DeviceType> effectiveDeviceTypes) {
assert(effectiveDeviceTypes.empty());
assert(!getWaitAttr());
assert(getWaitOperands().empty());
assert(!getWaitDevnum());
// if hasDevnum, the first value is the devnum. The 'rest' go into the
// operands list.
if (hasDevnum) {
getWaitDevnumMutable().append(newValues.front());
newValues = newValues.drop_front();
}
getWaitOperandsMutable().append(newValues);
}
//===----------------------------------------------------------------------===//
// EnterDataOp
//===----------------------------------------------------------------------===//