[Mlir-commits] [flang] [mlir] [mlir][acc][flang] Add genCast API to PointerLikeType (PR #192720)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Fri Apr 17 12:26:34 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-openacc

Author: Razvan Lupusoru (razvanlupusoru)

<details>
<summary>Changes</summary>

Introduces new API for PointerLikeType named genCast which can be used for generating IR that does type conversions. This is implemented for FIR reference types, memref, and LLVM ptr.

---

Patch is 24.97 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/192720.diff


9 Files Affected:

- (modified) flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h (+4) 
- (modified) flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp (+30) 
- (added) flang/test/Fir/OpenACC/pointer-like-interface-cast.mlir (+68) 
- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td (+28) 
- (modified) mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp (+73) 
- (added) mlir/test/Dialect/OpenACC/pointer-like-interface-cast.mlir (+36) 
- (modified) mlir/test/lib/Dialect/OpenACC/TestPointerLikeTypeInterface.cpp (+61-1) 
- (modified) mlir/unittests/Dialect/OpenACC/CMakeLists.txt (+1) 
- (modified) mlir/unittests/Dialect/OpenACC/OpenACCTypeInterfacesTest.cpp (+166-1) 


``````````diff
diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h
index 01a1e19afd74b..3798d668ed547 100644
--- a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h
+++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h
@@ -53,6 +53,10 @@ struct OpenACCPointerLikeModel
                 mlir::Location loc, mlir::Value valueToStore,
                 mlir::TypedValue<mlir::acc::PointerLikeType> destPtr) const;
 
+  mlir::Value genCast(mlir::Type pointer, mlir::OpBuilder &builder,
+                      mlir::Location loc, mlir::Value value,
+                      mlir::Type resultType) const;
+
   bool isDeviceData(mlir::Type pointer, mlir::Value var) const;
 };
 
diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
index 8749a816e1b00..ba72e46438a82 100644
--- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
@@ -1603,6 +1603,36 @@ template bool OpenACCPointerLikeModel<fir::LLVMPointerType>::genStore(
     mlir::Value valueToStore,
     mlir::TypedValue<mlir::acc::PointerLikeType> destPtr) const;
 
