[Mlir-commits] [mlir] [acc] Expand OpenACCSupport to provide getRecipeName and emitNYI (PR #165628)
Razvan Lupusoru
llvmlistbot at llvm.org
Wed Oct 29 14:49:51 PDT 2025
https://github.com/razvanlupusoru created https://github.com/llvm/llvm-project/pull/165628
Extends OpenACCSupport utilities to include recipe name generation and error reporting for unsupported features, providing foundation for variable privatization handling.
Changes:
- Add RecipeKind enum (private, firstprivate, reduction) for APIs that request a specific kind of recipe
- Add getRecipeName() API to OpenACCSupport and OpenACCUtils that generates recipe names from types (e.g., "privatization_memref_5x10xf32_")
- Add emitNYI() API to OpenACCSupport for graceful handling of not-yet-implemented cases
- Generalize MemRefPointerLikeModel template to support UnrankedMemRefType
- Add unit tests and integration tests for new APIs
>From add0d0584a22ca57a2992c6dece0a7f280f68a27 Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Wed, 29 Oct 2025 14:48:32 -0700
Subject: [PATCH] [acc] Expand OpenACCSupport to provide getRecipeName and
emitNYI
Extends OpenACCSupport utilities to include recipe name
generation and error reporting for unsupported features,
providing foundation for variable privatization handling.
Changes:
- Add RecipeKind enum (private, firstprivate, reduction) for
APIs that request a specific kind of recipe
- Add getRecipeName() API to OpenACCSupport and OpenACCUtils
that generates recipe names from types (e.g.,
"privatization_memref_5x10xf32_")
- Add emitNYI() API to OpenACCSupport for graceful handling
of not-yet-implemented cases
- Generalize MemRefPointerLikeModel template to support
UnrankedMemRefType
- Add unit tests and integration tests for new APIs
---
.../Dialect/OpenACC/Analysis/OpenACCSupport.h | 36 ++++++++
.../mlir/Dialect/OpenACC/OpenACCOps.td | 20 +++++
.../mlir/Dialect/OpenACC/OpenACCUtils.h | 8 ++
.../OpenACC/Analysis/OpenACCSupport.cpp | 20 +++++
mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp | 13 +--
.../Dialect/OpenACC/Utils/OpenACCUtils.cpp | 39 +++++++++
.../OpenACC/support-analysis-recipename.mlir | 78 +++++++++++++++++
.../OpenACC/support-analysis-unsupported.mlir | 18 ++++
.../Dialect/OpenACC/TestOpenACCSupport.cpp | 22 +++++
.../Dialect/OpenACC/OpenACCUtilsTest.cpp | 85 +++++++++++++++++++
10 files changed, 334 insertions(+), 5 deletions(-)
create mode 100644 mlir/test/Dialect/OpenACC/support-analysis-recipename.mlir
create mode 100644 mlir/test/Dialect/OpenACC/support-analysis-unsupported.mlir
diff --git a/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h b/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
index 0833462ea0509..d9b2646b753f3 100644
--- a/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
+++ b/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
@@ -58,6 +58,9 @@
namespace mlir {
namespace acc {
+// Forward declaration for RecipeKind enum
+enum class RecipeKind : uint32_t;
+
namespace detail {
/// This class contains internal trait classes used by OpenACCSupport.
/// It follows the Concept-Model pattern used throughout MLIR (e.g., in
@@ -69,6 +72,13 @@ struct OpenACCSupportTraits {
/// Get the variable name for a given MLIR value.
virtual std::string getVariableName(Value v) = 0;
+
+ /// Get the recipe name for a given kind, type and value.
+ virtual std::string getRecipeName(RecipeKind kind, Type type,
+ Value var) = 0;
+
+ // Used to report a case that is not supported by the implementation.
+ virtual InFlightDiagnostic emitNYI(Location loc, const Twine &message) = 0;
};
/// This class wraps a concrete OpenACCSupport implementation and forwards
@@ -84,6 +94,14 @@ struct OpenACCSupportTraits {
return impl.getVariableName(v);
}
+ std::string getRecipeName(RecipeKind kind, Type type, Value var) final {
+ return impl.getRecipeName(kind, type, var);
+ }
+
+ InFlightDiagnostic emitNYI(Location loc, const Twine &message) final {
+ return impl.emitNYI(loc, message);
+ }
+
private:
ImplT impl;
};
@@ -118,6 +136,24 @@ class OpenACCSupport {
/// \return The variable name, or an empty string if unavailable.
std::string getVariableName(Value v);
+ /// Get the recipe name for a given type and value.
+ ///
+ /// \param kind The kind of recipe to get the name for.
+ /// \param type The type to get the recipe name for. Can be null if the
+ /// var is provided instead.
+ /// \param var The MLIR value to get the recipe name for. Can be null if
+ /// the type is provided instead.
+ /// \return The recipe name, or an empty string if not available.
+ std::string getRecipeName(RecipeKind kind, Type type, Value var);
+
+ /// Report a case that is not yet supported by the implementation.
+ ///
+ /// \param loc The location to report the unsupported case at.
+ /// \param message The message to report.
+ /// \return An in-flight diagnostic object that can be used to report the
+ /// unsupported case.
+ InFlightDiagnostic emitNYI(Location loc, const Twine &message);
+
/// Signal that this analysis should always be preserved so that
/// underlying implementation registration is not lost.
bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa) {
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index a18c18af8a753..2f4517ddfe754 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -152,6 +152,26 @@ def OpenACC_LoopParMode : I32EnumAttr<
let genSpecializedAttr = 0;
}
+def OpenACC_PrivateRecipe : I32EnumAttrCase<"private_recipe", 0>;
+def OpenACC_FirstprivateRecipe : I32EnumAttrCase<"firstprivate_recipe", 1>;
+def OpenACC_ReductionRecipe : I32EnumAttrCase<"reduction_recipe", 2>;
+
+def OpenACC_RecipeKind : I32EnumAttr<
+ "RecipeKind",
+ "Encodes the options for kinds of recipes availabie in acc dialect",
+ [
+ OpenACC_PrivateRecipe, OpenACC_FirstprivateRecipe,
+ OpenACC_ReductionRecipe]> {
+ let cppNamespace = "::mlir::acc";
+ let genSpecializedAttr = 0;
+}
+
+def OpenACC_RecipeKindAttr : EnumAttr<OpenACC_Dialect,
+ OpenACC_RecipeKind,
+ "recipe_kind"> {
+ let assemblyFormat = [{ ```<` $value `>` }];
+}
+
// Type used in operation below.
def IntOrIndex : AnyTypeOf<[AnyInteger, Index]>;
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h b/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h
index 0ee88c6f47b67..98a30c8d9530a 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h
@@ -43,6 +43,14 @@ mlir::acc::VariableTypeCategory getTypeCategory(mlir::Value var);
/// empty string if no name is found.
std::string getVariableName(mlir::Value v);
+/// Get the recipe name for a given kind, type and value.
+///
+/// \param kind The kind of recipe to get the name for.
+/// \param type The type to get the recipe name for. Can be null if the
+/// var is provided instead.
+/// \return The recipe name, or an empty string if not available.
+std::string getRecipeName(mlir::acc::RecipeKind kind, mlir::Type type);
+
} // namespace acc
} // namespace mlir
diff --git a/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp b/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp
index f6b4534794eaf..78d0e9ab6369c 100644
--- a/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp
+++ b/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp
@@ -22,5 +22,25 @@ std::string OpenACCSupport::getVariableName(Value v) {
return acc::getVariableName(v);
}
+std::string OpenACCSupport::getRecipeName(RecipeKind kind, Type type,
+ Value var) {
+ if (impl)
+ return impl->getRecipeName(kind, type, var);
+ // The default implementation assumes that only type matters
+ // and the actual instance of variable is not relevant.
+ auto recipeName = acc::getRecipeName(kind, type);
+ if (recipeName.empty())
+ emitNYI(var ? var.getLoc() : UnknownLoc::get(type.getContext()),
+ "variable privatization (incomplete recipe name handling)");
+ return recipeName;
+}
+
+InFlightDiagnostic OpenACCSupport::emitNYI(Location loc,
+ const Twine &message) {
+ if (impl)
+ return impl->emitNYI(loc, message);
+ return mlir::emitError(loc, "not yet implemented: " + message);
+}
+
} // namespace acc
} // namespace mlir
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index ca46629919dba..35eba724a9059 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -50,11 +50,11 @@ static void attachVarNameAttr(Operation *op, OpBuilder &builder,
}
}
+template <typename T>
struct MemRefPointerLikeModel
- : public PointerLikeType::ExternalModel<MemRefPointerLikeModel,
- MemRefType> {
+ : public PointerLikeType::ExternalModel<MemRefPointerLikeModel<T>, T> {
Type getElementType(Type pointer) const {
- return cast<MemRefType>(pointer).getElementType();
+ return cast<T>(pointer).getElementType();
}
mlir::acc::VariableTypeCategory
@@ -63,7 +63,7 @@ struct MemRefPointerLikeModel
if (auto mappableTy = dyn_cast<MappableType>(varType)) {
return mappableTy.getTypeCategory(varPtr);
}
- auto memrefTy = cast<MemRefType>(pointer);
+ auto memrefTy = cast<T>(pointer);
if (!memrefTy.hasRank()) {
// This memref is unranked - aka it could have any rank, including a
// rank of 0 which could mean scalar. For now, return uncategorized.
@@ -296,7 +296,10 @@ void OpenACCDialect::initialize() {
// By attaching interfaces here, we make the OpenACC dialect dependent on
// the other dialects. This is probably better than having dialects like LLVM
// and memref be dependent on OpenACC.
- MemRefType::attachInterface<MemRefPointerLikeModel>(*getContext());
+ MemRefType::attachInterface<MemRefPointerLikeModel<MemRefType>>(
+ *getContext());
+ UnrankedMemRefType::attachInterface<
+ MemRefPointerLikeModel<UnrankedMemRefType>>(*getContext());
LLVM::LLVMPointerType::attachInterface<LLVMPointerPointerLikeModel>(
*getContext());
}
diff --git a/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp b/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp
index 89adda82646e6..660c3138af0ec 100644
--- a/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp
+++ b/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp
@@ -11,6 +11,7 @@
#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/Interfaces/ViewLikeInterface.h"
#include "llvm/ADT/TypeSwitch.h"
+#include "llvm/Support/Casting.h"
mlir::Operation *mlir::acc::getEnclosingComputeOp(mlir::Region ®ion) {
mlir::Operation *parentOp = region.getParentOp();
@@ -106,3 +107,41 @@ std::string mlir::acc::getVariableName(mlir::Value v) {
return "";
}
+
+std::string mlir::acc::getRecipeName(mlir::acc::RecipeKind kind,
+ mlir::Type type) {
+ assert(kind == mlir::acc::RecipeKind::private_recipe ||
+ kind == mlir::acc::RecipeKind::firstprivate_recipe ||
+ kind == mlir::acc::RecipeKind::reduction_recipe);
+ if (!llvm::isa<mlir::acc::PointerLikeType, mlir::acc::MappableType>(type))
+ return "";
+
+ std::string recipeName;
+ llvm::raw_string_ostream ss(recipeName);
+ ss << (kind == mlir::acc::RecipeKind::private_recipe ? "privatization_"
+ : kind == mlir::acc::RecipeKind::firstprivate_recipe
+ ? "firstprivatization_"
+ : "reduction_");
+
+ // Print the type using its dialect-defined textual format.
+ type.print(ss);
+ ss.flush();
+
+ // Replace invalid characters (anything that's not a letter, number, or
+ // period) since this needs to be a valid MLIR identifier.
+ for (char &c : recipeName) {
+ if (!std::isalnum(static_cast<unsigned char>(c)) && c != '.' && c != '_') {
+ if (c == '?')
+ c = 'U';
+ else if (c == '*')
+ c = 'Z';
+ else if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' ||
+ c == '}' || c == '<' || c == '>')
+ c = '_';
+ else
+ c = 'X';
+ }
+ }
+
+ return recipeName;
+}
diff --git a/mlir/test/Dialect/OpenACC/support-analysis-recipename.mlir b/mlir/test/Dialect/OpenACC/support-analysis-recipename.mlir
new file mode 100644
index 0000000000000..8ea53b5d0f4d4
--- /dev/null
+++ b/mlir/test/Dialect/OpenACC/support-analysis-recipename.mlir
@@ -0,0 +1,78 @@
+// RUN: mlir-opt %s -split-input-file -test-acc-support | FileCheck %s
+
+// Test private recipe with 2D memref
+func.func @test_private_2d_memref() {
+ // Create a 2D memref
+ %0 = memref.alloca() {test.recipe_name = #acc.recipe_kind<private_recipe>} : memref<5x10xf32>
+
+ // CHECK: op=%{{.*}} = memref.alloca() {test.recipe_name = #acc.recipe_kind<private_recipe>} : memref<5x10xf32>
+ // CHECK-NEXT: getRecipeName(kind=private_recipe, type=memref<5x10xf32>)="privatization_memref_5x10xf32_"
+
+ return
+}
+
+// -----
+
+// Test firstprivate recipe with 2D memref
+func.func @test_firstprivate_2d_memref() {
+ // Create a 2D memref
+ %0 = memref.alloca() {test.recipe_name = #acc.recipe_kind<firstprivate_recipe>} : memref<8x16xf64>
+
+ // CHECK: op=%{{.*}} = memref.alloca() {test.recipe_name = #acc.recipe_kind<firstprivate_recipe>} : memref<8x16xf64>
+ // CHECK-NEXT: getRecipeName(kind=firstprivate_recipe, type=memref<8x16xf64>)="firstprivatization_memref_8x16xf64_"
+
+ return
+}
+
+// -----
+
+// Test reduction recipe with 2D memref
+func.func @test_reduction_2d_memref() {
+ // Create a 2D memref
+ %0 = memref.alloca() {test.recipe_name = #acc.recipe_kind<reduction_recipe>} : memref<4x8xi32>
+
+ // CHECK: op=%{{.*}} = memref.alloca() {test.recipe_name = #acc.recipe_kind<reduction_recipe>} : memref<4x8xi32>
+ // CHECK-NEXT: getRecipeName(kind=reduction_recipe, type=memref<4x8xi32>)="reduction_memref_4x8xi32_"
+
+ return
+}
+
+// -----
+
+// Test private recipe with dynamic memref
+func.func @test_private_dynamic_memref(%arg0: memref<5x10xi32>) {
+ // Cast to dynamic dimensions
+ %0 = memref.cast %arg0 {test.recipe_name = #acc.recipe_kind<private_recipe>} : memref<5x10xi32> to memref<?x10xi32>
+
+ // CHECK: op=%{{.*}} = memref.cast %{{.*}} {test.recipe_name = #acc.recipe_kind<private_recipe>} : memref<5x10xi32> to memref<?x10xi32>
+ // CHECK-NEXT: getRecipeName(kind=private_recipe, type=memref<?x10xi32>)="privatization_memref_Ux10xi32_"
+
+ return
+}
+
+// -----
+
+// Test private recipe with scalar memref
+func.func @test_private_scalar_memref() {
+ // Create a scalar memref (no dimensions)
+ %0 = memref.alloca() {test.recipe_name = #acc.recipe_kind<private_recipe>} : memref<i32>
+
+ // CHECK: op=%{{.*}} = memref.alloca() {test.recipe_name = #acc.recipe_kind<private_recipe>} : memref<i32>
+ // CHECK-NEXT: getRecipeName(kind=private_recipe, type=memref<i32>)="privatization_memref_i32_"
+
+ return
+}
+
+// -----
+
+// Test private recipe with unranked memref
+func.func @test_private_unranked_memref(%arg0: memref<10xi32>) {
+ // Cast to unranked memref
+ %0 = memref.cast %arg0 {test.recipe_name = #acc.recipe_kind<private_recipe>} : memref<10xi32> to memref<*xi32>
+
+ // CHECK: op=%{{.*}} = memref.cast %{{.*}} {test.recipe_name = #acc.recipe_kind<private_recipe>} : memref<10xi32> to memref<*xi32>
+ // CHECK-NEXT: getRecipeName(kind=private_recipe, type=memref<*xi32>)="privatization_memref_Zxi32_"
+
+ return
+}
+
diff --git a/mlir/test/Dialect/OpenACC/support-analysis-unsupported.mlir b/mlir/test/Dialect/OpenACC/support-analysis-unsupported.mlir
new file mode 100644
index 0000000000000..c4d5b81a1380a
--- /dev/null
+++ b/mlir/test/Dialect/OpenACC/support-analysis-unsupported.mlir
@@ -0,0 +1,18 @@
+// RUN: mlir-opt %s --split-input-file -test-acc-support -verify-diagnostics
+
+// Test emitNYI with a simple message
+func.func @test_emit_nyi() {
+ // expected-error @below {{not yet implemented: Unsupported feature in OpenACC}}
+ %0 = memref.alloca() {test.emit_nyi = "Unsupported feature in OpenACC"} : memref<10xi32>
+ return
+}
+
+// -----
+
+// Test recipe name on load operation from scalar memref
+func.func @test_recipe_load_scalar() {
+ %0 = memref.alloca() : memref<i32>
+ // expected-error @below {{not yet implemented: variable privatization (incomplete recipe name handling)}}
+ %1 = memref.load %0[] {test.recipe_name = #acc.recipe_kind<private_recipe>} : memref<i32>
+ return
+}
diff --git a/mlir/test/lib/Dialect/OpenACC/TestOpenACCSupport.cpp b/mlir/test/lib/Dialect/OpenACC/TestOpenACCSupport.cpp
index 8bf984bdc2632..7c8b08489c62e 100644
--- a/mlir/test/lib/Dialect/OpenACC/TestOpenACCSupport.cpp
+++ b/mlir/test/lib/Dialect/OpenACC/TestOpenACCSupport.cpp
@@ -57,6 +57,28 @@ void TestOpenACCSupportPass::runOnOperation() {
<< "\"\n";
}
}
+
+ // Check for test.recipe_name attribute. This is the marker used to identify
+ // the operations that need to be tested for getRecipeName.
+ if (auto recipeAttr =
+ op->getAttrOfType<RecipeKindAttr>("test.recipe_name")) {
+ RecipeKind kind = recipeAttr.getValue();
+ // Get the type from the first result if available
+ if (op->getNumResults() > 0) {
+ Type type = op->getResult(0).getType();
+ std::string recipeName =
+ support.getRecipeName(kind, type, op->getResult(0));
+ llvm::outs() << "op=" << *op
+ << "\n\tgetRecipeName(kind=" << stringifyRecipeKind(kind)
+ << ", type=" << type << ")=\"" << recipeName << "\"\n";
+ }
+ }
+
+ // Check for test.emit_nyi attribute. This is the marker used to
+ // test whether the not yet implemented case is reported correctly.
+ if (auto messageAttr = op->getAttrOfType<StringAttr>("test.emit_nyi")) {
+ support.emitNYI(op->getLoc(), messageAttr.getValue());
+ }
});
}
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp
index 3fbbcc90a67c9..f1fe53c15a6f5 100644
--- a/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp
@@ -485,3 +485,88 @@ TEST_F(OpenACCUtilsTest, getVariableNameFromCopyin) {
std::string varName = getVariableName(copyinOp->getAccVar());
EXPECT_EQ(varName, name);
}
+
+//===----------------------------------------------------------------------===//
+// getRecipeName Tests
+//===----------------------------------------------------------------------===//
+
+TEST_F(OpenACCUtilsTest, getRecipeNamePrivateScalarMemref) {
+ // Create a scalar memref type
+ auto scalarMemrefTy = MemRefType::get({}, b.getI32Type());
+
+ // Test private recipe with scalar memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::private_recipe, scalarMemrefTy);
+ EXPECT_EQ(recipeName, "privatization_memref_i32_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNameFirstprivateScalarMemref) {
+ // Create a scalar memref type
+ auto scalarMemrefTy = MemRefType::get({}, b.getF32Type());
+
+ // Test firstprivate recipe with scalar memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::firstprivate_recipe, scalarMemrefTy);
+ EXPECT_EQ(recipeName, "firstprivatization_memref_f32_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNameReductionScalarMemref) {
+ // Create a scalar memref type
+ auto scalarMemrefTy = MemRefType::get({}, b.getI64Type());
+
+ // Test reduction recipe with scalar memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::reduction_recipe, scalarMemrefTy);
+ EXPECT_EQ(recipeName, "reduction_memref_i64_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNamePrivate2DMemref) {
+ // Create a 2D memref type
+ auto memref2DTy = MemRefType::get({5, 10}, b.getF32Type());
+
+ // Test private recipe with 2D memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::private_recipe, memref2DTy);
+ EXPECT_EQ(recipeName, "privatization_memref_5x10xf32_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNameFirstprivate2DMemref) {
+ // Create a 2D memref type
+ auto memref2DTy = MemRefType::get({8, 16}, b.getF64Type());
+
+ // Test firstprivate recipe with 2D memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::firstprivate_recipe, memref2DTy);
+ EXPECT_EQ(recipeName, "firstprivatization_memref_8x16xf64_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNameReduction2DMemref) {
+ // Create a 2D memref type
+ auto memref2DTy = MemRefType::get({4, 8}, b.getI32Type());
+
+ // Test reduction recipe with 2D memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::reduction_recipe, memref2DTy);
+ EXPECT_EQ(recipeName, "reduction_memref_4x8xi32_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNamePrivateDynamicMemref) {
+ // Create a memref with dynamic dimensions
+ auto dynamicMemrefTy =
+ MemRefType::get({ShapedType::kDynamic, 10}, b.getI32Type());
+
+ // Test private recipe with dynamic memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::private_recipe, dynamicMemrefTy);
+ EXPECT_EQ(recipeName, "privatization_memref_Ux10xi32_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNamePrivateUnrankedMemref) {
+ // Create an unranked memref type
+ auto unrankedMemrefTy = UnrankedMemRefType::get(b.getI32Type(), 0);
+
+ // Test private recipe with unranked memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::private_recipe, unrankedMemrefTy);
+ EXPECT_EQ(recipeName, "privatization_memref_Zxi32_");
+}
More information about the Mlir-commits
mailing list