[Mlir-commits] [mlir] [mlir][acc] Support lazy remark message construction (PR #180665)
Razvan Lupusoru
llvmlistbot at llvm.org
Mon Feb 9 18:02:39 PST 2026
https://github.com/razvanlupusoru updated https://github.com/llvm/llvm-project/pull/180665
>From 3124661278134d19e6b9393c74430be0bff3624b Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Mon, 9 Feb 2026 17:57:58 -0800
Subject: [PATCH 1/2] [mlir][acc] Support lazy remark message construction
The OpenACC remark emission utilities previously only accepted Twine
for message construction. However, complex remarks often require
additional logic to build messages, such as resolving variable
names. This results in unnecessary work when remarks are disabled.
Add an overload that accepts a lambda for message generation,
which is only invoked when remark emission is enabled. Update
ACCLoopTiling to use this lazy API for tile size reporting.
Additionally, getVariableName now returns numeric strings for
constant integer values. This is also being used by ACCLoopTiling
along with the lazy remark update.
---
.../Dialect/OpenACC/Analysis/OpenACCSupport.h | 39 ++++++++++++----
.../mlir/Dialect/OpenACC/OpenACCUtils.h | 25 +++++++++--
.../OpenACC/Analysis/OpenACCSupport.cpp | 7 +--
.../OpenACC/Transforms/ACCLoopTiling.cpp | 45 +++++++++++--------
.../Dialect/OpenACC/Utils/OpenACCUtils.cpp | 10 ++++-
.../Dialect/OpenACC/OpenACCUtilsTest.cpp | 24 ++++++++++
6 files changed, 115 insertions(+), 35 deletions(-)
diff --git a/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h b/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
index c49452556f0c4..6cceb704bca4e 100644
--- a/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
+++ b/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
@@ -55,6 +55,7 @@
#include "mlir/IR/Value.h"
#include "mlir/Pass/AnalysisManager.h"
#include "llvm/ADT/StringRef.h"
+#include <functional>
#include <memory>
#include <string>
@@ -85,7 +86,7 @@ struct OpenACCSupportTraits {
// emitted. When not provided, in the default implementation, the category
// is "openacc".
virtual remark::detail::InFlightRemark
- emitRemark(Operation *op, const Twine &message,
+ emitRemark(Operation *op, std::function<std::string()> messageFn,
llvm::StringRef category) = 0;
/// Check if a symbol use is valid for use in an OpenACC region.
@@ -120,8 +121,9 @@ struct OpenACCSupportTraits {
decltype(std::declval<ImplT>().emitRemark(std::declval<Args>()...));
template <typename ImplT>
- using has_emitRemark = llvm::is_detected<emitRemark_t, ImplT, Operation *,
- const Twine &, llvm::StringRef>;
+ using has_emitRemark =
+ llvm::is_detected<emitRemark_t, ImplT, Operation *,
+ std::function<std::string()>, llvm::StringRef>;
/// This class wraps a concrete OpenACCSupport implementation and forwards
/// interface calls to it. This provides type erasure, allowing different
@@ -146,13 +148,13 @@ struct OpenACCSupportTraits {
return impl.emitNYI(loc, message);
}
- remark::detail::InFlightRemark emitRemark(Operation *op,
- const Twine &message,
- llvm::StringRef category) final {
+ remark::detail::InFlightRemark
+ emitRemark(Operation *op, std::function<std::string()> messageFn,
+ llvm::StringRef category) final {
if constexpr (has_emitRemark<ImplT>::value)
- return impl.emitRemark(op, message, category);
+ return impl.emitRemark(op, std::move(messageFn), category);
else
- return acc::emitRemark(op, message, category);
+ return acc::emitRemark(op, messageFn(), category);
}
bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol,
@@ -222,6 +224,21 @@ class OpenACCSupport {
/// unsupported case.
InFlightDiagnostic emitNYI(Location loc, const Twine &message);
+ /// Emit an OpenACC remark with lazy message generation.
+ ///
+ /// The messageFn is only invoked if remarks are enabled for the given
+ /// operation, allowing callers to avoid constructing expensive messages
+ /// when remarks are disabled.
+ ///
+ /// \param op The operation to emit the remark for.
+ /// \param messageFn A callable that returns the remark message.
+ /// \param category Optional category for the remark. Defaults to "openacc".
+ /// \return An in-flight remark object that can be used to append
+ /// additional information to the remark.
+ remark::detail::InFlightRemark
+ emitRemark(Operation *op, std::function<std::string()> messageFn,
+ llvm::StringRef category = "openacc");
+
/// Emit an OpenACC remark.
///
/// \param op The operation to emit the remark for.
@@ -231,7 +248,11 @@ class OpenACCSupport {
/// additional information to the remark.
remark::detail::InFlightRemark
emitRemark(Operation *op, const Twine &message,
- llvm::StringRef category = "openacc");
+ llvm::StringRef category = "openacc") {
+ return emitRemark(
+ op, std::function<std::string()>([msg = message.str()]() { return msg; }),
+ category);
+ }
/// Check if a symbol use is valid for use in an OpenACC region.
///
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h b/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h
index a436050babce2..aac3bf7ed67c8 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCUtils.h
@@ -13,6 +13,7 @@
#include "mlir/IR/Remarks.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include <functional>
namespace mlir {
class DominanceInfo;
@@ -100,6 +101,20 @@ getDominatingDataClauses(mlir::Operation *computeConstructOp,
mlir::DominanceInfo &domInfo,
mlir::PostDominanceInfo &postDomInfo);
+/// Emit an OpenACC remark with lazy message generation.
+///
+/// The messageFn is only invoked if remarks are enabled, allowing callers
+/// to avoid constructing expensive messages when remarks are disabled.
+///
+/// \param op The operation to emit the remark for.
+/// \param messageFn A callable that returns the remark message.
+/// \param category Optional category for the remark. Defaults to "openacc".
+/// \return An in-flight remark object that can be used to append
+/// additional information to the remark.
+remark::detail::InFlightRemark
+emitRemark(mlir::Operation *op, const std::function<std::string()> &messageFn,
+ llvm::StringRef category = "openacc");
+
/// Emit an OpenACC remark for the given operation with the given message.
///
/// \param op The operation to emit the remark for.
@@ -107,9 +122,13 @@ getDominatingDataClauses(mlir::Operation *computeConstructOp,
/// \param category Optional category for the remark. Defaults to "openacc".
/// \return An in-flight remark object that can be used to append
/// additional information to the remark.
-remark::detail::InFlightRemark emitRemark(mlir::Operation *op,
- const llvm::Twine &message,
- llvm::StringRef category = "openacc");
+inline remark::detail::InFlightRemark
+emitRemark(mlir::Operation *op, const llvm::Twine &message,
+ llvm::StringRef category = "openacc") {
+ return emitRemark(
+ op, std::function<std::string()>([msg = message.str()]() { return msg; }),
+ category);
+}
} // namespace acc
} // namespace mlir
diff --git a/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp b/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp
index 4fbe3e06c2532..f204ace4609ab 100644
--- a/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp
+++ b/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp
@@ -42,11 +42,12 @@ InFlightDiagnostic OpenACCSupport::emitNYI(Location loc, const Twine &message) {
}
remark::detail::InFlightRemark
-OpenACCSupport::emitRemark(Operation *op, const Twine &message,
+OpenACCSupport::emitRemark(Operation *op,
+ std::function<std::string()> messageFn,
llvm::StringRef category) {
if (impl)
- return impl->emitRemark(op, message, category);
- return acc::emitRemark(op, message, category);
+ return impl->emitRemark(op, std::move(messageFn), category);
+ return acc::emitRemark(op, messageFn(), category);
}
bool OpenACCSupport::isValidSymbolUse(Operation *user, SymbolRefAttr symbol,
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCLoopTiling.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCLoopTiling.cpp
index 23bec6a295061..495d0247d86d3 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCLoopTiling.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCLoopTiling.cpp
@@ -63,6 +63,7 @@
#include "mlir/IR/PatternMatch.h"
#include "mlir/Support/LLVM.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
namespace mlir {
@@ -117,30 +118,38 @@ struct ACCLoopTilingImpl : public OpRewritePattern<acc::LoopOp> {
void emitTilingRemarks(acc::LoopOp loop, ArrayRef<Value> tileSizes) const {
// Emit remarks for loop tiling
- size_t tileLevel = tileSizes.size();
- std::string msg =
- "Tiling " + std::to_string(tileLevel) + "-level loop nest with tile(";
- for (size_t i = 0; i < tileSizes.size(); ++i) {
- std::optional<int64_t> val = getConstantIntValue(tileSizes[i]);
- if (*val == -1)
- msg += "*";
- else
- msg += std::to_string(*val);
- if (i < tileSizes.size() - 1)
- msg += ",";
- }
- msg += ")";
- accSupport.emitRemark(loop, llvm::Twine(msg), DEBUG_TYPE);
+ accSupport.emitRemark(
+ loop,
+ [&]() {
+ auto getTileSizeStr = [&](Value v) -> std::string {
+ std::string name = accSupport.getVariableName(v);
+ // Use "*" for unknown tile sizes (represented as -1 or empty)
+ if (name.empty() || name == "-1")
+ return "*";
+ return name;
+ };
+ SmallVector<std::string> tileStrs;
+ for (Value v : tileSizes)
+ tileStrs.push_back(getTileSizeStr(v));
+ return "Tiling " + std::to_string(tileSizes.size()) +
+ "-level loop nest with tile(" + llvm::join(tileStrs, ",") +
+ ")";
+ },
+ DEBUG_TYPE);
// Emit remarks for unknown tile sizes that will be resolved to default
// TODO: Need to base the default tile size on some heuristics.
for (Value tileSize : tileSizes) {
std::optional<int64_t> val = getConstantIntValue(tileSize);
if (val && *val < 0) {
- std::string unknownMsg = "Picking default tile size " +
- std::to_string(defaultTileSize) +
- " for unknown tile size '*'";
- accSupport.emitRemark(loop, llvm::Twine(unknownMsg), DEBUG_TYPE);
+ accSupport.emitRemark(
+ loop,
+ [&]() {
+ return "Picking default tile size " +
+ std::to_string(defaultTileSize) +
+ " for unknown tile size '*'";
+ },
+ DEBUG_TYPE);
}
}
}
diff --git a/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp b/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp
index 26243b2ae84be..6e5ec0ccd1210 100644
--- a/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp
+++ b/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtils.cpp
@@ -9,6 +9,7 @@
#include "mlir/Dialect/OpenACC/OpenACCUtils.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/Dialect/Utils/StaticValueUtils.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dominance.h"
#include "mlir/IR/SymbolTable.h"
@@ -92,6 +93,10 @@ std::string mlir::acc::getVariableName(mlir::Value v) {
// Walk through view operations until a name is found or can't go further
while (Operation *definingOp = current.getDefiningOp()) {
+ // For integer constants, return their value as a string.
+ if (std::optional<int64_t> constVal = getConstantIntValue(current))
+ return std::to_string(*constVal);
+
// Check for `acc.var_name` attribute
if (auto varNameAttr =
definingOp->getAttrOfType<VarNameAttr>(getVarNameAttrName()))
@@ -331,7 +336,8 @@ mlir::acc::getDominatingDataClauses(mlir::Operation *computeConstructOp,
}
mlir::remark::detail::InFlightRemark
-mlir::acc::emitRemark(mlir::Operation *op, const llvm::Twine &message,
+mlir::acc::emitRemark(mlir::Operation *op,
+ const std::function<std::string()> &messageFn,
llvm::StringRef category) {
using namespace mlir::remark;
mlir::Location loc = op->getLoc();
@@ -351,6 +357,6 @@ mlir::acc::emitRemark(mlir::Operation *op, const llvm::Twine &message,
auto remark = engine->emitOptimizationRemark(loc, opts);
if (remark)
- remark << message.str();
+ remark << messageFn();
return remark;
}
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp
index 56cc2b9d9ba0b..489fe9108c04e 100644
--- a/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp
@@ -488,6 +488,30 @@ TEST_F(OpenACCUtilsTest, getVariableNameFromCopyin) {
EXPECT_EQ(varName, name);
}
+TEST_F(OpenACCUtilsTest, getVariableNameConstantInt) {
+ // Create a constant integer value
+ OwningOpRef<arith::ConstantOp> constOp =
+ arith::ConstantOp::create(b, loc, b.getI64IntegerAttr(42));
+
+ Value constVal = constOp->getResult();
+
+ // Test that getVariableName returns the constant value as a string
+ std::string varName = getVariableName(constVal);
+ EXPECT_EQ(varName, "42");
+}
+
+TEST_F(OpenACCUtilsTest, getVariableNameNegativeConstantInt) {
+ // Create a negative constant integer value
+ OwningOpRef<arith::ConstantOp> constOp =
+ arith::ConstantOp::create(b, loc, b.getI64IntegerAttr(-123));
+
+ Value constVal = constOp->getResult();
+
+ // Test that getVariableName returns the negative constant value as a string
+ std::string varName = getVariableName(constVal);
+ EXPECT_EQ(varName, "-123");
+}
+
//===----------------------------------------------------------------------===//
// getRecipeName Tests
//===----------------------------------------------------------------------===//
>From e5c6f66ad33f780dfa0e8ad7523ffdd3126a2447 Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Mon, 9 Feb 2026 18:02:28 -0800
Subject: [PATCH 2/2] Fix format
---
.../include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h b/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
index 6cceb704bca4e..31ef05c2f1743 100644
--- a/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
+++ b/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
@@ -249,9 +249,10 @@ class OpenACCSupport {
remark::detail::InFlightRemark
emitRemark(Operation *op, const Twine &message,
llvm::StringRef category = "openacc") {
- return emitRemark(
- op, std::function<std::string()>([msg = message.str()]() { return msg; }),
- category);
+ return emitRemark(op, std::function<std::string()>([msg = message.str()]() {
+ return msg;
+ }),
+ category);
}
/// Check if a symbol use is valid for use in an OpenACC region.
More information about the Mlir-commits
mailing list