[Mlir-commits] [mlir] [mlir][acc] Fold present() clauses on device values (PR #212815)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Jul 29 09:29:57 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Ivan R. Ivanov (ivanradanov)

<details>
<summary>Changes</summary>

The compiler must emit acc.device_ptr mapping for device values, however, an existing present clause prevents that. A present on a device value always holds, so fold it away to allow implicit data handling to generate device_ptr mapping.

---
Full diff: https://github.com/llvm/llvm-project/pull/212815.diff


2 Files Affected:

- (modified) mlir/lib/Dialect/OpenACC/Transforms/ACCImplicitData.cpp (+46-11) 
- (modified) mlir/test/Dialect/OpenACC/acc-implicit-data.mlir (+46) 


``````````diff
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCImplicitData.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCImplicitData.cpp
index 628454905b488..d031d9a7f35a3 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCImplicitData.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCImplicitData.cpp
@@ -215,6 +215,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/TypeSwitch.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <type_traits>
 
@@ -702,6 +703,35 @@ static void insertInSortedOrder(SmallVector<Value> &sortedDataClauseOperands,
   }
 }
 
+/// A present() clause on a device value always holds. Erase it to allow the
+/// implicit data to generate an acc.deviceptr for it.
+template <typename OpT>
+static void foldPresentDeviceValue(OpT computeConstructOp) {
+  SmallVector<Value> remainingOperands;
+  SmallVector<acc::PresentOp> toErase;
+  for (Value var : computeConstructOp.getDataClauseOperands()) {
+    if (auto presentOp =
+            dyn_cast_if_present<acc::PresentOp>(var.getDefiningOp())) {
+      if (acc::isDeviceValue(presentOp.getVar())) {
+        toErase.push_back(presentOp);
+        continue;
+      }
+    }
+    remainingOperands.push_back(var);
+  }
+  if (toErase.empty())
+    return;
+
+  computeConstructOp.getDataClauseOperandsMutable().assign(remainingOperands);
+  for (acc::PresentOp presentOp : toErase) {
+    Operation *exitOp = findDataExitOp(presentOp);
+    assert(exitOp && exitOp->getNumResults() == 0);
+    presentOp.getAccVar().replaceAllUsesWith(presentOp.getVar());
+    exitOp->erase();
+    presentOp->erase();
+  }
+}
+
 template <typename OpT>
 void ACCImplicitData::generateImplicitDataOps(
     ModuleOp &module, OpT computeConstructOp,
@@ -790,19 +820,24 @@ void ACCImplicitData::runOnOperation() {
 
   acc::OpenACCSupport &accSupport = getAnalysis<acc::OpenACCSupport>();
 
+  SmallVector<Operation *> computeConstructOps;
   module.walk([&](Operation *op) {
-    if (isa<ACC_COMPUTE_CONSTRUCT_OPS, acc::KernelEnvironmentOp>(op)) {
-      assert(op->getNumRegions() == 1 && "must have 1 region");
-
-      auto defaultClause = acc::getDefaultAttr(op);
-      llvm::TypeSwitch<Operation *, void>(op)
-          .Case<ACC_COMPUTE_CONSTRUCT_OPS, acc::KernelEnvironmentOp>(
-              [&](auto op) {
-                generateImplicitDataOps(module, op, defaultClause, accSupport);
-              })
-          .Default([&](Operation *) {});
-    }
+    if (isa<ACC_COMPUTE_CONSTRUCT_OPS, acc::KernelEnvironmentOp>(op))
+      computeConstructOps.push_back(op);
   });
+
+  for (Operation *op : computeConstructOps) {
+    assert(op->getNumRegions() == 1 && "must have 1 region");
+
+    auto defaultClause = acc::getDefaultAttr(op);
+    llvm::TypeSwitch<Operation *, void>(op)
+        .Case<ACC_COMPUTE_CONSTRUCT_OPS, acc::KernelEnvironmentOp>(
+            [&](auto op) {
+              foldPresentDeviceValue(op);
+              generateImplicitDataOps(module, op, defaultClause, accSupport);
+            })
+        .Default([&](Operation *) {});
+  }
 }
 
 } // namespace