+template <typename Ty>
+mlir::Value OpenACCPointerLikeModel<Ty>::genCast(
+    mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
+    mlir::Value value, mlir::Type resultType) const {
+  (void)pointer;
+  if (value.getType() == resultType)
+    return value;
+
+  if (fir::ConvertOp::canBeConverted(value.getType(), resultType))
+    return fir::ConvertOp::create(builder, loc, resultType, value);
+
+  return {};
+}
+
+template mlir::Value OpenACCPointerLikeModel<fir::ReferenceType>::genCast(
+    mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
+    mlir::Value value, mlir::Type resultType) const;
+
+template mlir::Value OpenACCPointerLikeModel<fir::PointerType>::genCast(
+    mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
+    mlir::Value value, mlir::Type resultType) const;
+
+template mlir::Value OpenACCPointerLikeModel<fir::HeapType>::genCast(
+    mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
+    mlir::Value value, mlir::Type resultType) const;
+
+template mlir::Value OpenACCPointerLikeModel<fir::LLVMPointerType>::genCast(
+    mlir::Type pointer, mlir::OpBuilder &builder, mlir::Location loc,
+    mlir::Value value, mlir::Type resultType) const;
+
 /// Check CUDA attributes on a function argument.
 static bool hasCUDADeviceAttrOnFuncArg(mlir::BlockArgument blockArg) {
   auto *owner = blockArg.getOwner();
diff --git a/flang/test/Fir/OpenACC/pointer-like-interface-cast.mlir b/flang/test/Fir/OpenACC/pointer-like-interface-cast.mlir
new file mode 100644
index 0000000000000..c0ebd8ae1fbc3
--- /dev/null
+++ b/flang/test/Fir/OpenACC/pointer-like-interface-cast.mlir
@@ -0,0 +1,68 @@
+// RUN: fir-opt %s --split-input-file --pass-pipeline="builtin.module(func.func(test-acc-pointer-like-interface{test-mode=cast}))" 2>&1 | FileCheck %s
+
+func.func @test_fir_ref_to_memref_scalar() {
+  %0 = fir.alloca f32 {test.cast, cast_dest = memref<f32>}
+  // CHECK: Successfully generated cast for operation: %{{.*}} = fir.alloca f32{{.*}}
+  // CHECK: Cast result type: memref<f32>
+  // CHECK: Generated: %{{.*}} = fir.convert %{{.*}} : (!fir.ref<f32>) -> memref<f32>
+  return
+}
+
+// -----
+
+func.func @test_memref_to_fir_ref_scalar() {
+  %0 = memref.alloca() {test.cast, cast_dest = !fir.ref<f32>} : memref<f32>
+  // CHECK: Successfully generated cast for operation: %{{.*}} = memref.alloca(){{.*}}
+  // CHECK: Cast result type: !fir.ref<f32>
+  // CHECK: Generated: %{{.*}} = fir.convert %{{.*}} : (memref<f32>) -> !fir.ref<f32>
+  return
+}
+
+// -----
+
+func.func @test_fir_ref_identity() {
+  %0 = fir.alloca i32 {test.cast, cast_dest = !fir.ref<i32>}
+  // CHECK: Successfully generated cast for operation: %{{.*}} = fir.alloca i32{{.*}}
+  // CHECK: Cast result type: !fir.ref<i32>
+  return
+}
+
+// -----
+
+func.func @test_i64_to_fir_ref() {
+  %0 = arith.constant {test.cast, cast_dest = !fir.ref<i8>} 0 : i64
+  // CHECK: Successfully generated cast for operation: %{{.*}} = arith.constant{{.*}}
+  // CHECK: Cast result type: !fir.ref<i8>
+  // CHECK: Generated: %{{.*}} = fir.convert %{{.*}} : (i64) -> !fir.ref<i8>
+  return
+}
+
+// -----
+
+func.func @test_index_to_fir_ptr() {
+  %0 = arith.constant {test.cast, cast_dest = !fir.ptr<i8>} 0 : index
+  // CHECK: Successfully generated cast for operation: %{{.*}} = arith.constant{{.*}}
+  // CHECK: Cast result type: !fir.ptr<i8>
+  // CHECK: Generated: %{{.*}} = fir.convert %{{.*}} : (index) -> !fir.ptr<i8>
+  return
+}
+
+// -----
+
+func.func @test_fir_heap_to_i64() {
+  %0 = fir.zero_bits !fir.heap<i8> {test.cast, cast_dest = i64}
+  // CHECK: Successfully generated cast for operation: %{{.*}} = fir.zero_bits{{.*}}
+  // CHECK: Cast result type: i64
+  // CHECK: Generated: %{{.*}} = fir.convert %{{.*}} : (!fir.heap<i8>) -> i64
+  return
+}
+
+// -----
+
+func.func @test_fir_llvm_ptr_to_index() {
+  %0 = fir.zero_bits !fir.llvm_ptr<i8> {test.cast, cast_dest = index}
+  // CHECK: Successfully generated cast for operation: %{{.*}} = fir.zero_bits{{.*}}
+  // CHECK: Cast result type: index
+  // CHECK: Generated: %{{.*}} = fir.convert %{{.*}} : (!fir.llvm_ptr<i8>) -> index
+  return
+}
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
index 3bd4e5c679659..2753056bf8a7a 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
@@ -220,6 +220,34 @@ def OpenACC_PointerLikeTypeInterface : TypeInterface<"PointerLikeType"> {
         return false;
       }]
     >,
