[Mlir-commits] [mlir] 2263210 - [mlir][acc] Add destroy region to reduction recipes (#155480)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Tue Aug 26 13:17:49 PDT 2025
Author: Razvan Lupusoru
Date: 2025-08-26T13:17:46-07:00
New Revision: 2263210d9e2b56bf910bde57a2bfc013450e131a
URL: https://github.com/llvm/llvm-project/commit/2263210d9e2b56bf910bde57a2bfc013450e131a
DIFF: https://github.com/llvm/llvm-project/commit/2263210d9e2b56bf910bde57a2bfc013450e131a.diff
LOG: [mlir][acc] Add destroy region to reduction recipes (#155480)
Reduction recipes capture how a private copy is created. In some
languages, like C++ class variables with destructors - that private copy
also must be properly destroyed. Thus update the reduction recipe to
contain a `destroy` region similarly to the private recipes.
Added:
Modified:
mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
mlir/test/Dialect/OpenACC/ops.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index 0db11aa9af683..cfe73d81953db 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -1302,7 +1302,7 @@ def OpenACC_ReductionRecipeOp
let description = [{
Declares an OpenACC reduction recipe. The operation requires two
- mandatory regions.
+ mandatory regions and one optional region.
1. The initializer region specifies how to initialize the local reduction
value. The region has a first argument that contains the value of the
@@ -1313,6 +1313,8 @@ def OpenACC_ReductionRecipeOp
values of the reduction type into one. It has at least two arguments
and it is expected to `acc.yield` the combined value. Extra arguments
can be added to deal with dynamic arrays.
+ 3. The optional destroy region specifies how to destruct the value when it
+ reaches its end of life. It takes the reduction value as argument.
Example:
@@ -1329,6 +1331,10 @@ def OpenACC_ReductionRecipeOp
// two values into one.
%2 = arith.addi %0, %1 : i64
acc.yield %2 : i64
+ } destroy {
+ ^bb0(%0: i64)
+ // destroy region contains a sequence of operations to destruct the
+ // created copy.
}
// The reduction symbol is then used in the corresponding operation.
@@ -1362,12 +1368,14 @@ def OpenACC_ReductionRecipeOp
OpenACC_ReductionOperatorAttr:$reductionOperator);
let regions = (region AnyRegion:$initRegion,
- AnyRegion:$combinerRegion);
+ AnyRegion:$combinerRegion,
+ AnyRegion:$destroyRegion);
let assemblyFormat = [{
$sym_name `:` $type attr-dict-with-keyword
`reduction_operator` $reductionOperator
`init` $initRegion `combiner` $combinerRegion
+ (`destroy` $destroyRegion^)?
}];
let hasRegionVerifier = 1;
diff --git a/mlir/test/Dialect/OpenACC/ops.mlir b/mlir/test/Dialect/OpenACC/ops.mlir
index 7bb6cf43e49a7..5a3bbaf4252db 100644
--- a/mlir/test/Dialect/OpenACC/ops.mlir
+++ b/mlir/test/Dialect/OpenACC/ops.mlir
@@ -1954,6 +1954,70 @@ acc.reduction.recipe @reduction_add_memref_i32 : memref<i32> reduction_operator
// CHECK-LABEL: acc.reduction.recipe @reduction_add_memref_i32
// CHECK: memref.alloca
+// -----
+
+// Test reduction recipe with destroy region using dynamic memory allocation
+acc.reduction.recipe @reduction_add_with_destroy : memref<?xf32> reduction_operator<add> init {
+^bb0(%arg0: memref<?xf32>):
+ %cst = arith.constant 0.000000e+00 : f32
+ %c0 = arith.constant 0 : index
+ %size = memref.dim %arg0, %c0 : memref<?xf32>
+ %alloc = memref.alloc(%size) : memref<?xf32>
+ %c1 = arith.constant 1 : index
+ scf.for %i = %c0 to %size step %c1 {
+ memref.store %cst, %alloc[%i] : memref<?xf32>
+ }
+ acc.yield %alloc : memref<?xf32>
+} combiner {
+^bb0(%arg0: memref<?xf32>, %arg1: memref<?xf32>):
+ %c0 = arith.constant 0 : index
+ %c1 = arith.constant 1 : index
+ %size = memref.dim %arg0, %c0 : memref<?xf32>
+ scf.for %i = %c0 to %size step %c1 {
+ %val0 = memref.load %arg0[%i] : memref<?xf32>
+ %val1 = memref.load %arg1[%i] : memref<?xf32>
+ %sum = arith.addf %val0, %val1 : f32
+ memref.store %sum, %arg0[%i] : memref<?xf32>
+ }
+ acc.yield %arg0 : memref<?xf32>
+} destroy {
+^bb0(%arg0: memref<?xf32>):
+ // destroy region to deallocate dynamically allocated memory
+ memref.dealloc %arg0 : memref<?xf32>
+ acc.yield
+}
+
+// CHECK-LABEL: acc.reduction.recipe @reduction_add_with_destroy : memref<?xf32> reduction_operator <add> init {
+// CHECK: ^bb0(%[[ARG:.*]]: memref<?xf32>):
+// CHECK: %[[CST:.*]] = arith.constant 0.000000e+00 : f32
+// CHECK: %[[C0:.*]] = arith.constant 0 : index
+// CHECK: %[[SIZE:.*]] = memref.dim %[[ARG]], %[[C0]] : memref<?xf32>
+// CHECK: %[[ALLOC:.*]] = memref.alloc(%[[SIZE]]) : memref<?xf32>
+// CHECK: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[SIZE]] step %[[C1]] {
+// CHECK: memref.store %[[CST]], %[[ALLOC]][%[[I]]] : memref<?xf32>
+// CHECK: }
+// CHECK: acc.yield %[[ALLOC]] : memref<?xf32>
+// CHECK: } combiner {
+// CHECK: ^bb0(%[[ARG0:.*]]: memref<?xf32>, %[[ARG1:.*]]: memref<?xf32>):
+// CHECK: %[[C0_1:.*]] = arith.constant 0 : index
+// CHECK: %[[C1_1:.*]] = arith.constant 1 : index
+// CHECK: %[[SIZE_1:.*]] = memref.dim %[[ARG0]], %[[C0_1]] : memref<?xf32>
+// CHECK: scf.for %[[I_1:.*]] = %[[C0_1]] to %[[SIZE_1]] step %[[C1_1]] {
+// CHECK: %{{.*}} = memref.load %[[ARG0]][%[[I_1]]] : memref<?xf32>
+// CHECK: %{{.*}} = memref.load %[[ARG1]][%[[I_1]]] : memref<?xf32>
+// CHECK: %[[SUM:.*]] = arith.addf %{{.*}}, %{{.*}} : f32
+// CHECK: memref.store %[[SUM]], %[[ARG0]][%[[I_1]]] : memref<?xf32>
+// CHECK: }
+// CHECK: acc.yield %[[ARG0]] : memref<?xf32>
+// CHECK: } destroy {
+// CHECK: ^bb0(%[[ARG_DESTROY:.*]]: memref<?xf32>):
+// CHECK: memref.dealloc %[[ARG_DESTROY]] : memref<?xf32>
+// CHECK: acc.yield
+// CHECK: }
+
+// -----
+
acc.private.recipe @privatization_memref_i32 : memref<i32> init {
^bb0(%arg0: memref<i32>):
%alloca = memref.alloca() : memref<i32>
More information about the Mlir-commits
mailing list