[Mlir-commits] [flang] [mlir] [flang][acc] Register fir::ConvertOp with OutlineRematerializationOpInterface (PR #184218)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Mar 2 12:52:49 PST 2026


https://github.com/khaki3 updated https://github.com/llvm/llvm-project/pull/184218

>From 16395d600c3b5c89f2d0ca9839422e3d8930b005 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 2 Mar 2026 12:16:48 -0800
Subject: [PATCH 1/3] [acc] Rematerialize view-like ops with
 OutlineRematerializationOpInterface

Check OutlineRematerializationOpInterface on the direct defining op
before tracing through ViewLikeOpInterface in
OffloadLiveInValueCanonicalization. An op may implement both interfaces
(e.g. fir.convert), and tracing first would reach a block argument,
missing the rematerialization.

Also register fir::ConvertOp with OutlineRematerializationOpInterface
so that CSE merging fir.convert across ACC region boundaries does not
prevent ACCImplicitData from mapping the original pointer.

Made-with: Cursor
---
 .../Support/RegisterOpenACCExtensions.cpp     |  2 +
 .../offload-livein-value-canonicalization.fir | 42 +++++++++++++++++++
 .../OffloadLiveInValueCanonicalization.cpp    | 11 +++++
 3 files changed, 55 insertions(+)

diff --git a/flang/lib/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.cpp b/flang/lib/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.cpp
index c0be247a47729..ed0b5707a0b90 100644
--- a/flang/lib/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.cpp
@@ -77,6 +77,8 @@ void registerOpenACCExtensions(mlir::DialectRegistry &registry) {
         *ctx);
     fir::FieldIndexOp::attachInterface<
         OutlineRematerializationModel<fir::FieldIndexOp>>(*ctx);
+    fir::ConvertOp::attachInterface<
+        OutlineRematerializationModel<fir::ConvertOp>>(*ctx);
   });
 
   // Register HLFIR operation interfaces