+    InterfaceMethod<
+      /*description=*/[{
+        Generates a cast from `value` to `resultType` when the implementing
+        pointer-like type can emit a lowering for that conversion.
+
+        This is intentionally a single operation (rather than separate
+        "cast to" / "cast from" hooks): the source type is always
+        `value.getType()` and the destination is always `resultType`.
+
+        Call sites typically dispatch on the `PointerLikeType` that owns the
+        conversion: use the source value's type when casting *from* a
+        pointer-like representation.
+
+        Returns the cast result on success, or an empty value if the cast is
+        unsupported (callers may then try the other endpoint's interface or
+        apply their own fallback).
+      }],
+      /*retTy=*/"::mlir::Value",
+      /*methodName=*/"genCast",
+      /*args=*/(ins "::mlir::OpBuilder &":$builder,
+                    "::mlir::Location":$loc,
+                    "::mlir::Value":$value,
+                    "::mlir::Type":$resultType),
+      /*methodBody=*/"",
+      /*defaultImplementation=*/[{
+        return {};
+      }]
+    >,
     InterfaceMethod<
       /*description=*/[{
         Returns true if the pointer points to device data.
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index bd26c70eb1831..6f49a66167f67 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -14,6 +14,7 @@
 #include "mlir/Dialect/MemRef/IR/MemRef.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/DialectImplementation.h"
 #include "mlir/IR/IRMapping.h"
@@ -246,6 +247,38 @@ struct MemRefPointerLikeModel
     return true;
   }
 
+  Value genCast(Type pointer, OpBuilder &builder, Location loc, Value value,
+                Type resultType) const {
+    (void)pointer;
+    if (value.getType() == resultType)
+      return value;
+
+    if (isa<BaseMemRefType>(value.getType()) &&
+        isa<BaseMemRefType>(resultType)) {
+      if (memref::CastOp::areCastCompatible(TypeRange(value.getType()),
+                                            TypeRange(resultType)))
+        return memref::CastOp::create(builder, loc, resultType, value);
+      if (memref::MemorySpaceCastOp::areCastCompatible(
+              TypeRange(value.getType()), TypeRange(resultType)))
+        return memref::MemorySpaceCastOp::create(builder, loc, resultType,
+                                                 value);
+    }
+
+    // If one side is not a memref, try the other type's `PointerLikeType`
+    // implementation (since it may be an out-of-tree reference type that
+    // we cannot generate here).
+    if (auto resPtrLike = dyn_cast<PointerLikeType>(resultType))
+      if (!isa<BaseMemRefType>(resPtrLike))
+        if (Value v = resPtrLike.genCast(builder, loc, value, resultType))
+          return v;
+    if (auto valPtrLike = dyn_cast<PointerLikeType>(value.getType()))
+      if (!isa<BaseMemRefType>(valPtrLike))
+        if (Value v = valPtrLike.genCast(builder, loc, value, resultType))
+          return v;
+
+    return {};
+  }
+
   bool isDeviceData(Type pointer, Value var) const {
     auto memrefTy = cast<T>(pointer);
     Attribute memSpace = memrefTy.getMemorySpace();
@@ -273,6 +306,46 @@ struct LLVMPointerPointerLikeModel
     LLVM::StoreOp::create(builder, loc, valueToStore, destPtr);
     return true;
   }
+
+  Value genCast(Type pointer, OpBuilder &builder, Location loc, Value value,
+                Type resultType) const {
+    (void)pointer;
+    if (value.getType() == resultType)
+      return value;
+
+    auto srcPtrTy = dyn_cast<LLVM::LLVMPointerType>(value.getType());
+    auto dstPtrTy = dyn_cast<LLVM::LLVMPointerType>(resultType);
+    if (srcPtrTy && dstPtrTy) {
+      if (srcPtrTy.getAddressSpace() != dstPtrTy.getAddressSpace())
+        return LLVM::AddrSpaceCastOp::create(builder, loc, resultType, value);
+      return value;
+    }
+
+    if (srcPtrTy && isa<IntegerType>(resultType))
+      return LLVM::PtrToIntOp::create(builder, loc, resultType, value);
+
+    if (dstPtrTy) {
+      Value intVal = value;
+      if (isa<IndexType>(value.getType()))
+        intVal = arith::IndexCastUIOp::create(builder, loc, builder.getI64Type(),
+                                              value);
+      if (isa<IntegerType>(intVal.getType()))
+        return LLVM::IntToPtrOp::create(builder, loc, resultType, intVal);
+    }
+
+    if (auto resPtrLike = dyn_cast<PointerLikeType>(resultType))
+      if (!isa<LLVM::LLVMPointerType>(resPtrLike))
+        if (Value v = resPtrLike.genCast(builder, loc, value, resultType))
+          return v;
+    if (auto valPtrLike = dyn_cast<PointerLikeType>(value.getType()))
+      if (!isa<LLVM::LLVMPointerType>(valPtrLike))
+        if (Value v = valPtrLike.genCast(builder, loc, value, resultType))
+          return v;
+
+    return UnrealizedConversionCastOp::create(builder, loc,
+                                              TypeRange(resultType), value)
+        .getResult(0);
+  }
 };
 
 struct MemrefAddressOfGlobalModel
