[Mlir-commits] [mlir] [acc] add RegionBranchTerminatorOpInterface to acc.terminator (PR #174165)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Jan 1 15:14:14 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-openacc

Author: Susan Tan (ス-ザン タン) (SusanTan)

<details>
<summary>Changes</summary>

This further helps with propagation in data flow analysis through acc regions

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


3 Files Affected:

- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td (+4-1) 
- (modified) mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp (+10) 
- (modified) mlir/test/Dialect/OpenACC/region-branchop-interface.mlir (+4-39) 


``````````diff
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index 14902730ba165..2375104eadb85 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -2364,7 +2364,10 @@ def OpenACC_DataOp
   let hasVerifier = 1;
 }
 
-def OpenACC_TerminatorOp : OpenACC_Op<"terminator", [Pure, Terminator]> {
+def OpenACC_TerminatorOp
+    : OpenACC_Op<"terminator", [Pure, Terminator,
+                                DeclareOpInterfaceMethods<
+                                    RegionBranchTerminatorOpInterface>]> {
   let summary = "Generic terminator for OpenACC regions";
 
   let description = [{
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index 7f9f2a59f83be..bb8e6881d7d9d 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -463,6 +463,16 @@ void LoopOp::getSuccessorRegions(RegionBranchPoint point,
   regions.push_back(RegionSuccessor(getOperation(), getResults()));
 }
 
+//===----------------------------------------------------------------------===//
+// RegionBranchTerminatorOpInterface
+//===----------------------------------------------------------------------===//
+
+MutableOperandRange
+TerminatorOp::getMutableSuccessorOperands(RegionSuccessor /*point*/) {
+  // `acc.terminator` does not forward operands.
+  return MutableOperandRange(getOperation(), /*start=*/0, /*length=*/0);
+}
+
 //===----------------------------------------------------------------------===//
 // device_type support helpers
 //===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/OpenACC/region-branchop-interface.mlir b/mlir/test/Dialect/OpenACC/region-branchop-interface.mlir
index 28789868fdef9..ea3bf6aec58ec 100644
--- a/mlir/test/Dialect/OpenACC/region-branchop-interface.mlir
+++ b/mlir/test/Dialect/OpenACC/region-branchop-interface.mlir
@@ -2,13 +2,6 @@
 
 // Test that RegionBranchOpInterface implementations for OpenACC single-region
 // ops behave reasonably under LastModifiedAnalysis.
-//
-// For acc.parallel / acc.serial, which only have value-based memory effects
-// coming from their bodies, the analysis can track the last writer precisely.
-// For other OpenACC region ops (e.g. acc.kernels, acc.data, acc.host_data),
-// which currently only report resource-only memory effects at the op level,
-// LastModifiedAnalysis cannot attribute a precise last writer and falls back
-// to "<unknown>" after the op for values not directly touched in the region.
 
 
 // CHECK-LABEL: test_tag: acc_parallel_after:
@@ -63,23 +56,14 @@ func.func @last_mod_openacc_serial(%arg0: memref<f32>) -> memref<f32> {
 // CHECK-NEXT:   - pre
 // CHECK-LABEL: test_tag: acc_kernels_after:
 // CHECK:  operand #0
-// CHECK-NEXT:   - <unknown>
+// CHECK-NEXT:   - pre
 func.func @last_mod_openacc_kernels(%arg0: memref<f32>) -> memref<f32> {
   %zero = arith.constant 0.0 : f32
-
-  // Single store before the region.
   memref.store %zero, %arg0[] {tag_name = "pre"} : memref<f32>
   memref.load %arg0[] {tag = "acc_kernels_before"} : memref<f32>
-
-  // The acc.kernels region does not touch %arg0.
   acc.kernels {
-    "test.openacc_dummy_op"() : () -> ()
     acc.terminator
   }
-
-  // After acc.kernels, LastModifiedAnalysis cannot prove that "pre" still
-  // dominates all paths and therefore reports the last modifier conservatively
-  // as "<unknown>" for this load.
   memref.load %arg0[] {tag = "acc_kernels_after"} : memref<f32>
   return %arg0 : memref<f32>
 }
@@ -91,24 +75,14 @@ func.func @last_mod_openacc_kernels(%arg0: memref<f32>) -> memref<f32> {
 // CHECK-NEXT:   - pre
 // CHECK-LABEL: test_tag: acc_data_after:
 // CHECK:  operand #0
-// CHECK-NEXT:   - <unknown>
+// CHECK-NEXT:   - pre
 func.func @last_mod_openacc_data(%arg0: memref<f32>, %mapped: memref<f32>) -> memref<f32> {
   %zero = arith.constant 0.0 : f32
-
-  // Single store to %arg0 before the region.
   memref.store %zero, %arg0[] {tag_name = "pre"} : memref<f32>
   memref.load %arg0[] {tag = "acc_data_before"} : memref<f32>
-
-  // Map an unrelated buffer into device memory and run an acc.data region that
-  // does not touch %arg0.
-  %create = acc.create varPtr(%mapped : memref<f32>) varType(tensor<f32>) -> memref<f32>
-  acc.data dataOperands(%create : memref<f32>) {
-    "test.openacc_dummy_op"() : () -> ()
+  acc.data {
     acc.terminator
-  }
-
-  // After acc.data, LastModifiedAnalysis cannot prove that "pre" still
-  // dominates all paths for %arg0 and reports "<unknown>" for this load.
+  } attributes {defaultAttr = #acc<defaultvalue none>}
   memref.load %arg0[] {tag = "acc_data_after"} : memref<f32>
   return %arg0 : memref<f32>
 }
@@ -123,21 +97,12 @@ func.func @last_mod_openacc_data(%arg0: memref<f32>, %mapped: memref<f32>) -> me
 // CHECK-NEXT:   - <unknown>
 func.func @last_mod_openacc_host_data(%arg0: memref<f32>, %mapped: memref<f32>) -> memref<f32> {
   %zero = arith.constant 0.0 : f32
-
-  // Single store to %arg0 before the region.
   memref.store %zero, %arg0[] {tag_name = "pre"} : memref<f32>
   memref.load %arg0[] {tag = "acc_host_before"} : memref<f32>
-
-  // Map %mapped into device memory and run an acc.host_data region that does
-  // not touch %arg0.
   %devptr = acc.use_device varPtr(%mapped : memref<f32>) varType(tensor<f32>) -> memref<f32>
   acc.host_data dataOperands(%devptr : memref<f32>) {
-    "test.openacc_dummy_op"() : () -> ()
     acc.terminator
   }
-
-  // After acc.host_data, the analysis cannot prove "pre" still dominates and
-  // reports "<unknown>" for the last writer on %arg0.
   memref.load %arg0[] {tag = "acc_host_after"} : memref<f32>
   return %arg0 : memref<f32>
 }

``````````

</details>


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


More information about the Mlir-commits mailing list