[Mlir-commits] [mlir] [OpenACC] Propagate variable names to ops after materializing recipes. (PR #205821)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Jun 25 07:11:45 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-openacc
@llvm/pr-subscribers-mlir
Author: Moazin K. (moazin)
<details>
<summary>Changes</summary>
ACCRecipeMaterialization only attaches names to the result of the recipe being materialized. However, some recipes produce multiple ops that need to carry the variable name.
This change introduces `acc::getVarNamePlaceholder()`, a placeholder value for `acc.var_name`. Implementations can attach this placeholder while building the recipe to any ops that should carry the variable name. ACCRecipeMaterialization will then replace the placeholder with the actual variable name while materializing the recipe.
Assisted-by: Claude Code
---
Full diff: https://github.com/llvm/llvm-project/pull/205821.diff
5 Files Affected:
- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td (+6)
- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h (+10)
- (modified) mlir/lib/Dialect/OpenACC/Transforms/ACCRecipeMaterialization.cpp (+18)
- (modified) mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp (+4)
- (added) mlir/test/Dialect/OpenACC/acc-recipe-materialization-firstprivate-two-allocs.mlir (+35)
``````````diff
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
index 37af4a4744839..bbc145777b295 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
@@ -440,6 +440,12 @@ def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
should invoke `generatePrivateDestroy` in the recipe's destroy region
with the privatized value returned by this method.
+ Implementations that want certain ops to carry the correct variable name
+ post materialization should attach `getVarNamePlaceholder()` as the
+ `acc.var_name` attribute to those ops. `ACCRecipeMaterialization` will
+ replace the placeholder with the actual variable name when inlining the
+ recipe.
+
If the return value is empty, it means that recipe body was not
successfully generated.
}],
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h b/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h
index 68f32ad73a3ba..925eefaf9c365 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h
@@ -61,6 +61,16 @@ mlir::acc::VariableTypeCategory getTypeCategory(mlir::Value var);
/// empty string if no name is found.
std::string getVariableName(mlir::Value v);
+/// Returns a placeholder string for use as an acc.var_name attribute value when
+/// the actual variable name is not yet known at the point of IR construction.
+/// The placeholder is meant to be replaced with the real name at a later
+/// lowering stage.
+/// For example, recipe init regions may attach this to ops at recipe-generation
+/// time, and ACCRecipeMaterialization will subsequently replace the placeholder
+/// with the actual variable name on all marked ops after inlining the recipe
+/// into the compute construct.
+llvm::StringLiteral getVarNamePlaceholder();
+
/// Get the recipe name for a given recipe kind and type.
/// Returns an empty string if not possible to generate a recipe name.
std::string getRecipeName(mlir::acc::RecipeKind kind, mlir::Type type);
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCRecipeMaterialization.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCRecipeMaterialization.cpp
index 41de4702b18df..638379cc9ff70 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCRecipeMaterialization.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCRecipeMaterialization.cpp
@@ -111,6 +111,19 @@ static void saveVarName(Value src, Value dst) {
saveVarName(acc::getVariableName(src), dst);
}
+static void resolveVarNamePlaceholders(Block *block, Block::iterator ip,
+ StringRef name) {
+ if (name.empty())
+ return;
+ StringRef placeholder = acc::getVarNamePlaceholder();
+ for (auto it = block->begin(); it != std::next(ip); ++it) {
+ auto attr = it->getAttrOfType<acc::VarNameAttr>(acc::getVarNameAttrName());
+ if (attr && attr.getName() == placeholder)
+ it->setAttr(acc::getVarNameAttrName(),
+ acc::VarNameAttr::get(it->getContext(), name));
+ }
+}
+
// Clone the destroy region of the recipe before the terminator of the provided
// block. Values must be provided for the destroy region block arguments
// according to the recipe specifications.
@@ -259,6 +272,7 @@ ACCRecipeMaterialization::materialize(OpTy op, RecipeOpTy recipe, AccOpTy accOp,
&initRegion, block, block->begin(), mapping, {accPtr});
assert(results.size() == 1 && "expected single result from init region");
saveVarName(op.getAccVar(), results[0]);
+ resolveVarNamePlaceholders(block, ip, acc::getVariableName(op.getAccVar()));
// Clone the destroy region for a private, if it exists.
if (!recipe.getDestroyRegion().empty()) {
results.insert(results.begin(), origPtr);
@@ -272,6 +286,7 @@ ACCRecipeMaterialization::materialize(OpTy op, RecipeOpTy recipe, AccOpTy accOp,
&initRegion, block, block->begin(), mapping, {accPtr});
assert(results.size() == 1 && "expected single result from init region");
saveVarName(op.getAccVar(), results[0]);
+ resolveVarNamePlaceholders(block, ip, acc::getVariableName(op.getAccVar()));
// We want the copy to store the origPtr to private
results.insert(results.begin(), origPtr);
results.append(triples);
@@ -313,6 +328,9 @@ ACCRecipeMaterialization::materialize(OpTy op, RecipeOpTy recipe, AccOpTy accOp,
saveVarName(op.getAccVar(), reductionOp.getResult());
cloneRegionIntoAccRegion(&initRegion, &reductionOp.getRegion(),
/*hasResult=*/true);
+ Block *initBlock = &reductionOp.getRegion().front();
+ resolveVarNamePlaceholders(initBlock, std::prev(initBlock->end()),
+ acc::getVariableName(op.getAccVar()));
// Update the uses within the loop to use the reduction op result.
replaceAllUsesInRegionWith(accPtr, reductionOp.getResult(), region);
diff --git a/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp b/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp
index f5b2a9bb86aa0..a84898b7678fc 100644
--- a/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp
+++ b/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp
@@ -106,6 +106,10 @@ mlir::acc::VariableTypeCategory mlir::acc::getTypeCategory(mlir::Value var) {
return typeCategory;
}
+llvm::StringLiteral mlir::acc::getVarNamePlaceholder() {
+ return llvm::StringLiteral("<acc.varname.placeholder>");
+}
+
std::string mlir::acc::getVariableName(mlir::Value v) {
Value current = v;
diff --git a/mlir/test/Dialect/OpenACC/acc-recipe-materialization-firstprivate-two-allocs.mlir b/mlir/test/Dialect/OpenACC/acc-recipe-materialization-firstprivate-two-allocs.mlir
new file mode 100644
index 0000000000000..0807e8f5800ab
--- /dev/null
+++ b/mlir/test/Dialect/OpenACC/acc-recipe-materialization-firstprivate-two-allocs.mlir
@@ -0,0 +1,35 @@
+// RUN: mlir-opt %s -acc-recipe-materialization | FileCheck %s
+
+// A recipe with two allocations. Tests if both allocations correctly get
+// the `var_name` attribute applied after materialization.
+
+acc.firstprivate.recipe @firstprivatization_two_allocs : memref<i32> init {
+^bb0(%arg0: memref<i32>):
+ %c42 = arith.constant 42 : i32
+ %0 = memref.alloca() {acc.var_name = #acc.var_name<"<acc.varname.placeholder>">} : memref<i32>
+ memref.store %c42, %0[] : memref<i32>
+ %1 = memref.alloca() {acc.var_name = #acc.var_name<"<acc.varname.placeholder>">} : memref<i32>
+ %v = memref.load %0[] : memref<i32>
+ memref.store %v, %1[] : memref<i32>
+ acc.yield %1 : memref<i32>
+} copy {
+^bb0(%arg0: memref<i32>, %arg1: memref<i32>):
+ %0 = memref.load %arg0[] : memref<i32>
+ memref.store %0, %arg1[] : memref<i32>
+ acc.terminator
+}
+
+// CHECK-LABEL: func.func @firstpriv_two_allocs
+// CHECK: acc.parallel {
+// CHECK: %[[ALLOC0:.*]] = memref.alloca() {acc.var_name = #acc.var_name<"t">} : memref<i32>
+// CHECK: %[[ALLOC1:.*]] = memref.alloca() {acc.var_name = #acc.var_name<"t">} : memref<i32>
+// CHECK-NOT: acc.varname.placeholder
+
+func.func @firstpriv_two_allocs() {
+ %alloc = memref.alloca() : memref<i32>
+ %fp = acc.firstprivate varPtr(%alloc : memref<i32>) recipe(@firstprivatization_two_allocs) -> memref<i32> {name = "t"}
+ acc.parallel firstprivate(%fp : memref<i32>) {
+ acc.yield
+ }
+ return
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/205821
More information about the Mlir-commits
mailing list