diff --git a/mlir/test/Dialect/OpenACC/pointer-like-interface-cast.mlir b/mlir/test/Dialect/OpenACC/pointer-like-interface-cast.mlir
new file mode 100644
index 0000000000000..2a0939a3020db
--- /dev/null
+++ b/mlir/test/Dialect/OpenACC/pointer-like-interface-cast.mlir
@@ -0,0 +1,36 @@
+// RUN: mlir-opt %s --split-input-file --pass-pipeline="builtin.module(func.func(test-acc-pointer-like-interface{test-mode=cast}))" 2>&1 | FileCheck %s
+
+func.func @test_memref_cast_identity() {
+  %0 = memref.alloca() {test.cast, cast_dest = memref<f32>} : memref<f32>
+  // CHECK: Successfully generated cast for operation: %[[V:.*]] = memref.alloca(){{.*}} : memref<f32>
+  // CHECK: Cast result type: memref<f32>
+  return
+}
+
+// -----
+
+func.func @test_memref_cast_static_to_dynamic() {
+  %0 = memref.alloca() {test.cast, cast_dest = memref<?xf32>} : memref<4xf32>
+  // CHECK: Successfully generated cast for operation: %[[V:.*]] = memref.alloca(){{.*}} : memref<4xf32>
+  // CHECK: Cast result type: memref<?xf32>
+  // CHECK: Generated: %{{.*}} = memref.cast %[[V]] : memref<4xf32> to memref<?xf32>
+  return
+}
+
+// -----
+
+func.func @test_memref_memory_space_cast() {
+  %0 = memref.alloca() {test.cast, cast_dest = memref<4xf32, 1>} : memref<4xf32>
+  // CHECK: Successfully generated cast for operation: %[[V:.*]] = memref.alloca(){{.*}} : memref<4xf32>
+  // CHECK: Cast result type: memref<4xf32, 1>
+  // CHECK: Generated: %{{.*}} = memref.memory_space_cast %[[V]] : memref<4xf32> to memref<4xf32, 1>
+  return
+}
+
+// -----
+
+func.func @test_memref_cast_incompatible() {
+  %0 = memref.alloca() {test.cast, cast_dest = tensor<4xf32>} : memref<4xf32>
+  // CHECK: Failed to generate cast for operation: %{{.*}} = memref.alloca(){{.*}} : memref<4xf32>
+  return
+}
diff --git a/mlir/test/lib/Dialect/OpenACC/TestPointerLikeTypeInterface.cpp b/mlir/test/lib/Dialect/OpenACC/TestPointerLikeTypeInterface.cpp
index 3ff0dc85b2152..e45fd104e7331 100644
--- a/mlir/test/lib/Dialect/OpenACC/TestPointerLikeTypeInterface.cpp
+++ b/mlir/test/lib/Dialect/OpenACC/TestPointerLikeTypeInterface.cpp
@@ -46,7 +46,8 @@ struct TestPointerLikeTypeInterfacePass
 
   Pass::Option<std::string> testMode{
       *this, "test-mode",
-      llvm::cl::desc("Test mode: walk, alloc, copy, free, load, or store"),
+      llvm::cl::desc(
+          "Test mode: walk, alloc, copy, free, load, store, or cast"),
       llvm::cl::init("walk")};
 
   StringRef getArgument() const override {
@@ -79,6 +80,8 @@ struct TestPointerLikeTypeInterfacePass
                    OpBuilder &builder);
   void testGenStore(Operation *op, Value result, PointerLikeType pointerType,
                     OpBuilder &builder, Value providedValue = {});
