[Mlir-commits] [mlir] [mlir] Handle backedges in --view-op-graph (PR #82002)

Artem Tyurin llvmlistbot at llvm.org
Sat Feb 17 05:07:28 PST 2024


https://github.com/agentcooper updated https://github.com/llvm/llvm-project/pull/82002

>From 8dc6364a6e68d032d161bf2f9316edf1adf03e41 Mon Sep 17 00:00:00 2001
From: Artem Tyurin <artem.tyurin at gmail.com>
Date: Fri, 16 Feb 2024 16:42:42 +0100
Subject: [PATCH 1/4] [mlir] Handle backedges in --view-op-graph

---
 mlir/lib/Transforms/ViewOpGraph.cpp           |  3 +++
 .../Transforms/print-op-graph-backedges.mlir  | 24 +++++++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 mlir/test/Transforms/print-op-graph-backedges.mlir

diff --git a/mlir/lib/Transforms/ViewOpGraph.cpp b/mlir/lib/Transforms/ViewOpGraph.cpp
index 3d2723839957c4..485f93aeb9c3c4 100644
--- a/mlir/lib/Transforms/ViewOpGraph.cpp
+++ b/mlir/lib/Transforms/ViewOpGraph.cpp
@@ -13,6 +13,7 @@
 #include "mlir/IR/Operation.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Support/IndentedOstream.h"
+#include "mlir/Transforms/TopologicalSortUtils.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/GraphWriter.h"
 #include <map>
@@ -276,6 +277,8 @@ class PrintOpPass : public impl::ViewOpGraphBase<PrintOpPass> {
   /// Process a block. Emit a cluster and one node per block argument and
   /// operation inside the cluster.
   void processBlock(Block &block) {
+    sortTopologically(&block);
+
     emitClusterStmt([&]() {
       for (BlockArgument &blockArg : block.getArguments())
         valueToNode[blockArg] = emitNodeStmt(getLabel(blockArg));
diff --git a/mlir/test/Transforms/print-op-graph-backedges.mlir b/mlir/test/Transforms/print-op-graph-backedges.mlir
new file mode 100644
index 00000000000000..cd03bd0c1c298f
--- /dev/null
+++ b/mlir/test/Transforms/print-op-graph-backedges.mlir
@@ -0,0 +1,24 @@
+// RUN: mlir-opt -view-op-graph %s -o %t 2>&1 | FileCheck -check-prefix=DFG %s
+
+// DFG-LABEL: digraph G {
+//       DFG:   compound = true;
+//       DFG:   subgraph cluster_1 {
+//       DFG:     v2 [label = " ", shape = plain];
+//       DFG:     label = "builtin.module : ()\n";
+//       DFG:     subgraph cluster_3 {
+//       DFG:       v4 [label = " ", shape = plain];
+//       DFG:       label = "";
+//       DFG:       v5 [fillcolor = "0.333333 1.0 1.0", label = "arith.constant : (index)\n\nvalue: 0 : index", shape = ellipse, style = filled];
+//       DFG:       v6 [fillcolor = "0.333333 1.0 1.0", label = "arith.constant : (index)\n\nvalue: 1 : index", shape = ellipse, style = filled];
+//       DFG:       v7 [fillcolor = "0.000000 1.0 1.0", label = "arith.addi : (index)\n\noverflowFlags: #arith.overflow<none...", shape = ellipse, style = filled];
+//       DFG:     }
+//       DFG:   }
+//       DFG:   v5 -> v7 [label = "0", style = solid];
+//       DFG:   v6 -> v7 [label = "1", style = solid];
+//       DFG: }
+
+module {
+  %add = arith.addi %c0, %c1 : index
+  %c0 = arith.constant 0 : index
+  %c1 = arith.constant 1 : index
+}

>From 96abe87d71acff42c34b43b4bf86c4d849b7cb2e Mon Sep 17 00:00:00 2001
From: Artem Tyurin <artem.tyurin at gmail.com>
Date: Sat, 17 Feb 2024 00:24:24 +0100
Subject: [PATCH 2/4] Do not modify existing blocks

---
 mlir/lib/Transforms/ViewOpGraph.cpp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/mlir/lib/Transforms/ViewOpGraph.cpp b/mlir/lib/Transforms/ViewOpGraph.cpp
index 485f93aeb9c3c4..8ebd8e631bb57f 100644
--- a/mlir/lib/Transforms/ViewOpGraph.cpp
+++ b/mlir/lib/Transforms/ViewOpGraph.cpp
@@ -277,16 +277,20 @@ class PrintOpPass : public impl::ViewOpGraphBase<PrintOpPass> {
   /// Process a block. Emit a cluster and one node per block argument and
   /// operation inside the cluster.
   void processBlock(Block &block) {
-    sortTopologically(&block);
-
     emitClusterStmt([&]() {
       for (BlockArgument &blockArg : block.getArguments())
         valueToNode[blockArg] = emitNodeStmt(getLabel(blockArg));
 
+      SmallVector<Operation*> sortedOperations;
+      for (Operation &op : block) {
+        sortedOperations.push_back(&op);
+      }
+      computeTopologicalSorting(sortedOperations);
+
       // Emit a node for each operation.
       std::optional<Node> prevNode;
-      for (Operation &op : block) {
-        Node nextNode = processOperation(&op);
+      for (Operation *op : sortedOperations) {
+        Node nextNode = processOperation(op);
         if (printControlFlowEdges && prevNode)
           emitEdgeStmt(*prevNode, nextNode, /*label=*/"",
                        kLineStyleControlFlow);

>From 51ed372d125e8b55a3f665df0a090b1f7c210e31 Mon Sep 17 00:00:00 2001
From: Artem Tyurin <artem.tyurin at gmail.com>
Date: Sat, 17 Feb 2024 00:25:40 +0100
Subject: [PATCH 3/4] Format code

---
 mlir/lib/Transforms/ViewOpGraph.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Transforms/ViewOpGraph.cpp b/mlir/lib/Transforms/ViewOpGraph.cpp
index 8ebd8e631bb57f..bbd95252ee614d 100644
--- a/mlir/lib/Transforms/ViewOpGraph.cpp
+++ b/mlir/lib/Transforms/ViewOpGraph.cpp
@@ -281,7 +281,7 @@ class PrintOpPass : public impl::ViewOpGraphBase<PrintOpPass> {
       for (BlockArgument &blockArg : block.getArguments())
         valueToNode[blockArg] = emitNodeStmt(getLabel(blockArg));
 
-      SmallVector<Operation*> sortedOperations;
+      SmallVector<Operation *> sortedOperations;
       for (Operation &op : block) {
         sortedOperations.push_back(&op);
       }

>From e22ffd671479834f1b7bea3db5b189e4680c1ff8 Mon Sep 17 00:00:00 2001
From: Artem Tyurin <artem.tyurin at gmail.com>
Date: Sat, 17 Feb 2024 14:07:11 +0100
Subject: [PATCH 4/4] Handle cycles

---
 mlir/lib/Transforms/ViewOpGraph.cpp           | 23 +++++----
 ...es.mlir => print-op-graph-back-edges.mlir} | 10 ++--
 .../Transforms/print-op-graph-cycles.mlir     | 51 +++++++++++++++++++
 3 files changed, 68 insertions(+), 16 deletions(-)
 rename mlir/test/Transforms/{print-op-graph-backedges.mlir => print-op-graph-back-edges.mlir} (79%)
 create mode 100644 mlir/test/Transforms/print-op-graph-cycles.mlir

diff --git a/mlir/lib/Transforms/ViewOpGraph.cpp b/mlir/lib/Transforms/ViewOpGraph.cpp
index bbd95252ee614d..c2eb2b893cea4c 100644
--- a/mlir/lib/Transforms/ViewOpGraph.cpp
+++ b/mlir/lib/Transforms/ViewOpGraph.cpp
@@ -127,6 +127,12 @@ class PrintOpPass : public impl::ViewOpGraphBase<PrintOpPass> {
   /// Emit all edges. This function should be called after all nodes have been
   /// emitted.
   void emitAllEdgeStmts() {
+    if (printDataFlowEdges) {
+      for (const auto &[value, node, label] : dataFlowEdges) {
+        emitEdgeStmt(valueToNode[value], node, label, kLineStyleDataFlow);
+      }
+    }
+
     for (const std::string &edge : edges)
       os << edge << ";\n";
     edges.clear();
@@ -281,16 +287,10 @@ class PrintOpPass : public impl::ViewOpGraphBase<PrintOpPass> {
       for (BlockArgument &blockArg : block.getArguments())
         valueToNode[blockArg] = emitNodeStmt(getLabel(blockArg));
 
-      SmallVector<Operation *> sortedOperations;
-      for (Operation &op : block) {
-        sortedOperations.push_back(&op);
-      }
-      computeTopologicalSorting(sortedOperations);
-
       // Emit a node for each operation.
       std::optional<Node> prevNode;
-      for (Operation *op : sortedOperations) {
-        Node nextNode = processOperation(op);
+      for (Operation &op : block) {
+        Node nextNode = processOperation(&op);
         if (printControlFlowEdges && prevNode)
           emitEdgeStmt(*prevNode, nextNode, /*label=*/"",
                        kLineStyleControlFlow);
@@ -320,9 +320,8 @@ class PrintOpPass : public impl::ViewOpGraphBase<PrintOpPass> {
     if (printDataFlowEdges) {
       unsigned numOperands = op->getNumOperands();
       for (unsigned i = 0; i < numOperands; i++)
-        emitEdgeStmt(valueToNode[op->getOperand(i)], node,
-                     /*label=*/numOperands == 1 ? "" : std::to_string(i),
-                     kLineStyleDataFlow);
+        dataFlowEdges.push_back({op->getOperand(i), node,
+                                 numOperands == 1 ? "" : std::to_string(i)});
     }
 
     for (Value result : op->getResults())
@@ -351,6 +350,8 @@ class PrintOpPass : public impl::ViewOpGraphBase<PrintOpPass> {
   std::vector<std::string> edges;
   /// Mapping of SSA values to Graphviz nodes/clusters.
   DenseMap<Value, Node> valueToNode;
+  /// Output for data flow edges is delayed until the end to handle cycles
+  std::vector<std::tuple<Value, Node, std::string>> dataFlowEdges;
   /// Counter for generating unique node/subgraph identifiers.
   int counter = 0;
 
diff --git a/mlir/test/Transforms/print-op-graph-backedges.mlir b/mlir/test/Transforms/print-op-graph-back-edges.mlir
similarity index 79%
rename from mlir/test/Transforms/print-op-graph-backedges.mlir
rename to mlir/test/Transforms/print-op-graph-back-edges.mlir
index cd03bd0c1c298f..ed922dd7cb13bd 100644
--- a/mlir/test/Transforms/print-op-graph-backedges.mlir
+++ b/mlir/test/Transforms/print-op-graph-back-edges.mlir
@@ -8,13 +8,13 @@
 //       DFG:     subgraph cluster_3 {
 //       DFG:       v4 [label = " ", shape = plain];
 //       DFG:       label = "";
-//       DFG:       v5 [fillcolor = "0.333333 1.0 1.0", label = "arith.constant : (index)\n\nvalue: 0 : index", shape = ellipse, style = filled];
-//       DFG:       v6 [fillcolor = "0.333333 1.0 1.0", label = "arith.constant : (index)\n\nvalue: 1 : index", shape = ellipse, style = filled];
-//       DFG:       v7 [fillcolor = "0.000000 1.0 1.0", label = "arith.addi : (index)\n\noverflowFlags: #arith.overflow<none...", shape = ellipse, style = filled];
+//       DFG:       v5 [fillcolor = "0.000000 1.0 1.0", label = "arith.addi : (index)\n\noverflowFlags: #arith.overflow<none...", shape = ellipse, style = filled];
+//       DFG:       v6 [fillcolor = "0.333333 1.0 1.0", label = "arith.constant : (index)\n\nvalue: 0 : index", shape = ellipse, style = filled];
+//       DFG:       v7 [fillcolor = "0.333333 1.0 1.0", label = "arith.constant : (index)\n\nvalue: 1 : index", shape = ellipse, style = filled];
 //       DFG:     }
 //       DFG:   }
-//       DFG:   v5 -> v7 [label = "0", style = solid];
-//       DFG:   v6 -> v7 [label = "1", style = solid];
+//       DFG:   v6 -> v5 [label = "0", style = solid];
+//       DFG:   v7 -> v5 [label = "1", style = solid];
 //       DFG: }
 
 module {
diff --git a/mlir/test/Transforms/print-op-graph-cycles.mlir b/mlir/test/Transforms/print-op-graph-cycles.mlir
new file mode 100644
index 00000000000000..7e4eb5616a28b3
--- /dev/null
+++ b/mlir/test/Transforms/print-op-graph-cycles.mlir
@@ -0,0 +1,51 @@
+// RUN: mlir-opt -view-op-graph -allow-unregistered-dialect %s -o %t 2>&1 | FileCheck -check-prefix=DFG %s
+
+// DFG-LABEL: digraph G {
+//       DFG:   compound = true;
+//       DFG:   subgraph cluster_1 {
+//       DFG:     v2 [label = " ", shape = plain];
+//       DFG:     label = "builtin.module : ()\n";
+//       DFG:     subgraph cluster_3 {
+//       DFG:       v4 [label = " ", shape = plain];
+//       DFG:       label = "";
+//       DFG:       subgraph cluster_5 {
+//       DFG:         v6 [label = " ", shape = plain];
+//       DFG:         label = "test.graph_region : ()\n";
+//       DFG:         subgraph cluster_7 {
+//       DFG:           v8 [label = " ", shape = plain];
+//       DFG:           label = "";
+//       DFG:           v9 [fillcolor = "0.000000 1.0 1.0", label = "op1 : (i32)\n", shape = ellipse, style = filled];
+//       DFG:           subgraph cluster_10 {
+//       DFG:             v11 [label = " ", shape = plain];
+//       DFG:             label = "test.ssacfg_region : (i32)\n";
+//       DFG:             subgraph cluster_12 {
+//       DFG:               v13 [label = " ", shape = plain];
+//       DFG:               label = "";
+//       DFG:               v14 [fillcolor = "0.166667 1.0 1.0", label = "op2 : (i32)\n", shape = ellipse, style = filled];
+//       DFG:             }
+//       DFG:           }
+//       DFG:           v15 [fillcolor = "0.166667 1.0 1.0", label = "op2 : (i32)\n", shape = ellipse, style = filled];
+//       DFG:           v16 [fillcolor = "0.500000 1.0 1.0", label = "op3 : (i32)\n", shape = ellipse, style = filled];
+//       DFG:         }
+//       DFG:       }
+//       DFG:     }
+//       DFG:   }
+//       DFG:   v9 -> v9 [label = "0", style = solid];
+//       DFG:   v15 -> v9 [label = "1", style = solid];
+//       DFG:   v9 -> v14 [label = "0", style = solid];
+//       DFG:   v11 -> v14 [ltail = cluster_10, style = solid];
+//       DFG:   v15 -> v14 [label = "2", style = solid];
+//       DFG:   v16 -> v14 [label = "3", style = solid];
+//       DFG:   v9 -> v15 [label = "0", style = solid];
+//       DFG:   v16 -> v15 [label = "1", style = solid];
+//       DFG:   v9 -> v16 [label = "", style = solid];
+//       DFG: }
+
+"test.graph_region"() ({ // A Graph region
+  %1 = "op1"(%1, %3) : (i32, i32) -> (i32)  // OK: %1, %3 allowed here
+  %2 = "test.ssacfg_region"() ({
+     %5 = "op2"(%1, %2, %3, %4) : (i32, i32, i32, i32) -> (i32) // OK: %1, %2, %3, %4 all defined in the containing region
+  }) : () -> (i32)
+  %3 = "op2"(%1, %4) : (i32, i32) -> (i32)  // OK: %4 allowed here
+  %4 = "op3"(%1) : (i32) -> (i32)
+}) : () -> ()



More information about the Mlir-commits mailing list