[Mlir-commits] [mlir] [OpenACC] Add pass `ACCEmitRemarksPrivate`. (PR #205824)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Jun 25 07:25:51 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-openacc
Author: Moazin K. (moazin)
<details>
<summary>Changes</summary>
The pass emits remarks describing `acc.firstprivate` and `acc.private` associated with OpenACC compute and loop constructs.
Assisted-by: Claude Code
---
Full diff: https://github.com/llvm/llvm-project/pull/205824.diff
4 Files Affected:
- (modified) mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.td (+14)
- (added) mlir/lib/Dialect/OpenACC/Transforms/ACCEmitRemarksPrivate.cpp (+99)
- (modified) mlir/lib/Dialect/OpenACC/Transforms/CMakeLists.txt (+1)
- (added) mlir/test/Dialect/OpenACC/acc-emit-remarks-private.mlir (+119)
``````````diff
diff --git a/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.td b/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.td
index e35e38adceb02..b52dee12d390a 100644
--- a/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.td
@@ -193,6 +193,20 @@ def ACCEmitRemarksLoop : Pass<"acc-emit-remarks-loop", "mlir::func::FuncOp"> {
];
}
+def ACCEmitRemarksPrivate
+ : Pass<"acc-emit-remarks-private", "mlir::func::FuncOp"> {
+ let summary = "Emit OpenACC private and firstprivate remarks";
+ let description = [{
+ This pass emits optimization remarks describing the private and firstprivate
+ variables associated with OpenACC compute and loop constructs.
+
+ The pass walks compute constructs and `acc.loop` operations and, for each,
+ reports the implicit and explicit `private` and `firstprivate` variables it
+ carries.
+ }];
+ let dependentDialects = ["mlir::acc::OpenACCDialect"];
+}
+
def ACCLoopTiling : Pass<"acc-loop-tiling", "mlir::func::FuncOp"> {
let summary = "Tile OpenACC loops with tile clauses";
let description = [{
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCEmitRemarksPrivate.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCEmitRemarksPrivate.cpp
new file mode 100644
index 0000000000000..119ee9cecd77a
--- /dev/null
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCEmitRemarksPrivate.cpp
@@ -0,0 +1,99 @@
+//===- ACCEmitRemarksPrivate.cpp - Emit OpenACC privatization remarks ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass emits remarks describing the private and firstprivate variables
+// associated with OpenACC compute and loop constructs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/Dialect/OpenACC/Transforms/Passes.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/TypeSwitch.h"
+
+namespace mlir {
+namespace acc {
+#define GEN_PASS_DEF_ACCEMITREMARKSPRIVATE
+#include "mlir/Dialect/OpenACC/Transforms/Passes.h.inc"
+} // namespace acc
+} // namespace mlir
+
+#define DEBUG_TYPE "acc-emit-remarks-private"
+
+using namespace mlir;
+
+namespace {
+
+template <typename OpTy>
+static void reportPrivatization(Operation *accOp, ValueRange operands,
+ acc::OpenACCSupport &accSupport,
+ StringRef clause) {
+ SmallVector<std::string> implicitNames;
+ SmallVector<std::string> explicitNames;
+ for (Value operand : operands) {
+ auto op = cast<OpTy>(operand.getDefiningOp());
+ std::string varName = accSupport.getVariableName(op.getAccVar());
+ (op.getImplicit() ? implicitNames : explicitNames)
+ .push_back(varName.empty() ? "<unknown>" : varName);
+ }
+
+ if (!implicitNames.empty())
+ accSupport.emitRemark(
+ accOp,
+ [clause, names = std::move(implicitNames)]() {
+ return (Twine("Generating implicit ") + clause + "(" +
+ llvm::join(names, ",") + ")")
+ .str();
+ },
+ DEBUG_TYPE);
+
+ if (!explicitNames.empty())
+ accSupport.emitRemark(
+ accOp,
+ [clause, names = std::move(explicitNames)]() {
+ return (Twine("Generating ") + clause + "(" + llvm::join(names, ",") +
+ ")")
+ .str();
+ },
+ DEBUG_TYPE);
+}
+
+template <typename OpTy>
+static void emitRemarksForACCOp(OpTy accOp, acc::OpenACCSupport &accSupport) {
+ reportPrivatization<acc::FirstprivateOp>(
+ accOp, accOp.getFirstprivateOperands(), accSupport, "firstprivate");
+ reportPrivatization<acc::PrivateOp>(accOp, accOp.getPrivateOperands(),
+ accSupport, "private");
+}
+
+class ACCEmitRemarksPrivate
+ : public acc::impl::ACCEmitRemarksPrivateBase<ACCEmitRemarksPrivate> {
+public:
+ using ACCEmitRemarksPrivateBase<
+ ACCEmitRemarksPrivate>::ACCEmitRemarksPrivateBase;
+
+ void runOnOperation() override {
+ func::FuncOp func = getOperation();
+
+ auto cachedAnalysis = getCachedParentAnalysis<acc::OpenACCSupport>();
+ acc::OpenACCSupport &accSupport =
+ cachedAnalysis ? cachedAnalysis->get()
+ : getAnalysis<acc::OpenACCSupport>();
+
+ func.walk([&](Operation *op) {
+ TypeSwitch<Operation *>(op).Case<ACC_COMPUTE_CONSTRUCT_AND_LOOP_OPS>(
+ [&](auto constructOp) { emitRemarksForACCOp(constructOp, accSupport); }
+ );
+ });
+ }
+};
+
+} // namespace
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/CMakeLists.txt b/mlir/lib/Dialect/OpenACC/Transforms/CMakeLists.txt
index 2ae3571673469..d977028c283e6 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/OpenACC/Transforms/CMakeLists.txt
@@ -5,6 +5,7 @@ add_mlir_dialect_library(MLIROpenACCTransforms
ACCRoutineToGPUFunc.cpp
ACCDeclareGPUModuleInsertion.cpp
ACCEmitRemarksLoop.cpp
+ ACCEmitRemarksPrivate.cpp
ACCIfClauseLowering.cpp
ACCImplicitData.cpp
ACCRecipeMaterialization.cpp
diff --git a/mlir/test/Dialect/OpenACC/acc-emit-remarks-private.mlir b/mlir/test/Dialect/OpenACC/acc-emit-remarks-private.mlir
new file mode 100644
index 0000000000000..b388ad51208a2
--- /dev/null
+++ b/mlir/test/Dialect/OpenACC/acc-emit-remarks-private.mlir
@@ -0,0 +1,119 @@
+// RUN: mlir-opt %s -acc-emit-remarks-private --remarks-filter="(open)?acc.*" 2>&1 | FileCheck %s
+
+// CHECK: remark: [Passed] openacc | Category:acc-emit-remarks-private | Function=firstpriv_implicit | Remark="Generating implicit firstprivate(t)"
+// CHECK: remark: [Passed] openacc | Category:acc-emit-remarks-private | Function=firstpriv_explicit | Remark="Generating firstprivate(t)"
+// CHECK: remark: [Passed] openacc | Category:acc-emit-remarks-private | Function=private_loop_implicit | Remark="Generating implicit private(x)"
+// CHECK: remark: [Passed] openacc | Category:acc-emit-remarks-private | Function=private_loop_unknown | Remark="Generating implicit private(<unknown>)"
+// CHECK: remark: [Passed] openacc | Category:acc-emit-remarks-private | Function=private_explicit | Remark="Generating private(x)"
+// CHECK: remark: [Passed] openacc | Category:acc-emit-remarks-private | Function=multi_private_implicit | Remark="Generating implicit private(a,b)"
+
+acc.firstprivate.recipe @firstprivatization_memref_i32 : memref<i32> init {
+^bb0(%arg0: memref<i32>):
+ %0 = memref.alloca() : memref<i32>
+ acc.yield %0 : memref<i32>
+} copy {
+^bb0(%arg0: memref<i32>, %arg1: memref<i32>):
+ %0 = memref.load %arg0[] : memref<i32>
+ memref.store %0, %arg1[] : memref<i32>
+ acc.terminator
+} destroy {
+^bb0(%arg0: memref<i32>, %arg1: memref<i32>):
+ memref.dealloc %arg1 : memref<i32>
+ acc.terminator
+}
+
+acc.private.recipe @privatization_memref_i64 : memref<i64> init {
+^bb0(%arg0: memref<i64>):
+ %0 = memref.alloca() : memref<i64>
+ acc.yield %0 : memref<i64>
+} destroy {
+^bb0(%arg0: memref<i64>, %arg1: memref<i64>):
+ memref.dealloc %arg1 : memref<i64>
+ acc.terminator
+}
+
+// CHECK-LABEL: func.func @firstpriv_implicit
+// CHECK: acc.firstprivate
+// CHECK: acc.parallel firstprivate
+func.func @firstpriv_implicit() {
+ %c1336 = arith.constant 1336 : i32
+ %alloc = memref.alloca() : memref<i32>
+ memref.store %c1336, %alloc[] : memref<i32>
+ %fp = acc.firstprivate varPtr(%alloc : memref<i32>) recipe(@firstprivatization_memref_i32) -> memref<i32> {implicit = true, name = "t"}
+ acc.parallel firstprivate(%fp : memref<i32>) {
+ %c1 = arith.constant 1 : i32
+ %v = memref.load %fp[] : memref<i32>
+ %add = arith.addi %v, %c1 : i32
+ memref.store %add, %fp[] : memref<i32>
+ acc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: func.func @firstpriv_explicit
+func.func @firstpriv_explicit() {
+ %c1336 = arith.constant 1336 : i32
+ %alloc = memref.alloca() : memref<i32>
+ memref.store %c1336, %alloc[] : memref<i32>
+ %fp = acc.firstprivate varPtr(%alloc : memref<i32>) recipe(@firstprivatization_memref_i32) -> memref<i32> {name = "t"}
+ acc.parallel firstprivate(%fp : memref<i32>) {
+ %c1 = arith.constant 1 : i32
+ %v = memref.load %fp[] : memref<i32>
+ %add = arith.addi %v, %c1 : i32
+ memref.store %add, %fp[] : memref<i32>
+ acc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: func.func @private_loop_implicit
+func.func @private_loop_implicit(%arg0 : memref<i64>) {
+ %c16 = arith.constant 16 : index
+ %c1 = arith.constant 1 : index
+ %priv = acc.private varPtr(%arg0 : memref<i64>) recipe(@privatization_memref_i64) -> memref<i64> {implicit = true, name = "x"}
+ acc.loop private(%priv : memref<i64>) control(%siv : index) = (%c1 : index) to (%c16 : index) step (%c1 : index) {
+ %iv_i64 = arith.index_cast %siv : index to i64
+ memref.store %iv_i64, %priv[] : memref<i64>
+ acc.yield
+ } attributes {independent = [#acc.device_type<none>]}
+ return
+}
+
+// CHECK-LABEL: func.func @private_loop_unknown
+func.func @private_loop_unknown(%arg0 : memref<i64>) {
+ %c16 = arith.constant 16 : index
+ %c1 = arith.constant 1 : index
+ %priv = acc.private varPtr(%arg0 : memref<i64>) recipe(@privatization_memref_i64) -> memref<i64> {implicit = true, name = ""}
+ acc.loop private(%priv : memref<i64>) control(%siv : index) = (%c1 : index) to (%c16 : index) step (%c1 : index) {
+ %iv_i64 = arith.index_cast %siv : index to i64
+ memref.store %iv_i64, %priv[] : memref<i64>
+ acc.yield
+ } attributes {independent = [#acc.device_type<none>]}
+ return
+}
+
+// CHECK-LABEL: func.func @private_explicit
+func.func @private_explicit(%arg0 : memref<i64>) {
+ %c16 = arith.constant 16 : index
+ %c1 = arith.constant 1 : index
+ %priv = acc.private varPtr(%arg0 : memref<i64>) recipe(@privatization_memref_i64) -> memref<i64> {name = "x"}
+ acc.parallel private(%priv : memref<i64>) {
+ acc.loop control(%siv : index) = (%c1 : index) to (%c16 : index) step (%c1 : index) {
+ %iv_i64 = arith.index_cast %siv : index to i64
+ memref.store %iv_i64, %priv[] : memref<i64>
+ acc.yield
+ } attributes {independent = [#acc.device_type<none>]}
+ acc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: func.func @multi_private_implicit
+func.func @multi_private_implicit(%arg0 : memref<i64>, %arg1 : memref<i64>) {
+ %privA = acc.private varPtr(%arg0 : memref<i64>) recipe(@privatization_memref_i64) -> memref<i64> {implicit = true, name = "a"}
+ %privB = acc.private varPtr(%arg1 : memref<i64>) recipe(@privatization_memref_i64) -> memref<i64> {implicit = true, name = "b"}
+ acc.parallel private(%privA, %privB : memref<i64>, memref<i64>) {
+ acc.yield
+ }
+ return
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/205824
More information about the Mlir-commits
mailing list