[Mlir-commits] [mlir] [mlir][acc] Add operation for private handle to memref (PR #201603)
Razvan Lupusoru
llvmlistbot at llvm.org
Thu Jun 4 07:50:11 PDT 2026
https://github.com/razvanlupusoru created https://github.com/llvm/llvm-project/pull/201603
This MR introduces a new operation `acc.unwrap_private` for creating a pointer-like view of the `acc.private_type` handle. This operation will be used when materializing `acc.private_local` into the memory view needed to access the allocated private memory. This new operation is just a simple cast and thus it gets ViewLikeOpInterface attached to it.
Additionally, `acc.private_type` is now treated as a pointer-like type to ease conversions to other pointer-like types via PointerLikeType::genCast.
>From 883a17d7232724e001d0ec5ca310c3e362f3d81c Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Thu, 4 Jun 2026 07:45:06 -0700
Subject: [PATCH] [mlir][acc] Add operation for private handle to memref
This MR introduces a new operation `acc.unwrap_private`
for creating a pointer-like view of the `acc.private_type`
handle. This operation will be used when materializing
`acc.private_local` into the memory view needed to access
the allocated private memory. This new operation is
just a simple cast and thus it gets ViewLikeOpInterface
attached to it.
Additionally, `acc.private_type` is now treated as a
pointer-like type to ease conversions to other pointer-like
types via PointerLikeType::genCast.
---
mlir/include/mlir/Dialect/OpenACC/OpenACC.h | 1 +
.../mlir/Dialect/OpenACC/OpenACCCGOps.td | 23 ++++++++++++++++
mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp | 18 +++++++++++++
.../Dialect/OpenACC/ops-cg-privatization.mlir | 27 +++++++++++++++++++
.../OpenACC/OpenACCTypeInterfacesTest.cpp | 21 +++++++++++++++
5 files changed, 90 insertions(+)
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACC.h b/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
index 682e8ff9784c8..d5cd04949c751 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
@@ -32,6 +32,7 @@
#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Interfaces/LoopLikeInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
+#include "mlir/Interfaces/ViewLikeInterface.h"
#include <variant>
#define GET_TYPEDEF_CLASSES
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCCGOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCCGOps.td
index 9bca3b36c9785..13969f9fc9c65 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCCGOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCCGOps.td
@@ -17,6 +17,7 @@
#define OPENACC_CG_OPS
include "mlir/Interfaces/InferTypeOpInterface.td"
+include "mlir/Interfaces/ViewLikeInterface.td"
// This file is intended to be included from OpenACCOps.td, which provides
// the necessary includes and definitions. The operations defined here use
@@ -253,6 +254,28 @@ def OpenACC_PrivatizeOp : OpenACC_Op<"privatize", []> {
];
}
+//===----------------------------------------------------------------------===//
+// acc.unwrap_private
+//===----------------------------------------------------------------------===//
+
+def OpenACC_UnwrapPrivateOp
+ : OpenACC_Op<"unwrap_private",
+ [NoMemoryEffect, AlwaysSpeculatable, ViewLikeOpInterface]> {
+ let summary = "Unwrap acc.private_type handle to pointer-like storage";
+ let description = [{
+ Converts a privatization handle (`acc.private_type<T>`) to a pointer-like
+ view of the underlying private storage.
+ }];
+ let arguments = (ins OpenACC_PrivateType:$handle);
+ let results = (outs OpenACC_PointerLikeType:$result);
+ let assemblyFormat = [{
+ $handle attr-dict `:` qualified(type($handle)) `to` type($result)
+ }];
+ let extraClassDeclaration = [{
+ ::mlir::Value getViewSource() { return getHandle(); }
+ }];
+}
+
//===----------------------------------------------------------------------===//
// acc.private_local
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index f5ad1867086b6..ec8bac765ed33 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -346,6 +346,23 @@ struct LLVMPointerPointerLikeModel
}
};
+struct PrivateTypePointerLikeModel
+ : public PointerLikeType::ExternalModel<PrivateTypePointerLikeModel,
+ PrivateType> {
+ Type getElementType(Type type) const {
+ return cast<PrivateType>(type).getBaseTy();
+ }
+
+ Value genCast(Type, OpBuilder &builder, Location loc, Value value,
+ Type resultType) const {
+ if (value.getType() == resultType)
+ return value;
+ if (!isa<PointerLikeType>(resultType))
+ return {};
+ return UnwrapPrivateOp::create(builder, loc, resultType, value).getResult();
+ }
+};
+
struct MemrefAddressOfGlobalModel
: public AddressOfGlobalOpInterface::ExternalModel<
MemrefAddressOfGlobalModel, memref::GetGlobalOp> {
@@ -474,6 +491,7 @@ void OpenACCDialect::initialize() {
MemRefPointerLikeModel<UnrankedMemRefType>>(*getContext());
LLVM::LLVMPointerType::attachInterface<LLVMPointerPointerLikeModel>(
*getContext());
+ PrivateType::attachInterface<PrivateTypePointerLikeModel>(*getContext());
// Attach operation interfaces
memref::GetGlobalOp::attachInterface<MemrefAddressOfGlobalModel>(
diff --git a/mlir/test/Dialect/OpenACC/ops-cg-privatization.mlir b/mlir/test/Dialect/OpenACC/ops-cg-privatization.mlir
index 206466e94abd7..2b0af1527a984 100644
--- a/mlir/test/Dialect/OpenACC/ops-cg-privatization.mlir
+++ b/mlir/test/Dialect/OpenACC/ops-cg-privatization.mlir
@@ -1,5 +1,7 @@
// RUN: mlir-opt -split-input-file %s | FileCheck %s --check-prefixes=CHECK
+// Verify the printed output can be parsed.
// RUN: mlir-opt -split-input-file %s | mlir-opt -split-input-file | FileCheck %s --check-prefixes=CHECK
+// Verify the generic form can be parsed.
// RUN: mlir-opt -split-input-file -mlir-print-op-generic %s | mlir-opt -split-input-file | FileCheck %s --check-prefixes=CHECK
// -----
@@ -114,3 +116,28 @@ func.func @privatize_inside_compute_region(%data : memref<64xf32>) {
// CHECK: acc.private_local
// CHECK: memref.load %{{.*}}[%{{.*}}] : memref<64xf32>
// CHECK: } {origin = "acc.parallel"}
+
+// -----
+
+// CHECK-LABEL: func @unwrap_private_to_memref
+func.func @unwrap_private_to_memref() {
+ %h = acc.privatize : () -> !acc.private_type<memref<i32>>
+ %m = acc.unwrap_private %h : !acc.private_type<memref<i32>> to memref<i32>
+ %z = arith.constant 0 : i32
+ memref.store %z, %m[] : memref<i32>
+ return
+}
+// CHECK-DAG: %[[H:.*]] = acc.privatize
+// CHECK-SAME: () -> !acc.private_type<memref<i32>>
+// CHECK: %{{.*}} = acc.unwrap_private %[[H]]
+// CHECK-SAME: !acc.private_type<memref<i32>> to memref<i32>
+
+// -----
+
+// CHECK-LABEL: func @unwrap_private_to_byte_memref
+func.func @unwrap_private_to_byte_memref() {
+ %h = acc.privatize : () -> !acc.private_type<memref<f64>>
+ %storage = acc.unwrap_private %h : !acc.private_type<memref<f64>> to memref<?xi8>
+ return
+}
+// CHECK: acc.unwrap_private %{{.*}} : !acc.private_type<memref<f64>> to memref<?xi8>
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCTypeInterfacesTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCTypeInterfacesTest.cpp
index 0d5419203dbbe..573f8c6e902cd 100644
--- a/mlir/unittests/Dialect/OpenACC/OpenACCTypeInterfacesTest.cpp
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCTypeInterfacesTest.cpp
@@ -256,3 +256,24 @@ TEST_F(OpenACCTypeInterfacesTest, PointerLikeGenCastLLVMIntToPtrFromIndex) {
ASSERT_TRUE(intToPtr);
EXPECT_TRUE(isa<arith::IndexCastUIOp>(intToPtr.getArg().getDefiningOp()));
}
+
+TEST_F(OpenACCTypeInterfacesTest, PointerLikeGenCastPrivateTypeToMemref) {
+ Location loc = UnknownLoc::get(&context);
+ OwningOpRef<ModuleOp> module = ModuleOp::create(loc);
+ OpBuilder builder(module->getBodyRegion());
+ func::FuncOp fn = func::FuncOp::create(
+ builder, loc, "cast_private_to_memref", builder.getFunctionType({}, {}));
+ Block *block = fn.addEntryBlock();
+ builder.setInsertionPointToStart(block);
+
+ Type privateTy = PrivateType::get(&context, builder.getI8Type());
+ Type memrefTy = MemRefType::get({ShapedType::kDynamic}, builder.getI8Type());
+ Value handle = UndefOp::create(builder, loc, privateTy);
+ auto ptrLike = cast<PointerLikeType>(privateTy);
+ Value out = ptrLike.genCast(builder, loc, handle, memrefTy);
+ ASSERT_TRUE(out);
+ EXPECT_EQ(out.getType(), memrefTy);
+ auto unwrap = dyn_cast<UnwrapPrivateOp>(out.getDefiningOp());
+ ASSERT_TRUE(unwrap);
+ EXPECT_EQ(unwrap.getHandle(), handle);
+}
More information about the Mlir-commits
mailing list