Skip to content

Commit

Permalink
[MLIR][IR] add -mlir-print-unique-ssa-ids to AsmPrinter (#91241)
Browse files Browse the repository at this point in the history
Add an option to unique the numbers of values, block arguments and
naming conflicts when requested and/or printing generic op form. This is
helpful when debugging. For example, if you have:

    scf.for
      %0 =
      %1 = opA %0

    scf.for
      %0 =
      %1 = opB %0

And you get a verifier error which says opB's "operand #0 does not
dominate this use", it looks like %0 does dominate the use. This is not
intuitive. If these were numbered uniquely, it would look like:

    scf.for
      %0 =
      %1 = opA %0

    scf.for
      %2 =
      %3 = opB %0

And thus, much clearer as to why you are getting the error since %0 is
out of scope. Since generic op form should aim to give you the most
possible information, it seems like a good idea to use unique numbers in
this situation. Adding an option also gives those an option to use it
outside of generic op form.

Co-authored-by: Scott Manley <scmanley@nvidia.com>
  • Loading branch information
rscottmanley and Scott Manley committed May 7, 2024
1 parent e84fae8 commit 5717553
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 3 deletions.
6 changes: 6 additions & 0 deletions mlir/include/mlir/IR/OperationSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,9 @@ class OpPrintingFlags {
/// Return if the printer should print users of values.
bool shouldPrintValueUsers() const;

/// Return if printer should use unique SSA IDs.
bool shouldPrintUniqueSSAIDs() const;

private:
/// Elide large elements attributes if the number of elements is larger than
/// the upper limit.
Expand Down Expand Up @@ -1249,6 +1252,9 @@ class OpPrintingFlags {

/// Print users of values.
bool printValueUsersFlag : 1;

/// Print unique SSA IDs for values, block arguments and naming conflicts
bool printUniqueSSAIDsFlag : 1;
};

//===----------------------------------------------------------------------===//
Expand Down
23 changes: 20 additions & 3 deletions mlir/lib/IR/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ struct AsmPrinterOptions {
"mlir-print-value-users", llvm::cl::init(false),
llvm::cl::desc(
"Print users of operation results and block arguments as a comment")};

llvm::cl::opt<bool> printUniqueSSAIDs{
"mlir-print-unique-ssa-ids", llvm::cl::init(false),
llvm::cl::desc("Print unique SSA ID numbers for values, block arguments "
"and naming conflicts across all regions")};
};
} // namespace

Expand All @@ -206,7 +211,7 @@ OpPrintingFlags::OpPrintingFlags()
: printDebugInfoFlag(false), printDebugInfoPrettyFormFlag(false),
printGenericOpFormFlag(false), skipRegionsFlag(false),
assumeVerifiedFlag(false), printLocalScope(false),
printValueUsersFlag(false) {
printValueUsersFlag(false), printUniqueSSAIDsFlag(false) {
// Initialize based upon command line options, if they are available.
if (!clOptions.isConstructed())
return;
Expand All @@ -224,6 +229,7 @@ OpPrintingFlags::OpPrintingFlags()
printLocalScope = clOptions->printLocalScopeOpt;
skipRegionsFlag = clOptions->skipRegionsOpt;
printValueUsersFlag = clOptions->printValueUsers;
printUniqueSSAIDsFlag = clOptions->printUniqueSSAIDs;
}

/// Enable the elision of large elements attributes, by printing a '...'
Expand Down Expand Up @@ -350,6 +356,11 @@ bool OpPrintingFlags::shouldPrintValueUsers() const {
return printValueUsersFlag;
}

/// Return if the printer should use unique IDs.
bool OpPrintingFlags::shouldPrintUniqueSSAIDs() const {
return printUniqueSSAIDsFlag || shouldPrintGenericOpForm();
}

//===----------------------------------------------------------------------===//
// NewLineCounter
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1369,8 +1380,14 @@ SSANameState::SSANameState(Operation *op, const OpPrintingFlags &printerFlags)
while (!nameContext.empty()) {
Region *region;
UsedNamesScopeTy *parentScope;
std::tie(region, nextValueID, nextArgumentID, nextConflictID, parentScope) =
nameContext.pop_back_val();

if (printerFlags.shouldPrintUniqueSSAIDs())
// To print unique SSA IDs, ignore saved ID counts from parent regions
std::tie(region, std::ignore, std::ignore, std::ignore, parentScope) =
nameContext.pop_back_val();
else
std::tie(region, nextValueID, nextArgumentID, nextConflictID,
parentScope) = nameContext.pop_back_val();

// When we switch from one subtree to another, pop the scopes(needless)
// until the parent scope.
Expand Down
30 changes: 30 additions & 0 deletions mlir/test/IR/print-unique-ssa-ids.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// RUN: mlir-opt -mlir-print-unique-ssa-ids %s | FileCheck %s
// RUN: mlir-opt -mlir-print-op-generic %s | FileCheck %s
// RUN: mlir-opt %s | FileCheck %s --check-prefix=LOCAL_SCOPE

// CHECK: %arg3
// CHECK: %7
// LOCAL_SCOPE-NOT: %arg3
// LOCAL_SCOPE-NOT: %7
module {
func.func @uniqueSSAIDs(%arg0 : memref<i32>, %arg1 : memref<i32>) {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c8 = arith.constant 8 : index
scf.for %arg2 = %c0 to %c8 step %c1 {
%a = memref.load %arg0[] : memref<i32>
%b = memref.load %arg1[] : memref<i32>
%0 = arith.addi %a, %b : i32
%1 = arith.subi %a, %b : i32
scf.yield
}
scf.for %arg2 = %c0 to %c8 step %c1 {
%a = memref.load %arg0[] : memref<i32>
%b = memref.load %arg1[] : memref<i32>
%0 = arith.addi %a, %b : i32
%1 = arith.subi %a, %b : i32
scf.yield
}
return
}
}

0 comments on commit 5717553

Please sign in to comment.