[Mlir-commits] [mlir] [mlir][IR][NFC] Add `Block::computeBlockNumber` convenience helper (PR #173475)
Matthias Springer
llvmlistbot at llvm.org
Wed Dec 24 02:45:07 PST 2025
https://github.com/matthias-springer created https://github.com/llvm/llvm-project/pull/173475
Add a helper function to compute the number of a block. Recommended only for debugging purposes and to print error messages.
>From 36a141a09b3288365bfef3d8bfb68cada785e0f0 Mon Sep 17 00:00:00 2001
From: Matthias Springer <me at m-sp.org>
Date: Wed, 24 Dec 2025 10:38:55 +0000
Subject: [PATCH] [mlir][IR][NFC] Add `Block::computeBlockNumber` helper
---
mlir/include/mlir/IR/Block.h | 12 ++++++++++++
.../Transform/DebugExtension/DebugExtensionOps.cpp | 5 ++---
.../Transform/Interfaces/TransformInterfaces.cpp | 3 +--
mlir/lib/IR/Block.cpp | 5 +++++
mlir/lib/IR/Unit.cpp | 4 +---
mlir/lib/IR/Verifier.cpp | 2 +-
mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp | 9 ++-------
mlir/lib/Transforms/RemoveDeadValues.cpp | 2 +-
mlir/test/lib/Analysis/TestAliasAnalysis.cpp | 3 +--
9 files changed, 26 insertions(+), 19 deletions(-)
diff --git a/mlir/include/mlir/IR/Block.h b/mlir/include/mlir/IR/Block.h
index 85ce66f69df48..3d737fa3e0659 100644
--- a/mlir/include/mlir/IR/Block.h
+++ b/mlir/include/mlir/IR/Block.h
@@ -77,6 +77,18 @@ class alignas(8) Block : public IRObjectWithUseList<BlockOperand>,
/// Unlink this Block from its parent region and delete it.
void erase();
+ /// Compute the position of this block within its parent region.
+ ///
+ /// Note: There is no semantic meaning to a block number. Blocks are used for
+ /// unstructured control flow and relying on block numbers for functional
+ /// purposes may indicate a design flaw. (You can give semantic meaning to
+ /// region numbers instead.) Block numbers are useful for debugging purposes
+ /// and for error messages.
+ ///
+ /// This function has a complexity of O(N) because it iterates over a linked
+ /// list of blocks.
+ unsigned computeBlockNumber();
+
//===--------------------------------------------------------------------===//
// Block argument management
//===--------------------------------------------------------------------===//
diff --git a/mlir/lib/Dialect/Transform/DebugExtension/DebugExtensionOps.cpp b/mlir/lib/Dialect/Transform/DebugExtension/DebugExtensionOps.cpp
index a963b3f063a8a..9f9695b7d348b 100644
--- a/mlir/lib/Dialect/Transform/DebugExtension/DebugExtensionOps.cpp
+++ b/mlir/lib/Dialect/Transform/DebugExtension/DebugExtensionOps.cpp
@@ -34,9 +34,8 @@ transform::EmitRemarkAtOp::apply(transform::TransformRewriter &rewriter,
os << "value handle points to ";
if (auto arg = llvm::dyn_cast<BlockArgument>(value)) {
os << "a block argument #" << arg.getArgNumber() << " in block #"
- << std::distance(arg.getOwner()->getParent()->begin(),
- arg.getOwner()->getIterator())
- << " in region #" << arg.getOwner()->getParent()->getRegionNumber();
+ << arg.getOwner()->computeBlockNumber() << " in region #"
+ << arg.getOwner()->getParent()->getRegionNumber();
} else {
os << "an op result #" << llvm::cast<OpResult>(value).getResultNumber();
}
diff --git a/mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp b/mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp
index 4f09782859e07..c1fc1d53742ea 100644
--- a/mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp
+++ b/mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp
@@ -554,8 +554,7 @@ void transform::TransformState::recordValueHandleInvalidationByOpHandleOne(
auto arg = llvm::cast<BlockArgument>(payloadValue);
definingOp = arg.getParentBlock()->getParentOp();
argumentNo = arg.getArgNumber();
- blockNo = std::distance(arg.getOwner()->getParent()->begin(),
- arg.getOwner()->getIterator());
+ blockNo = arg.getOwner()->computeBlockNumber();
regionNo = arg.getOwner()->getParent()->getRegionNumber();
}
assert(definingOp && "expected the value to be defined by an op as result "
diff --git a/mlir/lib/IR/Block.cpp b/mlir/lib/IR/Block.cpp
index 27b47e2d2653d..1a06c576fd01c 100644
--- a/mlir/lib/IR/Block.cpp
+++ b/mlir/lib/IR/Block.cpp
@@ -141,6 +141,11 @@ void Block::recomputeOpOrder() {
op.orderIndex = (orderIndex += Operation::kOrderStride);
}
+unsigned Block::computeBlockNumber() {
+ assert(getParent() && "cannot compute block number of detached block");
+ return std::distance(getParent()->begin(), getIterator());
+}
+
//===----------------------------------------------------------------------===//
// Argument list management.
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/IR/Unit.cpp b/mlir/lib/IR/Unit.cpp
index 58c1d27db87f0..158fa13bf9e5f 100644
--- a/mlir/lib/IR/Unit.cpp
+++ b/mlir/lib/IR/Unit.cpp
@@ -37,9 +37,7 @@ static void printRegion(llvm::raw_ostream &os, Region *region,
static void printBlock(llvm::raw_ostream &os, Block *block,
OpPrintingFlags &flags) {
Region *region = block->getParent();
- Block *entry = ®ion->front();
- int blockId = std::distance(entry->getIterator(), block->getIterator());
- os << "Block #" << blockId << " for ";
+ os << "Block #" << block->computeBlockNumber() << " for ";
bool shouldSkipRegions = flags.shouldSkipRegions();
printRegion(os, region, flags.skipRegions());
if (!shouldSkipRegions)
diff --git a/mlir/lib/IR/Verifier.cpp b/mlir/lib/IR/Verifier.cpp
index 3ced663a87be1..e19537a901d18 100644
--- a/mlir/lib/IR/Verifier.cpp
+++ b/mlir/lib/IR/Verifier.cpp
@@ -364,7 +364,7 @@ static void diagnoseInvalidOperandDominance(Operation &op, unsigned operandNo) {
}
if (block1 == block2)
llvm::report_fatal_error("Internal error in dominance verification");
- int index = std::distance(region2->begin(), block2->getIterator());
+ unsigned index = block2->computeBlockNumber();
note << "operand defined as a block argument (block #" << index;
if (region1 == region2)
note << " in the same region)";
diff --git a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
index 248f885505819..05ab4fb4f07cd 100644
--- a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
+++ b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp
@@ -172,11 +172,6 @@ static std::optional<StringRef> getTextFromRange(SMRange range) {
return StringRef(startPtr, range.End.getPointer() - startPtr);
}
-/// Given a block, return its position in its parent region.
-static unsigned getBlockNumber(Block *block) {
- return std::distance(block->getParent()->begin(), block->getIterator());
-}
-
/// Given a block and source location, print the source name of the block to the
/// given output stream.
static void printDefBlockName(raw_ostream &os, Block *block, SMRange loc = {}) {
@@ -188,7 +183,7 @@ static void printDefBlockName(raw_ostream &os, Block *block, SMRange loc = {}) {
}
// Otherwise, we don't have a name so print the block number.
- os << "<Block #" << getBlockNumber(block) << ">";
+ os << "<Block #" << block->computeBlockNumber() << ">";
}
static void printDefBlockName(raw_ostream &os,
const AsmParserState::BlockDefinition &def) {
@@ -622,7 +617,7 @@ MLIRDocument::buildHoverForBlock(SMRange hoverRange,
// Display the parent operation, block number, predecessors, and successors.
os << "Operation: \"" << block.block->getParentOp()->getName() << "\"\n\n"
- << "Block #" << getBlockNumber(block.block) << "\n\n";
+ << "Block #" << block.block->computeBlockNumber() << "\n\n";
if (!block.block->hasNoPredecessors()) {
os << "Predecessors: ";
llvm::interleaveComma(block.block->getPredecessors(), os,
diff --git a/mlir/lib/Transforms/RemoveDeadValues.cpp b/mlir/lib/Transforms/RemoveDeadValues.cpp
index 10942923ba1e1..04658b31c2466 100644
--- a/mlir/lib/Transforms/RemoveDeadValues.cpp
+++ b/mlir/lib/Transforms/RemoveDeadValues.cpp
@@ -795,7 +795,7 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
LDBG_OS([&](raw_ostream &os) {
os << "Erasing non-live arguments [";
llvm::interleaveComma(b.nonLiveArgs.set_bits(), os);
- os << "] from block: " << b.b << " in region "
+ os << "] from block #" << b.b->computeBlockNumber() << " in region #"
<< b.b->getParent()->getRegionNumber() << " of operation "
<< OpWithFlags(b.b->getParent()->getParentOp(),
OpPrintingFlags().skipRegions().printGenericOpForm());
diff --git a/mlir/test/lib/Analysis/TestAliasAnalysis.cpp b/mlir/test/lib/Analysis/TestAliasAnalysis.cpp
index 65e3490953d6e..0125e403272a8 100644
--- a/mlir/test/lib/Analysis/TestAliasAnalysis.cpp
+++ b/mlir/test/lib/Analysis/TestAliasAnalysis.cpp
@@ -26,8 +26,7 @@ static void printAliasOperand(Operation *op) {
static void printAliasOperand(Value value) {
if (BlockArgument arg = dyn_cast<BlockArgument>(value)) {
Region *region = arg.getParentRegion();
- unsigned parentBlockNumber =
- std::distance(region->begin(), arg.getOwner()->getIterator());
+ unsigned parentBlockNumber = arg.getOwner()->computeBlockNumber();
llvm::errs() << region->getParentOp()
->getAttrOfType<StringAttr>("test.ptr")
.getValue()
More information about the Mlir-commits
mailing list