[Mlir-commits] [mlir] [MLIR][IR] add -mlir-print-unique-ids to AsmPrinter (PR #91241)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon May 6 10:14:15 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-core

Author: Scott Manley (rscottmanley)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/91241.diff


3 Files Affected:

- (modified) mlir/include/mlir/IR/OperationSupport.h (+6) 
- (modified) mlir/lib/IR/AsmPrinter.cpp (+20-3) 
- (added) mlir/test/IR/print-unique-ids.mlir (+40) 


``````````diff
diff --git a/mlir/include/mlir/IR/OperationSupport.h b/mlir/include/mlir/IR/OperationSupport.h
index e661bb87a27ed0..e0b88d3b1bb4f3 100644
--- a/mlir/include/mlir/IR/OperationSupport.h
+++ b/mlir/include/mlir/IR/OperationSupport.h
@@ -1219,6 +1219,9 @@ class OpPrintingFlags {
   /// Return if the printer should print users of values.
   bool shouldPrintValueUsers() const;
 
+  /// Return if printer should use unique IDs.
+  bool shouldPrintUniqueIDs() const;
+
 private:
   /// Elide large elements attributes if the number of elements is larger than
   /// the upper limit.
@@ -1249,6 +1252,9 @@ class OpPrintingFlags {
 
   /// Print users of values.
   bool printValueUsersFlag : 1;
+
+  /// Print unique ids for values, block arguments and naming conflicts
+  bool printUniqueIDsFlag : 1;
 };
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp
index e915b97d9ff17b..72c84b57222092 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -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> printUniqueIDs{
+      "mlir-print-unique-ids", llvm::cl::init(false),
+      llvm::cl::desc("Print unique id numbers for values, block arguments and "
+                     "naming conflicts across all regions")};
 };
 } // namespace
 
@@ -206,7 +211,7 @@ OpPrintingFlags::OpPrintingFlags()
     : printDebugInfoFlag(false), printDebugInfoPrettyFormFlag(false),
       printGenericOpFormFlag(false), skipRegionsFlag(false),
       assumeVerifiedFlag(false), printLocalScope(false),
-      printValueUsersFlag(false) {
+      printValueUsersFlag(false), printUniqueIDsFlag(false) {
   // Initialize based upon command line options, if they are available.
   if (!clOptions.isConstructed())
     return;
@@ -224,6 +229,7 @@ OpPrintingFlags::OpPrintingFlags()
   printLocalScope = clOptions->printLocalScopeOpt;
   skipRegionsFlag = clOptions->skipRegionsOpt;
   printValueUsersFlag = clOptions->printValueUsers;
+  printUniqueIDsFlag = clOptions->printUniqueIDs;
 }
 
 /// Enable the elision of large elements attributes, by printing a '...'
@@ -350,6 +356,11 @@ bool OpPrintingFlags::shouldPrintValueUsers() const {
   return printValueUsersFlag;
 }
 
+/// Return if the printer should use unique IDs.
+bool OpPrintingFlags::shouldPrintUniqueIDs() const {
+  return printUniqueIDsFlag || shouldPrintGenericOpForm();
+}
+
 //===----------------------------------------------------------------------===//
 // NewLineCounter
 //===----------------------------------------------------------------------===//
@@ -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.shouldPrintUniqueIDs())
+      // When printing unique 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.
diff --git a/mlir/test/IR/print-unique-ids.mlir b/mlir/test/IR/print-unique-ids.mlir
new file mode 100644
index 00000000000000..8be57e0259de19
--- /dev/null
+++ b/mlir/test/IR/print-unique-ids.mlir
@@ -0,0 +1,40 @@
+// RUN: mlir-opt -mlir-print-unique-ids %s | FileCheck %s
+
+// CHECK: %arg5
+// CHECK: %15
+module {
+  func.func @uniqueConflicts(%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.for %arg3 = %c0 to %c8 step %c1 {
+        %a2 = memref.load %arg0[] : memref<i32>
+        %b2 = memref.load %arg1[] : memref<i32>
+        %2 = arith.addi %a2, %b2 : i32
+        %3 = arith.subi %a2, %b2 : i32
+        scf.yield
+      }
+      scf.for %arg3 = %c0 to %c8 step %c1 {
+        %a2 = memref.load %arg0[] : memref<i32>
+        %b2 = memref.load %arg1[] : memref<i32>
+        %2 = arith.addi %a2, %b2 : i32
+        %3 = arith.subi %a2, %b2 : i32
+        scf.yield
+      }
+      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
+  }
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/91241


More information about the Mlir-commits mailing list