diff --git a/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir b/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir
index 6ecccde39d3fb..d9313a1f933bd 100644
--- a/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir
+++ b/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir
@@ -253,3 +253,45 @@ func.func @test_accbounds_rematerialize_fir() {
 // CHECK: acc.bounds
 // CHECK: acc.serial {
 // CHECK:   acc.bounds
+
+// -----
+
+// Test fir.convert rematerialization (ViewLikeOpInterface +
+// OutlineRematerializationOpInterface).
+func.func private @use_i64(i64) -> ()
+
+func.func @test_convert_rematerialize(%arg0: !fir.ref<i32>) {
+  %0 = fir.convert %arg0 : (!fir.ref<i32>) -> i64
+  fir.call @use_i64(%0) : (i64) -> ()
+  acc.parallel {
+    fir.call @use_i64(%0) : (i64) -> ()
+    acc.yield
+  }
+  return
+}
+
+// CHECK-LABEL: @test_convert_rematerialize
+// CHECK: %[[CVT_OUTER:.*]] = fir.convert
+// CHECK: fir.call @use_i64(%[[CVT_OUTER]])
+// CHECK: acc.parallel {
+// CHECK:   %[[CVT_INNER:.*]] = fir.convert
+// CHECK:   fir.call @use_i64(%[[CVT_INNER]])
+
+// -----
+
+// Test fir.convert sinking (only used inside region).
+func.func private @use_i64(i64) -> ()
+
+func.func @test_convert_sink(%arg0: !fir.ref<i32>) {
+  %0 = fir.convert %arg0 : (!fir.ref<i32>) -> i64
+  acc.parallel {
+    fir.call @use_i64(%0) : (i64) -> ()
+    acc.yield
+  }
+  return
+}
+
+// CHECK-LABEL: @test_convert_sink
+// CHECK: acc.parallel {
+// CHECK:   %[[CVT:.*]] = fir.convert
+// CHECK:   fir.call @use_i64(%[[CVT]])
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
index ea7ee715189e3..851096b755f80 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
@@ -132,6 +132,17 @@ static Value getOriginalValue(Value val) {
 /// to find the original defining operation before making the determination.
 static bool isRematerializationCandidate(Value val,
                                          acc::OpenACCSupport &accSupport) {
+  // Check before tracing through view-like ops: an op may implement both
+  // ViewLikeOpInterface and OutlineRematerializationOpInterface.
+  if (Operation *directDefOp = val.getDefiningOp()) {
+    if (isa<acc::OutlineRematerializationOpInterface>(directDefOp)) {
+      LLVM_DEBUG(llvm::dbgs()
+                 << "\tDirect OutlineRematerializationOpInterface: "
+                 << *directDefOp << "\n");
+      return true;
+    }
+  }
+
   // Trace through view-like operations to find the original value.
   Value origVal = getOriginalValue(val);
   Operation *definingOp = origVal.getDefiningOp();

>From d12233255c907548f755901729a68e6a06d45a78 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 2 Mar 2026 12:27:49 -0800
Subject: [PATCH 2/3] Remove redundant OutlineRematerializationOpInterface
 check

Made-with: Cursor
---
 .../Transforms/OffloadLiveInValueCanonicalization.cpp       | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
index 851096b755f80..426f63f7508b3 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
@@ -157,12 +157,6 @@ static bool isRematerializationCandidate(Value val,
     return true;
   }
 
-  // Operations implementing OutlineRematerializationOpInterface are candidates.
-  if (isa<acc::OutlineRematerializationOpInterface>(definingOp)) {
-    LLVM_DEBUG(llvm::dbgs() << "\t\t-> OutlineRematerializationOpInterface\n");
-    return true;
-  }
-
   // Address-of operations referencing globals that are valid in GPU regions
   // or referencing constant globals should be rematerialized.
   if (auto addrOfOp = dyn_cast<acc::AddressOfGlobalOpInterface>(definingOp)) {

>From eb84ba06b51676bf6b4800cd88b6f8cddde1ea86 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 2 Mar 2026 12:52:19 -0800
Subject: [PATCH 3/3] Fallback to direct defining op when traced original is a
 block argument

Made-with: Cursor
---
 .../OffloadLiveInValueCanonicalization.cpp    | 23 ++++++++++---------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
index 426f63f7508b3..4fc7a49b04950 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
@@ -111,6 +111,10 @@ static Value getOriginalValue(Value val) {
   Value prev;
   while (val && val != prev) {
     prev = val;
+    // Stop tracing if the op is a rematerialization candidate itself.
+    if (isa_and_nonnull<acc::OutlineRematerializationOpInterface>(
+            val.getDefiningOp()))
+      break;
     if (auto viewLikeOp = val.getDefiningOp<ViewLikeOpInterface>())
       val = viewLikeOp.getViewSource();
     if (auto partialAccess =
@@ -132,20 +136,11 @@ static Value getOriginalValue(Value val) {
 /// to find the original defining operation before making the determination.
 static bool isRematerializationCandidate(Value val,
                                          acc::OpenACCSupport &accSupport) {
-  // Check before tracing through view-like ops: an op may implement both
-  // ViewLikeOpInterface and OutlineRematerializationOpInterface.
-  if (Operation *directDefOp = val.getDefiningOp()) {
-    if (isa<acc::OutlineRematerializationOpInterface>(directDefOp)) {
-      LLVM_DEBUG(llvm::dbgs()
-                 << "\tDirect OutlineRematerializationOpInterface: "
-                 << *directDefOp << "\n");
-      return true;
-    }
-  }
-
   // Trace through view-like operations to find the original value.
   Value origVal = getOriginalValue(val);
   Operation *definingOp = origVal.getDefiningOp();
+  if (!definingOp)
+    definingOp = val.getDefiningOp();
   if (!definingOp)
     return false;
 
@@ -157,6 +152,12 @@ static bool isRematerializationCandidate(Value val,
     return true;
   }
 
+  // Operations implementing OutlineRematerializationOpInterface are candidates.
+  if (isa<acc::OutlineRematerializationOpInterface>(definingOp)) {
+    LLVM_DEBUG(llvm::dbgs() << "\t\t-> OutlineRematerializationOpInterface\n");
+    return true;
+  }
+
   // Address-of operations referencing globals that are valid in GPU regions
   // or referencing constant globals should be rematerialized.
   if (auto addrOfOp = dyn_cast<acc::AddressOfGlobalOpInterface>(definingOp)) {



More information about the Mlir-commits mailing list