[llvm] [DDG][NFC] Colorize DDG dot graph (PR #181618)

Madhur Amilkanthwar via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 16 02:47:06 PST 2026


https://github.com/madhur13490 updated https://github.com/llvm/llvm-project/pull/181618

>From fb479e967de341f678c2fe57481700c8edd50237 Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <madhura at nvidia.com>
Date: Sun, 15 Feb 2026 23:39:10 -0800
Subject: [PATCH 1/2] [DDG][NFC] Colorize DDG dot graph

All blocks and edges are currently colored black which makes it
difficult to distinguish while looking at huge graph.

This simple patch implements the following colorization to make it
visually more distinguishable.

1. Pi-blocks - styled to rounded, filled, light-yellow fill, dark orange
   border
2. Multi-instruction blocks - Light cyan fill
3. MemoryDependence edges are now colored red.
4. Register def-use edges are now colored blue.

This patch implements `getNodeAttributes()` to return the string of
attributes to apply to the node.
---
 llvm/include/llvm/Analysis/DDGPrinter.h |  4 ++++
 llvm/lib/Analysis/DDGPrinter.cpp        | 29 +++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/llvm/include/llvm/Analysis/DDGPrinter.h b/llvm/include/llvm/Analysis/DDGPrinter.h
index 4aa154d173bad..2ed73ee2b59e7 100644
--- a/llvm/include/llvm/Analysis/DDGPrinter.h
+++ b/llvm/include/llvm/Analysis/DDGPrinter.h
@@ -64,6 +64,10 @@ struct DOTGraphTraits<const DataDependenceGraph *>
   /// will be printed when their containing pi-block is being printed.
   bool isNodeHidden(const DDGNode *Node, const DataDependenceGraph *G);
 
+  /// Return DOT attributes for a node (e.g. border and fill for pi-blocks).
+  static std::string getNodeAttributes(const DDGNode *Node,
+                                       const DataDependenceGraph *G);
+
 private:
   /// Print a DDG node in concise form.
   static std::string getSimpleNodeLabel(const DDGNode *Node,
diff --git a/llvm/lib/Analysis/DDGPrinter.cpp b/llvm/lib/Analysis/DDGPrinter.cpp
index 6b5acd204ec7f..4647e4dc343f3 100644
--- a/llvm/lib/Analysis/DDGPrinter.cpp
+++ b/llvm/lib/Analysis/DDGPrinter.cpp
@@ -82,6 +82,17 @@ bool DDGDotGraphTraits::isNodeHidden(const DDGNode *Node,
   return Graph->getPiBlock(*Node) != nullptr;
 }
 
+std::string DDGDotGraphTraits::getNodeAttributes(const DDGNode *Node,
+                                                const DataDependenceGraph *) {
+  if (isa<PiBlockDDGNode>(Node))
+    return "shape=box, style=\"rounded,filled\", fillcolor=lightyellow, "
+           "color=darkorange, penwidth=3";
+  if (isa<SimpleDDGNode>(Node) &&
+      Node->getKind() == DDGNode::NodeKind::MultiInstruction)
+    return "style=filled, fillcolor=lightcyan";
+  return "";
+}
+
 std::string
 DDGDotGraphTraits::getSimpleNodeLabel(const DDGNode *Node,
                                       const DataDependenceGraph *G) {
@@ -132,6 +143,15 @@ std::string DDGDotGraphTraits::getSimpleEdgeAttributes(
   raw_string_ostream OS(Str);
   DDGEdge::EdgeKind Kind = Edge->getKind();
   OS << "label=\"[" << Kind << "]\"";
+  // EdgeKind to color mapping:
+  // - MemoryDependence: red
+  // - RegisterDefUse: blue
+  // - Rooted: black
+  // - Unknown: black
+  if (Kind == DDGEdge::EdgeKind::MemoryDependence)
+    OS << ", color=red";
+  else if (Kind == DDGEdge::EdgeKind::RegisterDefUse)
+    OS << ", color=blue";
   return OS.str();
 }
 
@@ -146,5 +166,14 @@ std::string DDGDotGraphTraits::getVerboseEdgeAttributes(
   else
     OS << Kind;
   OS << "]\"";
+  // EdgeKind to color mapping:
+  // - MemoryDependence: red
+  // - RegisterDefUse: blue
+  // - Rooted: black
+  // - Unknown: black
+  if (Kind == DDGEdge::EdgeKind::MemoryDependence)
+    OS << ", color=red";
+  else if (Kind == DDGEdge::EdgeKind::RegisterDefUse)
+    OS << ", color=blue";
   return OS.str();
 }

>From 7b0e5ace21a1473f3c270969909098e6a40ba27f Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <madhura at nvidia.com>
Date: Mon, 16 Feb 2026 02:46:38 -0800
Subject: [PATCH 2/2] fixup! [DDG][NFC] fix failing test

---
 llvm/test/Analysis/DDG/print-dot-ddg.ll | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/llvm/test/Analysis/DDG/print-dot-ddg.ll b/llvm/test/Analysis/DDG/print-dot-ddg.ll
index 51e950d0acf6c..d4926feea3a5f 100644
--- a/llvm/test/Analysis/DDG/print-dot-ddg.ll
+++ b/llvm/test/Analysis/DDG/print-dot-ddg.ll
@@ -22,22 +22,22 @@ target datalayout = "e-m:e-i64:64-n32:64-v256:256:256-v512:512:512"
 ; CHECK-NEXT: label="DDG for 'foo.for.body'";
 ; CHECK: {{Node0x.*}} [shape=record,label="{\<kind:root\>\nroot\n}"]
 ; CHECK: {{Node0x.*}} -> {{Node0x.*}}[label="[rooted]"]
-; CHECK-COUNT-6: {{Node0x.*}} -> {{Node0x.*}}[label="[def-use]"]
+; CHECK-COUNT-6: {{Node0x.*}} -> {{Node0x.*}}[label="[def-use]", color=blue]
 ; CHECK-NOT: {{Node0x.*}} -> {{Node0x.*}}[label="[def-use]"]
 ; CHECK: [shape=record,label="{\<kind:single-instruction\>\n  %arrayidx10 = getelementptr inbounds float, ptr %B, i64 %indvars.iv.next\n}"];
-; CHECK: [shape=record,label="{\<kind:multi-instruction\>\n  %arrayidx = getelementptr inbounds float, ptr %A, i64 %indvars.iv\n  %0 = load float, ptr %arrayidx, align 4\n}"];
-; CHECK: {{Node0x.*}} -> {{Node0x.*}}[label="[consistent anti [0|<]!, consistent input [0|<]!]"]
-; CHECK: [shape=record,label="{\<kind:pi-block\>\n--- start of nodes in pi-block ---\n\<kind:single-instruction\>\n  %1 = load float, ptr %arrayidx2, align 4\n\n\<kind:single-instruction\>\n  %add = fadd fast float %0, %1\n\n\<kind:single-instruction\>\n  store float %add, ptr %arrayidx4, align 4\n\n\<kind:multi-instruction\>\n  %2 = load float, ptr %arrayidx6, align 4\n  %add7 = fadd fast float %2, 1.000000e+00\n\n\<kind:single-instruction\>\n  store float %add7, ptr %arrayidx10, align 4\n--- end of nodes in pi-block ---\n}"];
+; CHECK: [shape=record,style=filled, fillcolor=lightcyan,label="{\<kind:multi-instruction\>\n  %arrayidx = getelementptr inbounds float, ptr %A, i64 %indvars.iv\n  %0 = load float, ptr %arrayidx, align 4\n}"];
+; CHECK: {{Node0x.*}} -> {{Node0x.*}}[label="[consistent anti [0|<]!, consistent input [0|<]!]", color=red]
+; CHECK: [shape=record,shape=box, style="rounded,filled", fillcolor=lightyellow, color=darkorange, penwidth=3,label="{\<kind:pi-block\>\n--- start of nodes in pi-block ---\n\<kind:single-instruction\>\n  %1 = load float, ptr %arrayidx2, align 4\n\n\<kind:single-instruction\>\n  %add = fadd fast float %0, %1\n\n\<kind:single-instruction\>\n  store float %add, ptr %arrayidx4, align 4\n\n\<kind:multi-instruction\>\n  %2 = load float, ptr %arrayidx6, align 4\n  %add7 = fadd fast float %2, 1.000000e+00\n\n\<kind:single-instruction\>\n  store float %add7, ptr %arrayidx10, align 4\n--- end of nodes in pi-block ---\n}"];
 
 ; CHECK-ONLY: digraph "DDG for 'foo.for.body'"
 ; CHECK-ONLY-NEXT: label="DDG for 'foo.for.body'";
-; CHECK-ONLY: [shape=record,label="{pi-block\nwith\n2 nodes\n}"];
-; CHECK-ONLY-COUNT-6: {{Node0x.*}} -> {{Node0x.*}}[label="[def-use]"];
+; CHECK-ONLY: [shape=record,shape=box, style="rounded,filled", fillcolor=lightyellow, color=darkorange, penwidth=3,label="{pi-block\nwith\n2 nodes\n}"];
+; CHECK-ONLY-COUNT-6: {{Node0x.*}} -> {{Node0x.*}}[label="[def-use]", color=blue];
 ; CHECK-NOT: {{Node0x.*}} -> {{Node0x.*}}[label="[def-use]"];
 ; CHECK-ONLY: [shape=record,label="{  %arrayidx10 = getelementptr inbounds float, ptr %B, i64 %indvars.iv.next\n}"];
-; CHECK-ONLY: [shape=record,label="{  %arrayidx = getelementptr inbounds float, ptr %A, i64 %indvars.iv\n  %0 = load float, ptr %arrayidx, align 4\n}"];
-; CHECK-ONLY: {{Node0x.*}} -> {{Node0x.*}}[label="[memory]"]
-; CHECK-ONLY: [shape=record,label="{pi-block\nwith\n5 nodes\n}"];
+; CHECK-ONLY: [shape=record,style=filled, fillcolor=lightcyan,label="{  %arrayidx = getelementptr inbounds float, ptr %A, i64 %indvars.iv\n  %0 = load float, ptr %arrayidx, align 4\n}"];
+; CHECK-ONLY: {{Node0x.*}} -> {{Node0x.*}}[label="[memory]", color=red]
+; CHECK-ONLY: [shape=record,shape=box, style="rounded,filled", fillcolor=lightyellow, color=darkorange, penwidth=3,label="{pi-block\nwith\n5 nodes\n}"];
 
 define void @foo(ptr noalias %A, ptr noalias %B, i32 signext %n) {
 entry:



More information about the llvm-commits mailing list