diff --git a/mlir/test/Dialect/OpenACC/acc-implicit-data.mlir b/mlir/test/Dialect/OpenACC/acc-implicit-data.mlir
index 3b6b5e1ade5e0..6551b20100005 100644
--- a/mlir/test/Dialect/OpenACC/acc-implicit-data.mlir
+++ b/mlir/test/Dialect/OpenACC/acc-implicit-data.mlir
@@ -287,3 +287,49 @@ func.func @test_declare_deviceptr_arg_in_parallel(%arg0: memref<?xi8>) {
 // CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[DEVPTR]] : memref<10xf32>)
 // CHECK-NOT: acc.copyin
 // CHECK-NOT: acc.copyout
+
+// -----
+
+// Fold an explicit present of device data: drop present/delete and rewrite
+// region uses; subsequent implicit mapping should emit deviceptr.
+func.func @test_fold_present_device_value() {
+  %alloc = memref.alloca() : memref<10xf32, #gpu.address_space<global>>
+  %present = acc.present varPtr(%alloc : memref<10xf32, #gpu.address_space<global>>) -> memref<10xf32, #gpu.address_space<global>> {name = "a"}
+  acc.parallel dataOperands(%present : memref<10xf32, #gpu.address_space<global>>) {
+    %c0 = arith.constant 0 : index
+    %load = memref.load %present[%c0] : memref<10xf32, #gpu.address_space<global>>
+    acc.yield
+  }
+  acc.delete accPtr(%present : memref<10xf32, #gpu.address_space<global>>) {dataClause = #acc<data_clause acc_present>, name = "a"}
+  return
+}
+
+// CHECK-LABEL: func.func @test_fold_present_device_value
+// CHECK: %[[ALLOC:.*]] = memref.alloca() : memref<10xf32, #gpu.address_space<global>>
+// CHECK: %[[DEVPTR:.*]] = acc.deviceptr varPtr(%[[ALLOC]] : memref<10xf32, #gpu.address_space<global>>) -> memref<10xf32, #gpu.address_space<global>> {implicit = true, name = ""}
+// CHECK: acc.parallel dataOperands(%[[DEVPTR]] : memref<10xf32, #gpu.address_space<global>>) {
+// CHECK: memref.load %[[DEVPTR]][{{.*}}] : memref<10xf32, #gpu.address_space<global>>
+// CHECK-NOT: acc.present
+// CHECK-NOT: acc.delete
+
+// -----
+
+// Present of host data must not be folded away.
+func.func @test_present_host_not_folded() {
+  %alloc = memref.alloca() : memref<10xf32>
+  %present = acc.present varPtr(%alloc : memref<10xf32>) -> memref<10xf32> {name = "a"}
+  acc.parallel dataOperands(%present : memref<10xf32>) {
+    %c0 = arith.constant 0 : index
+    %load = memref.load %present[%c0] : memref<10xf32>
+    acc.yield
+  }
+  acc.delete accPtr(%present : memref<10xf32>) {dataClause = #acc<data_clause acc_present>, name = "a"}
+  return
+}
+
+// CHECK-LABEL: func.func @test_present_host_not_folded
+// CHECK: %[[ALLOC:.*]] = memref.alloca() : memref<10xf32>
+// CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[ALLOC]] : memref<10xf32>) -> memref<10xf32> {name = "a"}
+// CHECK: acc.parallel dataOperands(%[[PRESENT]] : memref<10xf32>) {
+// CHECK: memref.load %[[PRESENT]][{{.*}}] : memref<10xf32>
+// CHECK: acc.delete accPtr(%[[PRESENT]] : memref<10xf32>) {dataClause = #acc<data_clause acc_present>, name = "a"}

``````````

</details>


https://github.com/llvm/llvm-project/pull/212815


More information about the Mlir-commits mailing list