[Mlir-commits] [flang] [mlir] [flang][acc] Handle ViewLike ops with OutlineRematerializationOpInterface in OffloadLiveInValueCanonicalization (PR #184218)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Mar 5 08:55:49 PST 2026
https://github.com/khaki3 updated https://github.com/llvm/llvm-project/pull/184218
>From 596eafb6a23de8a75f94801c3c260f289fa997c3 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/8] [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 d7fadbc84ff1a..a994f30a6dd76 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 ®istry) {
*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 dd4fd06a17576318e5b0cf1fb785cef493e7860c 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/8] 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 1bca9e1da880e21190132269c87498fed2716b88 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/8] 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)) {
>From e5d52b8ab4074b238697f2ce10855195bf561b22 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 2 Mar 2026 12:53:09 -0800
Subject: [PATCH 4/8] Remove unnecessary getOriginalValue break
Made-with: Cursor
---
.../OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp | 4 ----
1 file changed, 4 deletions(-)
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
index 4fc7a49b04950..b1f3191bdb68b 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
@@ -111,10 +111,6 @@ 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 =
>From 72a839fb44083e27f5dda370a4491fbcb7af6025 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Wed, 4 Mar 2026 12:45:06 -0800
Subject: [PATCH 5/8] Fall back to direct defining op for
ViewLike+Rematerialization ops
When an op implements both ViewLikeOpInterface and
OutlineRematerializationOpInterface (e.g., fir.convert), getOriginalValue
traces through it. If the traced op is not a candidate, fall back to
checking the direct defining op. This handles all input types (block
arguments, fir.alloca, fir.call, etc.).
Made-with: Cursor
---
.../offload-livein-value-canonicalization.fir | 45 +++++++++++++++++++
.../OffloadLiveInValueCanonicalization.cpp | 18 ++++++--
2 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir b/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir
index d9313a1f933bd..04bf123dc3224 100644
--- a/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir
+++ b/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir
@@ -295,3 +295,48 @@ func.func @test_convert_sink(%arg0: !fir.ref<i32>) {
// CHECK: acc.parallel {
// CHECK: %[[CVT:.*]] = fir.convert
// CHECK: fir.call @use_i64(%[[CVT]])
+
+// -----
+
+// Test fir.convert sinking when input is fir.alloca (not a block argument).
+func.func private @use_i64(i64) -> ()
+
+func.func @test_convert_alloca_sink() {
+ %0 = fir.alloca i32
+ %1 = fir.convert %0 : (!fir.ref<i32>) -> i64
+ acc.parallel {
+ fir.call @use_i64(%1) : (i64) -> ()
+ acc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: @test_convert_alloca_sink
+// CHECK: %[[ALLOCA:.*]] = fir.alloca i32
+// CHECK: acc.parallel {
+// CHECK: %[[CVT:.*]] = fir.convert %[[ALLOCA]]
+// CHECK: fir.call @use_i64(%[[CVT]])
+
+// -----
+
+// Test fir.convert rematerialization when input is fir.alloca.
+func.func private @use_i64(i64) -> ()
+
+func.func @test_convert_alloca_remat() {
+ %0 = fir.alloca i32
+ %1 = fir.convert %0 : (!fir.ref<i32>) -> i64
+ fir.call @use_i64(%1) : (i64) -> ()
+ acc.parallel {
+ fir.call @use_i64(%1) : (i64) -> ()
+ acc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: @test_convert_alloca_remat
+// CHECK: %[[ALLOCA:.*]] = fir.alloca i32
+// CHECK: %[[CVT_OUTER:.*]] = fir.convert %[[ALLOCA]]
+// CHECK: fir.call @use_i64(%[[CVT_OUTER]])
+// CHECK: acc.parallel {
+// CHECK: %[[CVT_INNER:.*]] = fir.convert %[[ALLOCA]]
+// CHECK: fir.call @use_i64(%[[CVT_INNER]])
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
index b1f3191bdb68b..35657d3b28efb 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
@@ -135,9 +135,7 @@ static bool isRematerializationCandidate(Value val,
// 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)
+ if (!definingOp && !(definingOp = val.getDefiningOp()))
return false;
LLVM_DEBUG(llvm::dbgs() << "\tChecking candidate: " << *definingOp << "\n");
@@ -183,6 +181,20 @@ static bool isRematerializationCandidate(Value val,
}
}
+ // An op implementing ViewLikeOpInterface may also implement
+ // OutlineRematerializationOpInterface (e.g., fir.convert). When
+ // getOriginalValue traces through it, the traced op may not be a candidate.
+ // Fall back to the direct defining op.
+ if (origVal != val) {
+ definingOp = val.getDefiningOp();
+ if (definingOp &&
+ isa<acc::OutlineRematerializationOpInterface>(definingOp)) {
+ LLVM_DEBUG(llvm::dbgs()
+ << "\t\t-> OutlineRematerializationOpInterface (direct)\n");
+ return true;
+ }
+ }
+
LLVM_DEBUG(llvm::dbgs() << "\t\t-> not a candidate\n");
return false;
}
>From 1de2eb3214c83b0e587e6ca198fb254fa7a93946 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Wed, 4 Mar 2026 14:02:58 -0800
Subject: [PATCH 6/8] Stop tracing at OutlineRematerializationOpInterface in
getOriginalValue
Made-with: Cursor
---
.../OffloadLiveInValueCanonicalization.cpp | 23 ++++++-------------
1 file changed, 7 insertions(+), 16 deletions(-)
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
index 35657d3b28efb..d0c6bc3f0c423 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
@@ -106,11 +106,16 @@ static bool allUsersAreInsideRegion(Value val, Region ®ion) {
}
/// Traces through view-like and partial entity access operations to find the
-/// original defining value.
+/// original defining value. Stops tracing at ops that implement
+/// OutlineRematerializationOpInterface, since those ops are rematerialization
+/// candidates themselves and should not be traced through.
static Value getOriginalValue(Value val) {
Value prev;
while (val && val != prev) {
prev = val;
+ if (isa_and_nonnull<acc::OutlineRematerializationOpInterface>(
+ val.getDefiningOp()))
+ break;
if (auto viewLikeOp = val.getDefiningOp<ViewLikeOpInterface>())
val = viewLikeOp.getViewSource();
if (auto partialAccess =
@@ -135,7 +140,7 @@ static bool isRematerializationCandidate(Value val,
// 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;
LLVM_DEBUG(llvm::dbgs() << "\tChecking candidate: " << *definingOp << "\n");
@@ -181,20 +186,6 @@ static bool isRematerializationCandidate(Value val,
}
}
- // An op implementing ViewLikeOpInterface may also implement
- // OutlineRematerializationOpInterface (e.g., fir.convert). When
- // getOriginalValue traces through it, the traced op may not be a candidate.
- // Fall back to the direct defining op.
- if (origVal != val) {
- definingOp = val.getDefiningOp();
- if (definingOp &&
- isa<acc::OutlineRematerializationOpInterface>(definingOp)) {
- LLVM_DEBUG(llvm::dbgs()
- << "\t\t-> OutlineRematerializationOpInterface (direct)\n");
- return true;
- }
- }
-
LLVM_DEBUG(llvm::dbgs() << "\t\t-> not a candidate\n");
return false;
}
>From c27af818ede2411d0aa6f9d9ff5424ec1dfcbb69 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Wed, 4 Mar 2026 15:05:59 -0800
Subject: [PATCH 7/8] Revert getOriginalValue break; use fallback in
isRematerializationCandidate
Stopping at OutlineRematerializationOpInterface in getOriginalValue is
too aggressive: it catches intermediate fir.convert ops in the trace
chain (e.g., fir.declare -> fir.convert -> unboxchar), causing the pass
to rematerialize the intermediate convert and leave its operand as an
illegal live-in. The fallback approach only checks the direct defining
op of the live-in value, avoiding this problem.
Made-with: Cursor
---
.../OffloadLiveInValueCanonicalization.cpp | 23 +++++++++++++------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
index d0c6bc3f0c423..7dbde227b2fab 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/OffloadLiveInValueCanonicalization.cpp
@@ -106,16 +106,11 @@ static bool allUsersAreInsideRegion(Value val, Region ®ion) {
}
/// Traces through view-like and partial entity access operations to find the
-/// original defining value. Stops tracing at ops that implement
-/// OutlineRematerializationOpInterface, since those ops are rematerialization
-/// candidates themselves and should not be traced through.
+/// original defining value.
static Value getOriginalValue(Value val) {
Value prev;
while (val && val != prev) {
prev = val;
- if (isa_and_nonnull<acc::OutlineRematerializationOpInterface>(
- val.getDefiningOp()))
- break;
if (auto viewLikeOp = val.getDefiningOp<ViewLikeOpInterface>())
val = viewLikeOp.getViewSource();
if (auto partialAccess =
@@ -140,7 +135,7 @@ static bool isRematerializationCandidate(Value val,
// Trace through view-like operations to find the original value.
Value origVal = getOriginalValue(val);
Operation *definingOp = origVal.getDefiningOp();
- if (!definingOp)
+ if (!definingOp && !(definingOp = val.getDefiningOp()))
return false;
LLVM_DEBUG(llvm::dbgs() << "\tChecking candidate: " << *definingOp << "\n");
@@ -186,6 +181,20 @@ static bool isRematerializationCandidate(Value val,
}
}
+ // An op implementing both ViewLikeOpInterface and
+ // OutlineRematerializationOpInterface may have been traced through by
+ // getOriginalValue. If the traced op is not a candidate, check the direct
+ // defining op of the live-in value.
+ if (origVal != val) {
+ definingOp = val.getDefiningOp();
+ if (definingOp &&
+ isa<acc::OutlineRematerializationOpInterface>(definingOp)) {
+ LLVM_DEBUG(llvm::dbgs()
+ << "\t\t-> OutlineRematerializationOpInterface (direct)\n");
+ return true;
+ }
+ }
+
LLVM_DEBUG(llvm::dbgs() << "\t\t-> not a candidate\n");
return false;
}
>From ec88571eec7a41f1db1e6221adbb5fa0bdc655ff Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Thu, 5 Mar 2026 08:55:09 -0800
Subject: [PATCH 8/8] Add test for intermediate fir.convert in unboxchar trace
chain
Verify that an intermediate fir.convert in a declare -> convert ->
unboxchar chain is not rematerialized, while a direct ptr-to-int
fir.convert is correctly sunk.
Made-with: Cursor
---
.../offload-livein-value-canonicalization.fir | 31 +++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir b/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir
index 04bf123dc3224..fa9f9c429fa02 100644
--- a/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir
+++ b/flang/test/Fir/OpenACC/offload-livein-value-canonicalization.fir
@@ -340,3 +340,34 @@ func.func @test_convert_alloca_remat() {
// CHECK: acc.parallel {
// CHECK: %[[CVT_INNER:.*]] = fir.convert %[[ALLOCA]]
// CHECK: fir.call @use_i64(%[[CVT_INNER]])
+
+// -----
+
+// Test that an intermediate fir.convert in a trace chain
+// (declare -> convert -> unboxchar) does not get rematerialized,
+// while a direct ptr-to-int fir.convert is correctly sunk.
+func.func private @use_i64(i64) -> ()
+func.func private @use_ref(!fir.ref<!fir.char<1,10>>) -> ()
+
+func.func @test_convert_chain_and_direct(%arg0: !fir.boxchar<1>, %arg1: !fir.ref<i32>) {
+ %c10 = arith.constant 10 : index
+ %0:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+ %1 = fir.convert %0#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,10>>
+ %2 = fir.declare %1 typeparams %c10 {uniq_name = "scalar"} : (!fir.ref<!fir.char<1,10>>, index) -> !fir.ref<!fir.char<1,10>>
+ %3 = fir.convert %arg1 : (!fir.ref<i32>) -> i64
+ acc.parallel {
+ fir.call @use_ref(%2) : (!fir.ref<!fir.char<1,10>>) -> ()
+ fir.call @use_i64(%3) : (i64) -> ()
+ acc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: @test_convert_chain_and_direct
+// CHECK: %[[UNBOX:.*]]:2 = fir.unboxchar %arg0
+// CHECK: %[[CVT_REF:.*]] = fir.convert %[[UNBOX]]#0
+// CHECK: %[[DECL:.*]] = fir.declare %[[CVT_REF]]
+// CHECK: acc.parallel {
+// CHECK: %[[CVT_INT:.*]] = fir.convert %arg1
+// CHECK: fir.call @use_ref(%[[DECL]])
+// CHECK: fir.call @use_i64(%[[CVT_INT]])
More information about the Mlir-commits
mailing list