[Mlir-commits] [llvm] [mlir] Introduce a "log level" support for DEBUG_TYPE (PR #150855)
Mehdi Amini
llvmlistbot at llvm.org
Sun Jul 27 16:13:55 PDT 2025
https://github.com/joker-eph updated https://github.com/llvm/llvm-project/pull/150855
>From a7b3c62286f7093e1436ac36b939c076ad3fa97e Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sun, 27 Jul 2025 14:57:26 -0700
Subject: [PATCH 1/6] Introduce a "log level" support for DEBUG_TYPE
This allows to set an optional integer level for a given debug type.
The string format is `type[:level]`, and the integer is interpreted
as such:
- if 0 (default): all debugging for this debug type is enabled.
- if -1: all debug for this debug type is disabled
- if >0: all debug that is < to the level is enabled.
This means that when checking which level is enabled, 0 and 1 are identical.
The LDBG() macro is updated to accept an optional log level to illustrate
the feature. Here is the expected behavior:
LDBG() << "A";
LDBG(2) << "B";
With `--debug-only=some_type`: we'll see A and B in the output.
With `--debug-only=some_type:-1`: we'll see neither A not B in the output.
With `--debug-only=some_type:1`: we'll see A but not B in the output.
With `--debug-only=some_type:2`: we'll see A and B in the output.
(same with any level above 2)
Note that LDBG() is equivalent to LDBG(0) which is equivalent to LDBG(1).
---
llvm/include/llvm/Support/Debug.h | 11 ++--
llvm/include/llvm/Support/DebugLog.h | 69 +++++++++++++++++++------
llvm/lib/Support/Debug.cpp | 55 ++++++++++++++++----
llvm/unittests/Support/DebugLogTest.cpp | 35 ++++++++++---
4 files changed, 134 insertions(+), 36 deletions(-)
diff --git a/llvm/include/llvm/Support/Debug.h b/llvm/include/llvm/Support/Debug.h
index 924d7b216438e..2ce0bda3bdbbf 100644
--- a/llvm/include/llvm/Support/Debug.h
+++ b/llvm/include/llvm/Support/Debug.h
@@ -39,13 +39,18 @@ class raw_ostream;
/// isCurrentDebugType - Return true if the specified string is the debug type
/// specified on the command line, or if none was specified on the command line
/// with the -debug-only=X option.
-///
-bool isCurrentDebugType(const char *Type);
+/// An optional level can be provided to control the verbosity of the output.
+/// If the provided level is not 0 and user specified a level below the provided
+/// level, the output is disabled.
+bool isCurrentDebugType(const char *Type, int Level = 0);
/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X
/// option were specified. Note that DebugFlag also needs to be set to true for
/// debug output to be produced.
-///
+/// The debug type format is "type[:level]", where the level is an optional
+/// integer. The default level is 0, which is the most verbose.
+/// The level can be set to 1, 2, 3, etc. to control the verbosity of the
+/// output. The level can be set to -1 to disable the output.
void setCurrentDebugType(const char *Type);
/// setCurrentDebugTypes - Set the current debug type, as if the
diff --git a/llvm/include/llvm/Support/DebugLog.h b/llvm/include/llvm/Support/DebugLog.h
index 19d309865bbd4..453d0e265876f 100644
--- a/llvm/include/llvm/Support/DebugLog.h
+++ b/llvm/include/llvm/Support/DebugLog.h
@@ -19,29 +19,65 @@
namespace llvm {
#ifndef NDEBUG
-// Output with given inputs and trailing newline. E.g.,
+// LDBG() is a macro that can be used as a raw_ostream for debugging.
+// It will stream the output to the dbgs() stream, with a prefix of the
+// debug type and the file and line number. A trailing newline is added to the
+// output automatically. If the streamed content contains a newline, the prefix
+// is added to each beginning of a new line. Nothing is printed if the debug
+// output is not enabled or the debug type does not match.
+//
+// An optional `level` argument can be provided to control the verbosity of the
+// output. The default level is 0, which is the most verbose. The level can be
+// set to 1, 2, 3, etc. to control the verbosity of the output.
+//
+// The `level` argument can be a literal integer, or a macro that evaluates to
+// an integer.
+//
+// E.g.,
// LDBG() << "Bitset contains: " << Bitset;
// is equivalent to
-// LLVM_DEBUG(dbgs() << DEBUG_TYPE << " [" << __FILE__ << ":" << __LINE__
-// << "] " << "Bitset contains: " << Bitset << "\n");
-#define LDBG() DEBUGLOG_WITH_STREAM_AND_TYPE(llvm::dbgs(), DEBUG_TYPE)
+// LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] " << __FILE__ << ":" <<
+// __LINE__ << " "
+// << "Bitset contains: " << Bitset << "\n");
+#define LDBG(...) _GET_LDBG_MACRO(__VA_ARGS__)(__VA_ARGS__)
+
+// Helper macros to choose the correct macro based on the number of arguments.
+#define LDBG_FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3
+#define LDBG_FUNC_RECOMPOSER(argsWithParentheses) \
+ LDBG_FUNC_CHOOSER argsWithParentheses
+#define LDBG_CHOOSE_FROM_ARG_COUNT(...) \
+ LDBG_FUNC_RECOMPOSER((__VA_ARGS__, LDBG_LOG_LEVEL, ))
+#define LDBG_NO_ARG_EXPANDER() , , LDBG_LOG_LEVEL_0
+#define _GET_LDBG_MACRO(...) \
+ LDBG_CHOOSE_FROM_ARG_COUNT(LDBG_NO_ARG_EXPANDER __VA_ARGS__())
-#define DEBUGLOG_WITH_STREAM_TYPE_AND_FILE(STREAM, TYPE, FILE) \
- for (bool _c = (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)); _c; \
- _c = false) \
+// Dispatch macros to support the `level` argument or none (default to 1)
+#define LDBG_LOG_LEVEL(LEVEL) \
+ DEBUGLOG_WITH_STREAM_AND_TYPE(llvm::dbgs(), LEVEL, DEBUG_TYPE)
+#define LDBG_LOG_LEVEL_0() LDBG_LOG_LEVEL(1)
+
+#define DEBUGLOG_WITH_STREAM_TYPE_FILE_AND_LINE(STREAM, LEVEL, TYPE, FILE, \
+ LINE) \
+ for (bool _c = \
+ (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE, LEVEL)); \
+ _c; _c = false) \
::llvm::impl::raw_ldbg_ostream{ \
- ::llvm::impl::computePrefix(TYPE, FILE, __LINE__), (STREAM)} \
+ ::llvm::impl::computePrefix(TYPE, FILE, LINE, LEVEL), (STREAM)} \
.asLvalue()
+
+#define DEBUGLOG_WITH_STREAM_TYPE_AND_FILE(STREAM, LEVEL, TYPE, FILE) \
+ DEBUGLOG_WITH_STREAM_TYPE_FILE_AND_LINE(STREAM, LEVEL, TYPE, FILE, __LINE__)
// When __SHORT_FILE__ is not defined, the File is the full path,
// otherwise __SHORT_FILE__ is defined in CMake to provide the file name
// without the path prefix.
#if defined(__SHORT_FILE__)
-#define DEBUGLOG_WITH_STREAM_AND_TYPE(STREAM, TYPE) \
- DEBUGLOG_WITH_STREAM_TYPE_AND_FILE(STREAM, TYPE, __SHORT_FILE__)
+#define DEBUGLOG_WITH_STREAM_AND_TYPE(STREAM, LEVEL, TYPE) \
+ DEBUGLOG_WITH_STREAM_TYPE_AND_FILE(STREAM, LEVEL, TYPE, __SHORT_FILE__)
#else
-#define DEBUGLOG_WITH_STREAM_AND_TYPE(STREAM, TYPE) \
+#define DEBUGLOG_WITH_STREAM_AND_TYPE(STREAM, LEVEL, TYPE) \
DEBUGLOG_WITH_STREAM_TYPE_AND_FILE( \
- STREAM, TYPE, ::llvm::impl::LogWithNewline::getShortFileName(__FILE__))
+ STREAM, LEVEL, TYPE, \
+ ::llvm::impl::LogWithNewline::getShortFileName(__FILE__))
#endif
namespace impl {
@@ -119,11 +155,14 @@ getShortFileName(const char *path) {
/// "[DebugType] File:Line "
/// Where the File is the file name without the path prefix.
static LLVM_ATTRIBUTE_UNUSED std::string
-computePrefix(const char *DebugType, const char *File, int Line) {
+computePrefix(const char *DebugType, const char *File, int Line, int Level) {
std::string Prefix;
raw_string_ostream OsPrefix(Prefix);
- if (DebugType)
- OsPrefix << "[" << DebugType << "] ";
+ if (DebugType) {
+ if (Level == 0)
+ Level = 1;
+ OsPrefix << "[" << DebugType << ":" << Level << "] ";
+ }
OsPrefix << File << ":" << Line << " ";
return OsPrefix.str();
}
diff --git a/llvm/lib/Support/Debug.cpp b/llvm/lib/Support/Debug.cpp
index 5bb04d0c22998..9119d3e120c2a 100644
--- a/llvm/lib/Support/Debug.cpp
+++ b/llvm/lib/Support/Debug.cpp
@@ -24,11 +24,13 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Debug.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/circular_raw_ostream.h"
#include "llvm/Support/raw_ostream.h"
+#include <utility>
#include "DebugOptions.h"
@@ -38,25 +40,51 @@
using namespace llvm;
+/// Parse a debug type string into a pair of the debug type and the debug level.
+/// The expected format is "type[:level]", where the level is an optional
+/// integer.
+static std::pair<std::string, int> parseDebugType(StringRef DbgType) {
+ int Level = 0;
+ if (size_t ColonPos = DbgType.find(':'); ColonPos != StringRef::npos) {
+ StringRef LevelStr = DbgType.substr(ColonPos + 1);
+ DbgType = DbgType.take_front(ColonPos);
+ if (LevelStr.empty())
+ Level = -1;
+ else if (!to_integer(LevelStr, Level, 10))
+ Level = 0;
+ }
+ return std::make_pair(DbgType.str(), Level);
+}
+
// Even though LLVM might be built with NDEBUG, define symbols that the code
// built without NDEBUG can depend on via the llvm/Support/Debug.h header.
namespace llvm {
/// Exported boolean set by the -debug option.
bool DebugFlag = false;
-static ManagedStatic<std::vector<std::string>> CurrentDebugType;
+/// The current debug type and an optional debug level.
+/// The debug level is the verbosity of the debug output.
+/// The default level is 0, which is the most verbose.
+/// The level can be set to 1, 2, 3, etc. to control the verbosity of the
+/// output. The level can be set to -1 to disable the output.
+static ManagedStatic<std::vector<std::pair<std::string, int>>> CurrentDebugType;
/// Return true if the specified string is the debug type
/// specified on the command line, or if none was specified on the command line
/// with the -debug-only=X option.
-bool isCurrentDebugType(const char *DebugType) {
+bool isCurrentDebugType(const char *DebugType, int Level) {
if (CurrentDebugType->empty())
return true;
// See if DebugType is in list. Note: do not use find() as that forces us to
// unnecessarily create an std::string instance.
for (auto &d : *CurrentDebugType) {
- if (d == DebugType)
- return true;
+ if (d.first == DebugType) {
+ if (d.second < 0)
+ return false;
+ if (d.second == 0)
+ return true;
+ return d.second >= Level;
+ }
}
return false;
}
@@ -73,8 +101,11 @@ void setCurrentDebugType(const char *Type) {
void setCurrentDebugTypes(const char **Types, unsigned Count) {
CurrentDebugType->clear();
- llvm::append_range(*CurrentDebugType, ArrayRef(Types, Count));
+ CurrentDebugType->reserve(Count);
+ for (const char *Type : ArrayRef(Types, Count))
+ CurrentDebugType->push_back(parseDebugType(Type));
}
+
} // namespace llvm
// All Debug.h functionality is a no-op in NDEBUG mode.
@@ -114,10 +145,10 @@ struct DebugOnlyOpt {
if (Val.empty())
return;
DebugFlag = true;
- SmallVector<StringRef,8> dbgTypes;
- StringRef(Val).split(dbgTypes, ',', -1, false);
- for (auto dbgType : dbgTypes)
- CurrentDebugType->push_back(std::string(dbgType));
+ SmallVector<StringRef, 8> DbgTypes;
+ StringRef(Val).split(DbgTypes, ',', -1, false);
+ for (auto DbgType : DbgTypes)
+ CurrentDebugType->push_back(parseDebugType(DbgType));
}
};
} // namespace
@@ -130,7 +161,11 @@ struct CreateDebugOnly {
return new cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>(
"debug-only",
cl::desc("Enable a specific type of debug output (comma separated list "
- "of types)"),
+ "of types using the format \"type[:level]\", where the level "
+ "is an optional integer. The default level is 0, which is the "
+ "most verbose. The level can be set to 1, 2, 3, etc. to "
+ "control the verbosity of the output. The level can be set to "
+ "-1 or an empty string to disable the output."),
cl::Hidden, cl::value_desc("debug string"),
cl::location(DebugOnlyOptLoc), cl::ValueRequired);
}
diff --git a/llvm/unittests/Support/DebugLogTest.cpp b/llvm/unittests/Support/DebugLogTest.cpp
index c34d888ab4cad..8356ae856be27 100644
--- a/llvm/unittests/Support/DebugLogTest.cpp
+++ b/llvm/unittests/Support/DebugLogTest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/DebugLog.h"
+#include "llvm/ADT/Sequence.h"
#include "llvm/Support/raw_ostream.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -26,7 +27,7 @@ TEST(DebugLogTest, Basic) {
{
std::string str;
raw_string_ostream os(str);
- DEBUGLOG_WITH_STREAM_AND_TYPE(os, nullptr) << "NoType";
+ DEBUGLOG_WITH_STREAM_AND_TYPE(os, 0, nullptr) << "NoType";
EXPECT_FALSE(StringRef(os.str()).starts_with('['));
EXPECT_TRUE(StringRef(os.str()).ends_with("NoType\n"));
}
@@ -35,8 +36,8 @@ TEST(DebugLogTest, Basic) {
{
std::string str;
raw_string_ostream os(str);
- DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << "A";
- DEBUGLOG_WITH_STREAM_AND_TYPE(os, "B") << "B";
+ DEBUGLOG_WITH_STREAM_AND_TYPE(os, 0, "A") << "A";
+ DEBUGLOG_WITH_STREAM_AND_TYPE(os, 0, "B") << "B";
EXPECT_TRUE(StringRef(os.str()).starts_with('['));
EXPECT_THAT(os.str(), AllOf(HasSubstr("A\n"), HasSubstr("B\n")));
}
@@ -47,22 +48,40 @@ TEST(DebugLogTest, Basic) {
raw_string_ostream os(str);
// Just check that the macro doesn't result in dangling else.
if (true)
- DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << "A";
+ DEBUGLOG_WITH_STREAM_AND_TYPE(os, 0, "A") << "A";
else
- DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << "B";
- DEBUGLOG_WITH_STREAM_AND_TYPE(os, "B") << "B";
+ DEBUGLOG_WITH_STREAM_AND_TYPE(os, 0, "A") << "B";
+ DEBUGLOG_WITH_STREAM_AND_TYPE(os, 0, "B") << "B";
EXPECT_THAT(os.str(), AllOf(HasSubstr("A\n"), Not(HasSubstr("B\n"))));
int count = 0;
auto inc = [&]() { return ++count; };
EXPECT_THAT(count, Eq(0));
- DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << inc();
+ DEBUGLOG_WITH_STREAM_AND_TYPE(os, 0, "A") << inc();
EXPECT_THAT(count, Eq(1));
- DEBUGLOG_WITH_STREAM_AND_TYPE(os, "B") << inc();
+ DEBUGLOG_WITH_STREAM_AND_TYPE(os, 0, "B") << inc();
EXPECT_THAT(count, Eq(1));
}
}
+TEST(DebugLogTest, BasicWithLevel) {
+ llvm::DebugFlag = true;
+ // We expect A to be always printed, B to be printed only when level is 1 or
+ // below, and C to be never printed.
+ static const char *DT[] = {"A:0", "B:1", "C:-1", "D:"};
+
+ setCurrentDebugTypes(DT, sizeof(DT) / sizeof(DT[0]));
+ std::string str;
+ raw_string_ostream os(str);
+ for (auto type : {"A", "B", "C", "D"})
+ for (int level : llvm::seq<int>(0, 3))
+ DEBUGLOG_WITH_STREAM_TYPE_FILE_AND_LINE(os, level, type, type, level)
+ << level;
+ EXPECT_EQ(
+ os.str(),
+ "[A:1] A:0 0\n[A:1] A:1 1\n[A:2] A:2 2\n[B:1] B:0 0\n[B:1] B:1 1\n");
+}
+
TEST(DebugLogTest, StreamPrefix) {
llvm::DebugFlag = true;
static const char *DT[] = {"A", "B"};
>From f5285b8779987bbf2ff1fa021de5c05099430b62 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 26 Jul 2025 07:30:06 -0700
Subject: [PATCH 2/6] [MLIR] Migrate InlinerInterfaceImpl to the new LDBG()
debug form (NFC)
---
.../Transforms/InlinerInterfaceImpl.cpp | 32 +++++++++----------
1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
index 935aa3ce6b1f1..b951df8af3550 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp
@@ -22,6 +22,8 @@
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/DebugLog.h"
+
#define DEBUG_TYPE "llvm-inliner"
using namespace mlir;
@@ -670,44 +672,42 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
bool wouldBeCloned) const final {
auto callOp = dyn_cast<LLVM::CallOp>(call);
if (!callOp) {
- LLVM_DEBUG(llvm::dbgs() << "Cannot inline: call is not an '"
- << LLVM::CallOp::getOperationName() << "' op\n");
+ LDBG() << "Cannot inline: call is not an '"
+ << LLVM::CallOp::getOperationName() << "' op";
return false;
}
if (callOp.getNoInline()) {
- LLVM_DEBUG(llvm::dbgs() << "Cannot inline: call is marked no_inline\n");
+ LDBG() << "Cannot inline: call is marked no_inline";
return false;
}
auto funcOp = dyn_cast<LLVM::LLVMFuncOp>(callable);
if (!funcOp) {
- LLVM_DEBUG(llvm::dbgs()
- << "Cannot inline: callable is not an '"
- << LLVM::LLVMFuncOp::getOperationName() << "' op\n");
+ LDBG() << "Cannot inline: callable is not an '"
+ << LLVM::LLVMFuncOp::getOperationName() << "' op";
return false;
}
if (funcOp.isNoInline()) {
- LLVM_DEBUG(llvm::dbgs()
- << "Cannot inline: function is marked no_inline\n");
+ LDBG() << "Cannot inline: function is marked no_inline";
return false;
}
if (funcOp.isVarArg()) {
- LLVM_DEBUG(llvm::dbgs() << "Cannot inline: callable is variadic\n");
+ LDBG() << "Cannot inline: callable is variadic";
return false;
}
// TODO: Generate aliasing metadata from noalias result attributes.
if (auto attrs = funcOp.getArgAttrs()) {
for (DictionaryAttr attrDict : attrs->getAsRange<DictionaryAttr>()) {
if (attrDict.contains(LLVM::LLVMDialect::getInAllocaAttrName())) {
- LLVM_DEBUG(llvm::dbgs() << "Cannot inline " << funcOp.getSymName()
- << ": inalloca arguments not supported\n");
+ LDBG() << "Cannot inline " << funcOp.getSymName()
+ << ": inalloca arguments not supported";
return false;
}
}
}
// TODO: Handle exceptions.
if (funcOp.getPersonality()) {
- LLVM_DEBUG(llvm::dbgs() << "Cannot inline " << funcOp.getSymName()
- << ": unhandled function personality\n");
+ LDBG() << "Cannot inline " << funcOp.getSymName()
+ << ": unhandled function personality";
return false;
}
if (funcOp.getPassthrough()) {
@@ -717,10 +717,8 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
if (!stringAttr)
return false;
if (disallowedFunctionAttrs.contains(stringAttr)) {
- LLVM_DEBUG(llvm::dbgs()
- << "Cannot inline " << funcOp.getSymName()
- << ": found disallowed function attribute "
- << stringAttr << "\n");
+ LDBG() << "Cannot inline " << funcOp.getSymName()
+ << ": found disallowed function attribute " << stringAttr;
return true;
}
return false;
>From a2ab534e154a291cbf977d0e2807cab09d54b3fb Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 26 Jul 2025 02:41:37 -0700
Subject: [PATCH 3/6] Migrate NVVM to the new LDBG
---
.../Conversion/NVGPUToNVVM/NVGPUToNVVM.cpp | 52 +++++++++----------
mlir/lib/Conversion/NVVMToLLVM/NVVMToLLVM.cpp | 9 ++--
2 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/mlir/lib/Conversion/NVGPUToNVVM/NVGPUToNVVM.cpp b/mlir/lib/Conversion/NVGPUToNVVM/NVGPUToNVVM.cpp
index 5d133533e61ea..2549a9c631c24 100644
--- a/mlir/lib/Conversion/NVGPUToNVVM/NVGPUToNVVM.cpp
+++ b/mlir/lib/Conversion/NVGPUToNVVM/NVGPUToNVVM.cpp
@@ -26,13 +26,12 @@
#include "mlir/IR/Value.h"
#include "mlir/Pass/Pass.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/DebugLog.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>
#define DEBUG_TYPE "nvgpu-to-nvvm"
-#define DBGS() (llvm::dbgs() << '[' << DEBUG_TYPE << "] ")
-#define DBGSE() (llvm::dbgs())
namespace mlir {
#define GEN_PASS_DEF_CONVERTNVGPUTONVVMPASS
@@ -1105,13 +1104,13 @@ struct NVGPUGenerateWarpgroupDescriptorLowering
// // [0,14) start_address
dsc = insertBit(dsc, basePtr14bit, startBaseAddrBit);
- LLVM_DEBUG(DBGS() << "Generating warpgroup.descriptor: "
- << "leading_off:" << leadDimVal << "\t"
- << "stride_off :" << strideDimVal << "\t"
- << "base_offset:" << offsetVal << "\t"
- << "layout_type:" << swizzle << " ("
- << nvgpu::stringifyTensorMapSwizzleKind(swizzleKind)
- << ")\n start_addr : " << baseAddr << "\n");
+ LDBG() << "Generating warpgroup.descriptor: "
+ << "leading_off:" << leadDimVal << "\t"
+ << "stride_off :" << strideDimVal << "\t"
+ << "base_offset:" << offsetVal << "\t"
+ << "layout_type:" << swizzle << " ("
+ << nvgpu::stringifyTensorMapSwizzleKind(swizzleKind)
+ << ")\n start_addr : " << baseAddr;
rewriter.replaceOp(op, dsc);
return success();
@@ -1281,8 +1280,8 @@ struct NVGPUWarpgroupMmaOpLowering
} else {
llvm_unreachable("msg: not supported K shape");
}
- LLVM_DEBUG(DBGS() << "Generating WgmmaMmaAsyncOp shape[m = " << wgmmaM
- << ", n = " << wgmmaN << ", k = " << wgmmaK << "]\n");
+ LDBG() << "Generating WgmmaMmaAsyncOp shape[m = " << wgmmaM
+ << ", n = " << wgmmaN << ", k = " << wgmmaK << "]";
}
/// Generates WGMMATypesAttr from MLIR Type
@@ -1366,9 +1365,9 @@ struct NVGPUWarpgroupMmaOpLowering
int tileShapeA = matrixTypeA.getDimSize(1);
int incrementVal = ((wgmmaK * k) + (totalK * tileShapeA * i)) * byte;
incrementVal = incrementVal >> exclude4LSB;
- LLVM_DEBUG(DBGS() << "\t\t[m: " << i << " n: " << j << " k: " << k
- << "] [wgmma descriptors] Descriptor A + "
- << incrementVal << " | \t ");
+ LDBG() << "\t\t[m: " << i << " n: " << j << " k: " << k
+ << "] [wgmma descriptors] Descriptor A + " << incrementVal
+ << " | \t ";
if (!incrementVal)
return desc;
return makeAdd(desc, makeI64Const(b, incrementVal));
@@ -1391,7 +1390,7 @@ struct NVGPUWarpgroupMmaOpLowering
int byte = elemB.getIntOrFloatBitWidth() / 8;
int incrementVal = matrixTypeB.getDimSize(0) * wgmmaK * k * byte;
incrementVal = incrementVal >> exclude4LSB;
- LLVM_DEBUG(DBGSE() << "Descriptor B + " << incrementVal << "\n");
+ LDBG() << "Descriptor B + " << incrementVal;
if (!incrementVal)
return desc;
return makeAdd(desc, makeI64Const(b, incrementVal));
@@ -1400,15 +1399,14 @@ struct NVGPUWarpgroupMmaOpLowering
/// This function generates a WgmmaMmaAsyncOp using provided GMMA matrix
/// descriptors and arranges them based on induction variables: i, j, and k.
Value generateWgmma(int i, int j, int k, Value matrixC) {
- LLVM_DEBUG(DBGS() << "\t wgmma."
- << "m" << wgmmaM << "n" << wgmmaN << "k" << wgmmaK
- << "(A[" << (iterationM * wgmmaM) << ":"
- << (iterationM * wgmmaM) + wgmmaM << "]["
- << (iterationK * wgmmaK) << ":"
- << (iterationK * wgmmaK + wgmmaK) << "] * "
- << " B[" << (iterationK * wgmmaK) << ":"
- << (iterationK * wgmmaK + wgmmaK) << "][" << 0 << ":"
- << wgmmaN << "])\n");
+ LDBG() << "\t wgmma."
+ << "m" << wgmmaM << "n" << wgmmaN << "k" << wgmmaK << "(A["
+ << (iterationM * wgmmaM) << ":" << (iterationM * wgmmaM) + wgmmaM
+ << "][" << (iterationK * wgmmaK) << ":"
+ << (iterationK * wgmmaK + wgmmaK) << "] * "
+ << " B[" << (iterationK * wgmmaK) << ":"
+ << (iterationK * wgmmaK + wgmmaK) << "][" << 0 << ":" << wgmmaN
+ << "])";
Value descriptorA = iterateDescriptorA(adaptor.getDescriptorA(), i, j, k);
Value descriptorB = iterateDescriptorB(adaptor.getDescriptorB(), i, j, k);
@@ -1467,9 +1465,9 @@ struct NVGPUWarpgroupMmaOpLowering
totalM = op.getDescriptorA().getType().getTensor().getDimSize(0);
totalN = op.getDescriptorB().getType().getTensor().getDimSize(1);
totalK = op.getDescriptorA().getType().getTensor().getDimSize(1);
- LLVM_DEBUG(DBGS() << "===--- GEMM D[" << totalM << "][" << totalN
- << "] += A[" << totalM << "][" << totalK << "] * B["
- << totalK << "][" << totalN << "] ---===\n");
+ LDBG() << "===--- GEMM D[" << totalM << "][" << totalN << "] += A["
+ << totalM << "][" << totalK << "] * B[" << totalK << "][" << totalN
+ << "] ---===";
// Find the shape for one wgmma instruction
findWgmmaShape(
diff --git a/mlir/lib/Conversion/NVVMToLLVM/NVVMToLLVM.cpp b/mlir/lib/Conversion/NVVMToLLVM/NVVMToLLVM.cpp
index 662ee9e483bc5..91788f9848fe6 100644
--- a/mlir/lib/Conversion/NVVMToLLVM/NVVMToLLVM.cpp
+++ b/mlir/lib/Conversion/NVVMToLLVM/NVVMToLLVM.cpp
@@ -25,11 +25,10 @@
#include "mlir/IR/Value.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Support/LLVM.h"
+#include "llvm/Support/DebugLog.h"
#include "llvm/Support/raw_ostream.h"
#define DEBUG_TYPE "nvvm-to-llvm"
-#define DBGS() (llvm::dbgs() << "[" DEBUG_TYPE "]: ")
-#define DBGSNL() (llvm::dbgs() << "\n")
namespace mlir {
#define GEN_PASS_DEF_CONVERTNVVMTOLLVMPASS
@@ -52,17 +51,17 @@ struct PtxLowering
LogicalResult matchAndRewrite(BasicPtxBuilderInterface op,
PatternRewriter &rewriter) const override {
if (op.hasIntrinsic()) {
- LLVM_DEBUG(DBGS() << "Ptx Builder does not lower \n\t" << op << "\n");
+ LDBG() << "Ptx Builder does not lower \n\t" << op;
return failure();
}
SmallVector<std::pair<Value, PTXRegisterMod>> asmValues;
- LLVM_DEBUG(DBGS() << op.getPtx() << "\n");
+ LDBG() << op.getPtx();
PtxBuilder generator(op, rewriter);
op.getAsmValues(rewriter, asmValues);
for (auto &[asmValue, modifier] : asmValues) {
- LLVM_DEBUG(DBGSNL() << asmValue << "\t Modifier : " << &modifier);
+ LDBG() << asmValue << "\t Modifier : " << &modifier;
generator.insertValue(asmValue, modifier);
}
>From 34b5e995c0e493143c2e843d4946f80bd566eb6b Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 26 Jul 2025 07:30:30 -0700
Subject: [PATCH 4/6] [MLIR] Migrate pattern application / dialect conversion
to the LDBG logging format
This prefix the output with the DEBUG_TYPE.
Dialect conversion is using a ScopedPrinter, we insert the raw_ldbg_ostream to
consistently prefix each new line.
---
mlir/lib/Rewrite/PatternApplicator.cpp | 10 ++++------
mlir/lib/Transforms/Utils/DialectConversion.cpp | 8 +++++++-
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/mlir/lib/Rewrite/PatternApplicator.cpp b/mlir/lib/Rewrite/PatternApplicator.cpp
index b2b372b7b1249..4672761398f8e 100644
--- a/mlir/lib/Rewrite/PatternApplicator.cpp
+++ b/mlir/lib/Rewrite/PatternApplicator.cpp
@@ -13,7 +13,7 @@
#include "mlir/Rewrite/PatternApplicator.h"
#include "ByteCode.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/Support/DebugLog.h"
#ifndef NDEBUG
#include "llvm/ADT/ScopeExit.h"
@@ -51,9 +51,7 @@ static Operation *getDumpRootOp(Operation *op) {
return op;
}
static void logSucessfulPatternApplication(Operation *op) {
- llvm::dbgs() << "// *** IR Dump After Pattern Application ***\n";
- op->dump();
- llvm::dbgs() << "\n\n";
+ LDBG() << "// *** IR Dump After Pattern Application ***\n" << *op << "\n";
}
#endif
@@ -208,8 +206,8 @@ LogicalResult PatternApplicator::matchAndRewrite(
result =
bytecode->rewrite(rewriter, *pdlMatch, *mutableByteCodeState);
} else {
- LLVM_DEBUG(llvm::dbgs() << "Trying to match \""
- << bestPattern->getDebugName() << "\"\n");
+ LDBG() << "Trying to match \"" << bestPattern->getDebugName()
+ << "\"";
const auto *pattern =
static_cast<const RewritePattern *>(bestPattern);
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index 08803e082b057..d8151eef729fc 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -20,6 +20,7 @@
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/DebugLog.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -1129,8 +1130,13 @@ struct ConversionPatternRewriterImpl : public RewriterBase::Listener {
/// verification.
SmallPtrSet<Operation *, 1> pendingRootUpdates;
+ /// A raw output stream used to prefix the debug log.
+ llvm::impl::raw_ldbg_ostream os{(Twine("[") + DEBUG_TYPE + "] ").str(),
+ llvm::dbgs()};
+
/// A logger used to emit diagnostics during the conversion process.
- llvm::ScopedPrinter logger{llvm::dbgs()};
+ llvm::ScopedPrinter logger{os};
+ std::string logPrefix;
#endif
};
} // namespace detail
>From 25c9e596e77775e2011e3d226a7a56f0a645af60 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 26 Jul 2025 07:49:06 -0700
Subject: [PATCH 5/6] [MLIR] Use LDBG in MLIR AsmPrinter
---
mlir/lib/IR/AsmPrinter.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp
index f95ad290a1981..de52fbd3f215c 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -40,7 +40,7 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/Support/DebugLog.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Regex.h"
@@ -2070,9 +2070,8 @@ static OpPrintingFlags verifyOpAndAdjustFlags(Operation *op,
return failure();
});
if (failed(verify(op))) {
- LLVM_DEBUG(llvm::dbgs()
- << DEBUG_TYPE << ": '" << op->getName()
- << "' failed to verify and will be printed in generic form\n");
+ LDBG() << op->getName()
+ << "' failed to verify and will be printed in generic form";
printerFlags.printGenericOpForm();
}
>From 3aad573ceeb5639a5a424ed99da4bc79068c262b Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sun, 27 Jul 2025 15:24:10 -0700
Subject: [PATCH 6/6] [MLIR] Use LDBG(4) for verbose output in transform
interfaces (NFC)
---
llvm/include/llvm/Support/DebugLog.h | 2 +-
.../Transform/Interfaces/TransformInterfaces.cpp | 10 +---------
2 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/Support/DebugLog.h b/llvm/include/llvm/Support/DebugLog.h
index 453d0e265876f..b8d80114a6a23 100644
--- a/llvm/include/llvm/Support/DebugLog.h
+++ b/llvm/include/llvm/Support/DebugLog.h
@@ -170,7 +170,7 @@ computePrefix(const char *DebugType, const char *File, int Line, int Level) {
#else
// As others in Debug, When compiling without assertions, the -debug-* options
// and all inputs too LDBG() are ignored.
-#define LDBG() \
+#define LDBG(...) \
for (bool _c = false; _c; _c = false) \
::llvm::nulls()
#endif
diff --git a/mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp b/mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp
index e297f7cddc13a..14a4fdfcb89da 100644
--- a/mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp
+++ b/mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp
@@ -21,16 +21,8 @@
#include "llvm/Support/InterleavedRange.h"
#define DEBUG_TYPE "transform-dialect"
-#define DEBUG_TYPE_FULL "transform-dialect-full"
#define DEBUG_PRINT_AFTER_ALL "transform-dialect-print-top-level-after-all"
-#ifndef NDEBUG
-#define FULL_LDBG(X) \
- DEBUGLOG_WITH_STREAM_AND_TYPE(llvm::dbgs(), DEBUG_TYPE_FULL)
-#else
-#define FULL_LDBG(X) \
- for (bool _c = false; _c; _c = false) \
- ::llvm::nulls()
-#endif
+#define FULL_LDBG() LDBG(4)
using namespace mlir;
More information about the Mlir-commits
mailing list