[Mlir-commits] [mlir] [mlir][acc] Flag the data region of a structured declare for the runtime (PR #234822)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Oct 22 20:00:55 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-openacc
Author: Zhen Wang (wangzpgi)
<details>
<summary>Changes</summary>
A structured `acc.declare_enter` / `acc.declare_exit` pair lowers to the same `__tgt_acc_data_begin` / `__tgt_acc_data_end` entry points as `acc.data`, with the region flags set to `None`. The runtime cannot tell the two apart, yet a declare of a device pointer in a local scope has to keep a registration that a plain `deviceptr` mapping does not need.
Add `ACCDataRegionFlags::Declare` and set it on the begin and end calls of a structured declare. Unstructured declares still go through `__tgt_acc_declare`, and the declare-action recipes through `__tgt_acc_mirror_alloc` / `__tgt_acc_mirror_dealloc`, so they are unchanged. A post-dealloc recipe's `data_end` holds no token and keeps `None`.
---
Full diff: https://github.com/llvm/llvm-project/pull/234822.diff
3 Files Affected:
- (modified) mlir/include/mlir/Conversion/OpenACCToLLVM/ACCDataRuntime.h (+3)
- (modified) mlir/lib/Conversion/OpenACCToLLVM/ACCDataDirectivePatterns.cpp (+17-7)
- (modified) mlir/test/Conversion/OpenACCToLLVM/declare.mlir (+31-5)
``````````diff
diff --git a/mlir/include/mlir/Conversion/OpenACCToLLVM/ACCDataRuntime.h b/mlir/include/mlir/Conversion/OpenACCToLLVM/ACCDataRuntime.h
index 8fdb4cb9d3ebc6..c3af08e9d37a5e 100644
--- a/mlir/include/mlir/Conversion/OpenACCToLLVM/ACCDataRuntime.h
+++ b/mlir/include/mlir/Conversion/OpenACCToLLVM/ACCDataRuntime.h
@@ -86,6 +86,9 @@ enum class ACCDataRegionFlags : int64_t {
None = 0,
/// The implicit data region of a compute construct.
Implicit = 1,
+ /// The region of a structured declare directive in a local scope, which
+ /// lasts until that scope ends.
+ Declare = 2,
};
/// What a data runtime call is asked for besides mapping its operands.
diff --git a/mlir/lib/Conversion/OpenACCToLLVM/ACCDataDirectivePatterns.cpp b/mlir/lib/Conversion/OpenACCToLLVM/ACCDataDirectivePatterns.cpp
index a895a97bb8dac4..a59b81d8acb1f9 100644
--- a/mlir/lib/Conversion/OpenACCToLLVM/ACCDataDirectivePatterns.cpp
+++ b/mlir/lib/Conversion/OpenACCToLLVM/ACCDataDirectivePatterns.cpp
@@ -32,15 +32,18 @@ using namespace mlir::acc;
/// Emits the call to the mapping entry point \p fn for \p mappingOperands, the
/// data-clause operands of a data construct, paired with their type converted
-/// values in \p convertedOperands.
+/// values in \p convertedOperands. \p regionFlags describe the data region
+/// the call opens or closes.
static LogicalResult emitDataRuntimeCall(
Location loc, RuntimeFunction fn, ValueRange mappingOperands,
ValueRange convertedOperands, ACCDataCallKind callKind,
ConversionPatternRewriter &rewriter, OpenACCSupport &accSupport,
Region &globalSymbolRegion, SymbolTable &symbolTable,
- const ACCRuntimeCallConfig &config, ArrayRef<Value> trailingArguments) {
+ const ACCRuntimeCallConfig &config, ArrayRef<Value> trailingArguments,
+ ACCDataRegionFlags regionFlags = ACCDataRegionFlags::None) {
ACCDataCallOptions options;
options.callKind = callKind;
+ options.flags = static_cast<int64_t>(regionFlags);
return emitACCDataRuntimeCall(
loc, fn, mappingOperands, convertedOperands, rewriter, accSupport,
globalSymbolRegion, symbolTable, config, trailingArguments, options);
@@ -192,8 +195,9 @@ using UpdateOpLowering =
ACCDataCallKind::DataEnter>;
/// Structured `acc.declare_enter` (token used by a matching exit) maps like
-/// `acc.data` enter. In a declare-action recipe the object the directive
-/// names is allocated by the host, so only the device mirror of it is
+/// `acc.data` enter, with the region flags telling the runtime that a declare
+/// directive opened the region. In a declare-action recipe the object the
+/// directive names is allocated by the host, so only the device mirror of it is
/// allocated here. An unstructured enter registers the objects it names with
/// `__tgt_acc_declare`.
struct DeclareEnterOpLowering : public ConvertOpToLLVMPattern<DeclareEnterOp> {
@@ -224,7 +228,8 @@ struct DeclareEnterOpLowering : public ConvertOpToLLVMPattern<DeclareEnterOp> {
emitted = emitDataRuntimeCall(
loc, RuntimeFunction::ACCRTL_tgt_acc_data_begin, mappingOperands,
convertedOperands, ACCDataCallKind::DataEnter, rewriter, accSupport,
- globalSymbolRegion, symbolTable, config, {asyncQueue});
+ globalSymbolRegion, symbolTable, config, {asyncQueue},
+ ACCDataRegionFlags::Declare);
} else {
Value binaryDescriptor =
config.createDeclareBinaryDescriptor(loc, rewriter);
@@ -256,7 +261,9 @@ struct DeclareEnterOpLowering : public ConvertOpToLLVMPattern<DeclareEnterOp> {
/// A recipe that runs before the host object is deallocated frees the device
/// mirror of it, as the mapping is torn down once the host storage is gone.
-/// Every other `acc.declare_exit` ends the mapping with `__tgt_acc_data_end`.
+/// Every other `acc.declare_exit` ends the mapping with `__tgt_acc_data_end`;
+/// a structured exit (one holding the token of its enter) carries the declare
+/// region flag, as its enter did.
struct DeclareExitOpLowering : public ConvertOpToLLVMPattern<DeclareExitOp> {
DeclareExitOpLowering(const LLVMTypeConverter &converter,
OpenACCSupport &accSupport, Region &globalSymbolRegion,
@@ -283,10 +290,13 @@ struct DeclareExitOpLowering : public ConvertOpToLLVMPattern<DeclareExitOp> {
convertedOperands, ACCDataCallKind::DataEnter, rewriter, accSupport,
globalSymbolRegion, symbolTable, config, {});
} else {
+ ACCDataRegionFlags regionFlags = op.getToken()
+ ? ACCDataRegionFlags::Declare
+ : ACCDataRegionFlags::None;
emitted = emitDataRuntimeCall(
loc, RuntimeFunction::ACCRTL_tgt_acc_data_end, mappingOperands,
convertedOperands, ACCDataCallKind::DataExit, rewriter, accSupport,
- globalSymbolRegion, symbolTable, config, {asyncQueue});
+ globalSymbolRegion, symbolTable, config, {asyncQueue}, regionFlags);
}
if (failed(emitted))
return failure();
diff --git a/mlir/test/Conversion/OpenACCToLLVM/declare.mlir b/mlir/test/Conversion/OpenACCToLLVM/declare.mlir
index a25ba4899d86b7..a77e97cbe362b9 100644
--- a/mlir/test/Conversion/OpenACCToLLVM/declare.mlir
+++ b/mlir/test/Conversion/OpenACCToLLVM/declare.mlir
@@ -1,10 +1,13 @@
// RUN: mlir-opt %s -acc-to-llvm -split-input-file | FileCheck %s
// A structured declare (the enter token is consumed by a matching exit) uses
-// the same begin/end runtime entry points as acc.data.
+// the same begin/end runtime entry points as acc.data, with the declare
+// region flag (2) so the runtime can tell the two apart.
// CHECK-LABEL: llvm.func @structured_declare
-// CHECK: llvm.call @__tgt_acc_data_begin
-// CHECK: llvm.call @__tgt_acc_data_end
+// CHECK: %[[BEGIN_FLAGS:.*]] = llvm.mlir.constant(2 : i64) : i64
+// CHECK: llvm.call @__tgt_acc_data_begin(%{{[^,]+}}, %[[BEGIN_FLAGS]],
+// CHECK: %[[END_FLAGS:.*]] = llvm.mlir.constant(2 : i64) : i64
+// CHECK: llvm.call @__tgt_acc_data_end(%{{[^,]+}}, %[[END_FLAGS]],
// CHECK-NOT: acc.declare_enter
// CHECK-NOT: acc.declare_exit
func.func @structured_declare(%arg0: !llvm.ptr) {
@@ -19,6 +22,26 @@ func.func @structured_declare(%arg0: !llvm.ptr) {
// -----
+// A structured declare whose exit names no objects, as a declare of a device
+// pointer does, still opens its region with the declare flag; there is no
+// end call, as nothing is to be released.
+// CHECK-LABEL: llvm.func @structured_declare_no_exit_operands
+// CHECK: %[[BEGIN_FLAGS:.*]] = llvm.mlir.constant(2 : i64) : i64
+// CHECK: llvm.call @__tgt_acc_data_begin(%{{[^,]+}}, %[[BEGIN_FLAGS]],
+// CHECK-NOT: llvm.call @__tgt_acc_data_end
+// CHECK-NOT: acc.declare_exit
+func.func @structured_declare_no_exit_operands(%arg0: !llvm.ptr) {
+ %size = arith.constant 40 : i64
+ %map = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(f32)
+ size(%size : i64) elementSize(4) name("a")
+ descKind(none) mapFlags(devptr) -> !llvm.ptr
+ %token = acc.declare_enter dataOperands(%map : !llvm.ptr)
+ acc.declare_exit token(%token)
+ return
+}
+
+// -----
+
// An unstructured declare registers the objects with __tgt_acc_declare. With
// no target hook installed, its binary descriptor is null.
// CHECK-LABEL: llvm.func @unstructured_declare
@@ -70,9 +93,12 @@ llvm.func @pre_dealloc_recipe(%arg0: !llvm.ptr) attributes {acc.declare_action =
// -----
// A recipe that runs after the host object is deallocated releases the
-// mapping of the descriptor, which is still valid storage at that point.
+// mapping of the descriptor, which is still valid storage at that point. The
+// exit holds no token, so the call carries no declare region flag.
// CHECK-LABEL: llvm.func @post_dealloc_recipe
-// CHECK: llvm.call @__tgt_acc_data_end
+// CHECK: llvm.mlir.addressof @acc.ident
+// CHECK: %[[END_FLAGS:.*]] = llvm.mlir.constant(0 : i64) : i64
+// CHECK: llvm.call @__tgt_acc_data_end(%{{[^,]+}}, %[[END_FLAGS]],
// CHECK-NOT: llvm.call @__tgt_acc_mirror_dealloc
llvm.func @post_dealloc_recipe(%arg0: !llvm.ptr) attributes {acc.declare_action = #acc.declare_action<postDealloc = @post_dealloc_recipe>} {
%size = arith.constant 4 : i64
``````````
</details>
https://github.com/llvm/llvm-project/pull/234822
More information about the Mlir-commits
mailing list