+  void testGenCast(Operation *op, Value value, Type resultType,
+                   OpBuilder &builder);
 
   struct PointerCandidate {
     Operation *op;
@@ -96,6 +99,18 @@ void TestPointerLikeTypeInterfacePass::runOnOperation() {
   auto func = getOperation();
   OpBuilder builder(&getContext());
 
+  if (testMode == "cast") {
+    func.walk([&](Operation *op) {
+      if (!op->hasAttr("test.cast"))
+        return;
+      auto destAttr = dyn_cast_or_null<TypeAttr>(op->getAttr("cast_dest"));
+      if (!destAttr || op->getNumResults() == 0)
+        return;
+      testGenCast(op, op->getResult(0), destAttr.getValue(), builder);
+    });
+    return;
+  }
+
   if (testMode == "alloc" || testMode == "free" || testMode == "load" ||
       testMode == "store") {
     // Collect all candidates first
@@ -409,6 +424,51 @@ void TestPointerLikeTypeInterfacePass::testGenStore(Operation *op, Value result,
   }
 }
 
+void TestPointerLikeTypeInterfacePass::testGenCast(Operation *op, Value value,
+                                                   Type resultType,
+                                                   OpBuilder &builder) {
+  Location loc = op->getLoc();
+
+  OperationTracker tracker;
+  OpBuilder newBuilder(op->getContext());
+  newBuilder.setListener(&tracker);
+  newBuilder.setInsertionPointAfter(op);
+
+  PointerLikeType dispatchTy;
+  if (isa<PointerLikeType>(value.getType()))
+    dispatchTy = cast<PointerLikeType>(value.getType());
+  else if (isa<PointerLikeType>(resultType))
+    dispatchTy = cast<PointerLikeType>(resultType);
+  else {
+    llvm::errs() << "Failed genCast: neither value nor result type is "
+                    "PointerLikeType for operation: ";
+    op->print(llvm::errs());
+    llvm::errs() << "\n";
+    return;
+  }
+
+  Value castRes = dispatchTy.genCast(newBuilder, loc, value, resultType);
+
+  if (castRes) {
+    llvm::errs() << "Successfully generated cast for operation: ";
+    op->print(llvm::errs());
+    llvm::errs() << "\n";
+    llvm::errs() << "\tCast result type: ";
+    castRes.getType().print(llvm::errs());
+    llvm::errs() << "\n";
+
+    for (Operation *insertedOp : tracker.insertedOps) {
+      llvm::errs() << "\tGenerated: ";
+      insertedOp->print(llvm::errs());
+      llvm::errs() << "\n";
+    }
+  } else {
+    llvm::errs() << "Failed to generate cast for operation: ";
+    op->print(llvm::errs());
+    llvm::errs() << "\n";
+  }
+}
+
 } // namespace
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/unittests/Dialect/OpenACC/CMakeLists.txt b/mlir/unittests/Dialect/OpenACC/CMakeLists.txt
index 17d1721b82602..7bcb652b69185 100644
--- a/mlir/unittests/Dialect/OpenACC/CMakeLists.txt
+++ b/mlir/unittests/Dialect/OpenACC/CMakeLists.txt
@@ -16,6 +16,7 @@ mlir_target_link_libraries(MLIROpenACCTests
   MLIRDLTIDialect
   MLIRFuncDialect
   MLIRGPUDialect
+  MLIRLLVMDialect
   MLIRMemRefDialect
   MLIRArithDialect
   MLIROpenACCDialect
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCTypeInterfacesTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCTypeInterfacesTest.cpp
index c773c031e3b6e..521a2f3f26c16 100644
--- a/mlir/unittests/Dialect/OpenACC/OpenACCTypeInterfacesTest.cpp
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCTypeInterfacesTest.cpp
@@ -7,8 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Dialect/Arith/IR/Arith.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
 #include "mlir/Dialect/OpenACC/OpenACC.h"
 #include "mlir/IR/BuiltinDialect.h"
+#include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/DialectRegistry.h"
 #include "mlir/IR/MLIRContext.h"
@@ -16,6 +20,7 @@
 
 using namespace mlir;
 using namespace mlir::acc;
+using namespace mlir::LLVM;
 
 namespace {
 
@@ -51,7 +56,9 @@ class OpenACCTypeInterfacesTest : public ::testing::Test {
       IntegerType::attachInterface<TestReducibleIntegerModel>(*ctx);
     });
     context.appendDialectRegistry(registry);
-    context.loadDialect<acc::OpenACCDialect, arith::ArithDialect>();
+    context.loadDialect<acc::OpenACCDialect, arith::ArithDialect,
+                        memref::MemRefDialect, func::FuncDialect,
+                        LLVMDialect>();
   }
 
   MLIRContext context;
@@ -91,3 +98,161 @@ TEST_F(OpenACCTypeInterfacesTest, NonReducibleTypeReturnsNull) {
   auto reducible = dyn_cast<ReducibleType>(f32Type);
   EXPECT_TRUE(reducible == nullptr);
 }
+
+//===----------------------------------------------------------------------===//
+// PointerLikeType::genCast tests
+//===----------------------------------------------------------------------===//
+
+TEST_F(OpenACCTypeInterfacesTest, PointerLikeGenCastMemrefIdentity) {
+  Location loc = UnknownLoc::get(&context);
+  OwningOpRef<ModuleOp> module = ModuleOp::create(loc);
+  OpBuilder builder(module->getBodyRegion());
+  func::FuncOp fn = func::FuncOp::create(builder, loc, "cast_identity",
+                                         builder.getFunctionType({}, {}));
+  Block *block = fn.addEntryBlock();
+  builder.setInsertionPointToStart(block);
+
+  auto memTy = MemRefType::get({}, builder.getF32Type());
+  memref::AllocaOp alloca = memref::AllocaOp::create(builder, loc, memTy);
+  Value v = alloca.getResult();
+  auto ptrLike = cast<PointerLikeType>(v.getType());
+  Value out = ptrLike.genCast(builder, loc, v, memTy);
+  ASSERT_TRUE(out);
+  EXPECT_EQ(out, v);
+}
+
+TEST_F(OpenACCTypeInterfacesTest, PointerLikeGenCastMemrefStaticToDynamic) {
+  Location loc = UnknownLoc::get(&context);
+  OwningOpRef<ModuleOp> module = ModuleOp::create(loc);
+  OpBuilder builder(module->getBodyRegion());
+  func::FuncOp fn = func::FuncOp::create(builder, loc, "cast_memref",
+                                         builder.getFunctionType({}, {}));
+  Block *block = fn.addEntryBlock();
+  builder.setInsertionPointToStart(block);
+
+  auto srcTy = MemRefType::get({4}, builder.getF32Type());
+  auto dstTy = MemRefType::get({ShapedType::kDynamic}, builder.getF32Type());
+  memref::AllocaOp alloca = memref::AllocaOp::create(builder, loc, srcTy);
+  Value v = alloca.getResult();
+  auto ptrLike = cast<PointerLikeType>(v.getType());
+  Value out = ptrLike.genCast(builder, loc, v, dstTy);
+  ASSERT_TRUE(out);
+  EXPECT_EQ(out.getType(), dstTy);
+  ASSERT_TRUE(isa<memref::CastOp>(out.getDefiningOp()));
+}
+
+TEST_F(OpenACCTypeInterfacesTest, PointerLikeGenCastMemrefMemorySpace) {
+  Location loc = Unkn...
[truncated]

``````````

</details>


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


More information about the Mlir-commits mailing list