[llvm] 3fee76c - Headers for basic blocks in CFG dot graphs
Artur Pilipenko via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 17 07:55:37 PDT 2023
Author: Marek Sedláček
Date: 2023-08-17T07:55:23-07:00
New Revision: 3fee76cff3431bebaa0068a39a7b0d0a645c823f
URL: https://github.com/llvm/llvm-project/commit/3fee76cff3431bebaa0068a39a7b0d0a645c823f
DIFF: https://github.com/llvm/llvm-project/commit/3fee76cff3431bebaa0068a39a7b0d0a645c823f.diff
LOG: Headers for basic blocks in CFG dot graphs
This change adds separators for basic block names, which makes it
easier to find a basic block based on its name and separates it
from the code.
Currently there is also a chance that the basic block label will
be present twice, that is in case the basic block has explicit
numbering, this change fixes this bug.
Differential Revision: https://reviews.llvm.org/D154102
Added:
Modified:
llvm/include/llvm/Analysis/CFGPrinter.h
llvm/test/Analysis/DotMachineCFG/AMDGPU/functions.mir
llvm/test/Analysis/DotMachineCFG/AMDGPU/irreducible.mir
llvm/test/Other/cfg_deopt_unreach.ll
polly/test/ScopDetect/dot-scops-npm.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/CFGPrinter.h b/llvm/include/llvm/Analysis/CFGPrinter.h
index 2d334c81bbdcd1..a1b2ba6aaf6bdd 100644
--- a/llvm/include/llvm/Analysis/CFGPrinter.h
+++ b/llvm/include/llvm/Analysis/CFGPrinter.h
@@ -147,16 +147,12 @@ std::string CompleteNodeLabelString(
enum { MaxColumns = 80 };
std::string Str;
raw_string_ostream OS(Str);
-
- if (Node->getName().empty()) {
- Node->printAsOperand(OS, false);
- OS << ':';
- }
-
HandleBasicBlock(OS, *Node);
std::string OutStr = OS.str();
- if (OutStr[0] == '\n')
+ // Remove "%" from BB name
+ if (OutStr[0] == '%') {
OutStr.erase(OutStr.begin());
+ }
unsigned ColNum = 0;
unsigned LastSpace = 0;
@@ -182,6 +178,8 @@ std::string CompleteNodeLabelString(
if (OutStr[i] == ' ')
LastSpace = i;
}
+ // Replace \l after BB name with | to separate it into header
+ OutStr.replace(OutStr.find_first_of('\\') + 1, 1, "|");
return OutStr;
}
@@ -206,11 +204,20 @@ struct DOTGraphTraits<DOTFuncInfo *> : public DefaultDOTGraphTraits {
return SimpleNodeLabelString(Node);
}
+ static void printBasicBlock(raw_string_ostream &OS, const BasicBlock &Node) {
+ // Prepend label name
+ Node.printAsOperand(OS, false);
+ OS << ":\n";
+ for (auto J = Node.begin(), JE = Node.end(); J != JE; ++J) {
+ const Instruction *Inst = &*J;
+ OS << *Inst << "\n";
+ }
+ }
+
static std::string getCompleteNodeLabel(
const BasicBlock *Node, DOTFuncInfo *,
function_ref<void(raw_string_ostream &, const BasicBlock &)>
- HandleBasicBlock = [](raw_string_ostream &OS,
- const BasicBlock &Node) -> void { OS << Node; },
+ HandleBasicBlock = printBasicBlock,
function_ref<void(std::string &, unsigned &, unsigned)>
HandleComment = eraseComment) {
return CompleteNodeLabelString(Node, HandleBasicBlock, HandleComment);
diff --git a/llvm/test/Analysis/DotMachineCFG/AMDGPU/functions.mir b/llvm/test/Analysis/DotMachineCFG/AMDGPU/functions.mir
index 51daa8637621b1..de6dc9c3a6231a 100644
--- a/llvm/test/Analysis/DotMachineCFG/AMDGPU/functions.mir
+++ b/llvm/test/Analysis/DotMachineCFG/AMDGPU/functions.mir
@@ -12,7 +12,7 @@ body: |
# MCFG: digraph "Machine CFG for 'func2' function"
# MCFG-NEXT: label="Machine CFG for 'func2' function"
-# MCFG: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.0:bb.0:\l $sgpr0 = S_LOAD_DWORD_IMM $sgpr12_sgpr13, 0, 0\l $sgpr1 = S_LOAD_DWORD_IMM $sgpr6_sgpr7, 0, 0\l $sgpr2 = S_LOAD_DWORD_IMM $sgpr14_sgpr15, 0, 0\l S_ENDPGM 0\l}"];
+# MCFG: Node{{[0-9A-Za-z]*}} [shape=record,label="{bb.0:| $sgpr0 = S_LOAD_DWORD_IMM $sgpr12_sgpr13, 0, 0\l $sgpr1 = S_LOAD_DWORD_IMM $sgpr6_sgpr7, 0, 0\l $sgpr2 = S_LOAD_DWORD_IMM $sgpr14_sgpr15, 0, 0\l S_ENDPGM 0\l}"];
---
name: func2
body: |
diff --git a/llvm/test/Analysis/DotMachineCFG/AMDGPU/irreducible.mir b/llvm/test/Analysis/DotMachineCFG/AMDGPU/irreducible.mir
index e06aac2ab3f5ab..8b63b10762a132 100644
--- a/llvm/test/Analysis/DotMachineCFG/AMDGPU/irreducible.mir
+++ b/llvm/test/Analysis/DotMachineCFG/AMDGPU/irreducible.mir
@@ -5,22 +5,22 @@
# MCFG: digraph "Machine CFG for 'irreducible' function"
# MCFG-NEXT: label="Machine CFG for 'irreducible' function"
-# MCFG: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.0:bb.0:\l successors: %bb.1(0x40000000), %bb.2(0x40000000)\l liveins: $vgpr0, $vgpr1, $vgpr2, $sgpr4_sgpr5, $sgpr6_sgpr7, $sgpr8_sgpr9,\l... $sgpr10_sgpr11, $sgpr14, $sgpr15, $sgpr16\l %0:sreg_32 = IMPLICIT_DEF\l %1:vgpr_32 = COPY $vgpr0\l %2:vgpr_32 = V_MOV_B32_e32 0, implicit $exec\l S_CMP_EQ_U32 %0:sreg_32, 0, implicit-def $scc\l S_CBRANCH_SCC1 %bb.1, implicit $scc\l S_BRANCH %bb.2\l}"];
+# MCFG: Node{{[0-9A-Za-z]*}} [shape=record,label="{bb.0:| successors: %bb.1(0x40000000), %bb.2(0x40000000)\l liveins: $vgpr0, $vgpr1, $vgpr2, $sgpr4_sgpr5, $sgpr6_sgpr7, $sgpr8_sgpr9,\l... $sgpr10_sgpr11, $sgpr14, $sgpr15, $sgpr16\l %0:sreg_32 = IMPLICIT_DEF\l %1:vgpr_32 = COPY $vgpr0\l %2:vgpr_32 = V_MOV_B32_e32 0, implicit $exec\l S_CMP_EQ_U32 %0:sreg_32, 0, implicit-def $scc\l S_CBRANCH_SCC1 %bb.1, implicit $scc\l S_BRANCH %bb.2\l}"];
# MCFG-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
# MCFG-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
-# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.1:bb.1:\l\l successors: %bb.3(0x80000000)\l\l %3:vgpr_32 = PHI %2:vgpr_32, %bb.0, %4:vgpr_32, %bb.5\l %5:vgpr_32 = V_ADD_U32_e64 %3:vgpr_32, 1, 0, implicit $exec\l S_BRANCH %bb.3\l}"];
+# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{bb.1:|\l successors: %bb.3(0x80000000)\l\l %3:vgpr_32 = PHI %2:vgpr_32, %bb.0, %4:vgpr_32, %bb.5\l %5:vgpr_32 = V_ADD_U32_e64 %3:vgpr_32, 1, 0, implicit $exec\l S_BRANCH %bb.3\l}"];
# MCFG-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
-# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.2:bb.2:\l\l successors: %bb.3(0x80000000)\l\l %6:vgpr_32 = PHI %2:vgpr_32, %bb.0, %4:vgpr_32, %bb.4\l %7:vgpr_32 = V_ADD_U32_e64 %6:vgpr_32, 2, 0, implicit $exec\l}"];
+# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{bb.2:|\l successors: %bb.3(0x80000000)\l\l %6:vgpr_32 = PHI %2:vgpr_32, %bb.0, %4:vgpr_32, %bb.4\l %7:vgpr_32 = V_ADD_U32_e64 %6:vgpr_32, 2, 0, implicit $exec\l}"];
# MCFG-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
-# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.3:bb.3:\l\l successors: %bb.4(0x80000000)\l\l %4:vgpr_32 = PHI %5:vgpr_32, %bb.1, %7:vgpr_32, %bb.2\l}"];
+# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{bb.3:|\l successors: %bb.4(0x80000000)\l\l %4:vgpr_32 = PHI %5:vgpr_32, %bb.1, %7:vgpr_32, %bb.2\l}"];
# MCFG-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
-# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.4:bb.4:\l\l successors: %bb.2(0x40000000), %bb.5(0x40000000)\l\l %8:vgpr_32 = V_AND_B32_e32 3, %1:vgpr_32, implicit $exec\l %9:sreg_64 = V_CMP_EQ_U32_e64 %8:vgpr_32, 2, implicit $exec\l %10:sreg_64 = SI_IF killed %9:sreg_64, %bb.2, implicit-def dead $exec,\l... implicit-def dead $scc, implicit $exec\l}"];
+# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{bb.4:|\l successors: %bb.2(0x40000000), %bb.5(0x40000000)\l\l %8:vgpr_32 = V_AND_B32_e32 3, %1:vgpr_32, implicit $exec\l %9:sreg_64 = V_CMP_EQ_U32_e64 %8:vgpr_32, 2, implicit $exec\l %10:sreg_64 = SI_IF killed %9:sreg_64, %bb.2, implicit-def dead $exec,\l... implicit-def dead $scc, implicit $exec\l}"];
# MCFG-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
# MCFG-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
-# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.5:bb.5:\l\l successors: %bb.1(0x40000000), %bb.6(0x40000000)\l\l %11:sreg_64 = V_CMP_EQ_U32_e64 %8:vgpr_32, 1, implicit $exec\l %12:sreg_64 = SI_IF killed %11:sreg_64, %bb.1, implicit-def dead $exec,\l... implicit-def dead $scc, implicit $exec\l}"];
+# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{bb.5:|\l successors: %bb.1(0x40000000), %bb.6(0x40000000)\l\l %11:sreg_64 = V_CMP_EQ_U32_e64 %8:vgpr_32, 1, implicit $exec\l %12:sreg_64 = SI_IF killed %11:sreg_64, %bb.1, implicit-def dead $exec,\l... implicit-def dead $scc, implicit $exec\l}"];
# MCFG-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
# MCFG-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
-# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.6:bb.6:\l\l\l S_ENDPGM 0\l}"];
+# MCFG-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{bb.6:|\l\l S_ENDPGM 0\l}"];
# MCFG-ONLY: digraph "Machine CFG for 'irreducible' function"
# MCFG-ONLY-NEXT: label="Machine CFG for 'irreducible' function"
diff --git a/llvm/test/Other/cfg_deopt_unreach.ll b/llvm/test/Other/cfg_deopt_unreach.ll
index 94895d7950c830..560c4d2aeeda4b 100644
--- a/llvm/test/Other/cfg_deopt_unreach.ll
+++ b/llvm/test/Other/cfg_deopt_unreach.ll
@@ -14,18 +14,18 @@ declare i8 @llvm.experimental.deoptimize.i8(...)
define i8 @callee(ptr %c) alwaysinline {
%c0 = load volatile i1, ptr %c
br i1 %c0, label %lleft, label %lright
-; NO-FLAGS: label="{lleft: \l %v0 = call i8 (...) @llvm.experimental.deoptimize.i8(i32 1) [ \"deopt\"(i32 1)\l... ]\l ret i8 %v0\l}"
-; DEOPT-NOT: label="{lleft: \l %v0 = call i8 (...) @llvm.experimental.deoptimize.i8(i32 1) [ \"deopt\"(i32 1)\l... ]\l ret i8 %v0\l}"
-; UNREACH: label="{lleft: \l %v0 = call i8 (...) @llvm.experimental.deoptimize.i8(i32 1) [ \"deopt\"(i32 1)\l... ]\l ret i8 %v0\l}"
-; BOTH-FLAGS-NOT: label="{lleft: \l %v0 = call i8 (...) @llvm.experimental.deoptimize.i8(i32 1) [ \"deopt\"(i32 1)\l... ]\l ret i8 %v0\l}"
+; NO-FLAGS: label="{lleft:| %v0 = call i8 (...) @llvm.experimental.deoptimize.i8(i32 1) [ \"deopt\"(i32 1)\l... ]\l ret i8 %v0\l}"
+; DEOPT-NOT: label="{lleft:| %v0 = call i8 (...) @llvm.experimental.deoptimize.i8(i32 1) [ \"deopt\"(i32 1)\l... ]\l ret i8 %v0\l}"
+; UNREACH: label="{lleft:| %v0 = call i8 (...) @llvm.experimental.deoptimize.i8(i32 1) [ \"deopt\"(i32 1)\l... ]\l ret i8 %v0\l}"
+; BOTH-FLAGS-NOT: label="{lleft:| %v0 = call i8 (...) @llvm.experimental.deoptimize.i8(i32 1) [ \"deopt\"(i32 1)\l... ]\l ret i8 %v0\l}"
lleft:
%v0 = call i8(...) @llvm.experimental.deoptimize.i8(i32 1) [ "deopt"(i32 1) ]
ret i8 %v0
-; NO-FLAGS: label="{lright: \l unreachable\l}"
-; DEOPT: label="{lright: \l unreachable\l}"
-; UNREACH-NOT: label="{lright: \l unreachable\l}"
-; BOTH-FLAGS-NOT: label="{lright: \l unreachable\l}"
+; NO-FLAGS: label="{lright:| unreachable\l}"
+; DEOPT: label="{lright:| unreachable\l}"
+; UNREACH-NOT: label="{lright:| unreachable\l}"
+; BOTH-FLAGS-NOT: label="{lright:| unreachable\l}"
lright:
unreachable
}
diff --git a/polly/test/ScopDetect/dot-scops-npm.ll b/polly/test/ScopDetect/dot-scops-npm.ll
index 30eefd1c18fd1b..722cd1e63c31ac 100644
--- a/polly/test/ScopDetect/dot-scops-npm.ll
+++ b/polly/test/ScopDetect/dot-scops-npm.ll
@@ -15,7 +15,7 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @func_npm(i32 %n, i32 %m, ptr noalias nonnull %A) {
; CHECK: digraph "Scop Graph for 'func_npm' function"
; CHECK-NEXT: label="Scop Graph for 'func_npm' function"
-; CHECK: Node0x[[EntryID:.*]] [shape=record,label="{entry:\l br label %outer.for\l}"];
+; CHECK: Node0x[[EntryID:.*]] [shape=record,label="{entry:| br label %outer.for\l}"];
; CHECK-NEXT: Node0x[[EntryID]] -> Node0x[[OUTER_FOR_ID:.*]];
; CHECK-NEXT: Node0x[[OUTER_FOR_ID]] [shape=record,label="{outer.for:
; CHECK-NEXT: Node0x[[OUTER_FOR_ID]] -> Node0x[[INNER_FOR_ID:.*]];
More information about the llvm-commits
mailing list