[llvm] 32a8260 - -dot-machine-cfg for printing MachineFunction to a dot file
Christudasan Devadasan via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 22 00:19:56 PDT 2022
Author: Christudasan Devadasan
Date: 2022-09-22T12:48:33+05:30
New Revision: 32a8260ccc8bc87134df6417c6deb0f4172bc4bf
URL: https://github.com/llvm/llvm-project/commit/32a8260ccc8bc87134df6417c6deb0f4172bc4bf
DIFF: https://github.com/llvm/llvm-project/commit/32a8260ccc8bc87134df6417c6deb0f4172bc4bf.diff
LOG: -dot-machine-cfg for printing MachineFunction to a dot file
This pass allows a user to dump a MIR function to a dot file
and view it as a graph. It is targeted to provide a similar
functionality as -dot-cfg pass on LLVM-IR. As of now the pass
also support below flags:
-dot-mcfg-only [optional][won't print instructions in the
graph just block name]
-mcfg-dot-filename-prefix [optional][prefix to add to output dot file]
-mcfg-func-name [optional] [specify function name or it's
substring, handy if mir file contains multiple functions and
you need to see graph of just one]
More flags and details can be introduced as per the requirements
in future. This pass is inspired from -dot-cfg IR pass and APIs
are written in almost identical format.
Patch by Yashwant Singh <Yashwant.Singh at amd.com> (yassingh)
Reviewed By: arsenm
Differential Revision: https://reviews.llvm.org/D133709
Added:
llvm/include/llvm/CodeGen/MachineCFGPrinter.h
llvm/lib/CodeGen/MachineCFGPrinter.cpp
llvm/test/Analysis/DotMachineCFG/AMDGPU/functions.mir
llvm/test/Analysis/DotMachineCFG/AMDGPU/irreducible.mir
llvm/test/Analysis/DotMachineCFG/AMDGPU/lit.local.cfg
Modified:
llvm/include/llvm/Analysis/CFGPrinter.h
llvm/include/llvm/CodeGen/MachinePassRegistry.def
llvm/include/llvm/CodeGen/Passes.h
llvm/include/llvm/InitializePasses.h
llvm/lib/CodeGen/CMakeLists.txt
llvm/lib/CodeGen/CodeGen.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/CFGPrinter.h b/llvm/include/llvm/Analysis/CFGPrinter.h
index 768cda59c57de..5def897839a4c 100644
--- a/llvm/include/llvm/Analysis/CFGPrinter.h
+++ b/llvm/include/llvm/Analysis/CFGPrinter.h
@@ -119,81 +119,96 @@ struct GraphTraits<DOTFuncInfo *> : public GraphTraits<const BasicBlock *> {
}
};
+template <typename BasicBlockT>
+std::string SimpleNodeLabelString(const BasicBlockT *Node) {
+ if (!Node->getName().empty())
+ return Node->getName().str();
+
+ std::string Str;
+ raw_string_ostream OS(Str);
+
+ Node->printAsOperand(OS, false);
+ return OS.str();
+}
+
+template <typename BasicBlockT>
+std::string CompleteNodeLabelString(
+ const BasicBlockT *Node,
+ function_ref<void(raw_string_ostream &, const BasicBlockT &)>
+ HandleBasicBlock,
+ function_ref<void(std::string &, unsigned &, unsigned)>
+ HandleComment) {
+
+ 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')
+ OutStr.erase(OutStr.begin());
+
+ unsigned ColNum = 0;
+ unsigned LastSpace = 0;
+ for (unsigned i = 0; i != OutStr.length(); ++i) {
+ if (OutStr[i] == '\n') { // Left justify
+ OutStr[i] = '\\';
+ OutStr.insert(OutStr.begin() + i + 1, 'l');
+ ColNum = 0;
+ LastSpace = 0;
+ } else if (OutStr[i] == ';') { // Delete comments!
+ unsigned Idx = OutStr.find('\n', i + 1); // Find end of line
+ HandleComment(OutStr, i, Idx);
+ } else if (ColNum == MaxColumns) { // Wrap lines.
+ // Wrap very long names even though we can't find a space.
+ if (!LastSpace)
+ LastSpace = i;
+ OutStr.insert(LastSpace, "\\l...");
+ ColNum = i - LastSpace;
+ LastSpace = 0;
+ i += 3; // The loop will advance 'i' again.
+ } else
+ ++ColNum;
+ if (OutStr[i] == ' ')
+ LastSpace = i;
+ }
+ return OutStr;
+}
+
template <>
struct DOTGraphTraits<DOTFuncInfo *> : public DefaultDOTGraphTraits {
// Cache for is hidden property
- llvm::DenseMap<const BasicBlock *, bool> isOnDeoptOrUnreachablePath;
+ DenseMap<const BasicBlock *, bool> isOnDeoptOrUnreachablePath;
DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
+ static void eraseComment(std::string &OutStr, unsigned &I, unsigned Idx) {
+ OutStr.erase(OutStr.begin() + I, OutStr.begin() + Idx);
+ --I;
+ }
+
static std::string getGraphName(DOTFuncInfo *CFGInfo) {
return "CFG for '" + CFGInfo->getFunction()->getName().str() + "' function";
}
static std::string getSimpleNodeLabel(const BasicBlock *Node, DOTFuncInfo *) {
- if (!Node->getName().empty())
- return Node->getName().str();
-
- std::string Str;
- raw_string_ostream OS(Str);
-
- Node->printAsOperand(OS, false);
- return OS.str();
- }
-
- static void eraseComment(std::string &OutStr, unsigned &I, unsigned Idx) {
- OutStr.erase(OutStr.begin() + I, OutStr.begin() + Idx);
- --I;
+ return SimpleNodeLabelString(Node);
}
static std::string getCompleteNodeLabel(
const BasicBlock *Node, DOTFuncInfo *,
- llvm::function_ref<void(raw_string_ostream &, const BasicBlock &)>
+ function_ref<void(raw_string_ostream &, const BasicBlock &)>
HandleBasicBlock = [](raw_string_ostream &OS,
const BasicBlock &Node) -> void { OS << Node; },
- llvm::function_ref<void(std::string &, unsigned &, unsigned)>
+ function_ref<void(std::string &, unsigned &, unsigned)>
HandleComment = eraseComment) {
- 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')
- OutStr.erase(OutStr.begin());
-
- // Process string output to make it nicer...
- unsigned ColNum = 0;
- unsigned LastSpace = 0;
- for (unsigned i = 0; i != OutStr.length(); ++i) {
- if (OutStr[i] == '\n') { // Left justify
- OutStr[i] = '\\';
- OutStr.insert(OutStr.begin() + i + 1, 'l');
- ColNum = 0;
- LastSpace = 0;
- } else if (OutStr[i] == ';') { // Delete comments!
- unsigned Idx = OutStr.find('\n', i + 1); // Find end of line
- HandleComment(OutStr, i, Idx);
- } else if (ColNum == MaxColumns) { // Wrap lines.
- // Wrap very long names even though we can't find a space.
- if (!LastSpace)
- LastSpace = i;
- OutStr.insert(LastSpace, "\\l...");
- ColNum = i - LastSpace;
- LastSpace = 0;
- i += 3; // The loop will advance 'i' again.
- } else
- ++ColNum;
- if (OutStr[i] == ' ')
- LastSpace = i;
- }
- return OutStr;
+ return CompleteNodeLabelString(Node, HandleBasicBlock, HandleComment);
}
std::string getNodeLabel(const BasicBlock *Node, DOTFuncInfo *CFGInfo) {
diff --git a/llvm/include/llvm/CodeGen/MachineCFGPrinter.h b/llvm/include/llvm/CodeGen/MachineCFGPrinter.h
new file mode 100644
index 0000000000000..ea3ff5a5c828b
--- /dev/null
+++ b/llvm/include/llvm/CodeGen/MachineCFGPrinter.h
@@ -0,0 +1,92 @@
+//===-- MachineCFGPrinter.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/CFGPrinter.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Support/DOTGraphTraits.h"
+
+namespace llvm {
+
+template <class GraphType> struct GraphTraits;
+class DOTMachineFuncInfo {
+private:
+ const MachineFunction *F;
+
+public:
+ DOTMachineFuncInfo(const MachineFunction *F) : F(F) {}
+
+ const MachineFunction *getFunction() const { return this->F; }
+};
+
+template <>
+struct GraphTraits<DOTMachineFuncInfo *>
+ : public GraphTraits<const MachineBasicBlock *> {
+ static NodeRef getEntryNode(DOTMachineFuncInfo *CFGInfo) {
+ return &(CFGInfo->getFunction()->front());
+ }
+
+ // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
+ using nodes_iterator = pointer_iterator<MachineFunction::const_iterator>;
+
+ static nodes_iterator nodes_begin(DOTMachineFuncInfo *CFGInfo) {
+ return nodes_iterator(CFGInfo->getFunction()->begin());
+ }
+
+ static nodes_iterator nodes_end(DOTMachineFuncInfo *CFGInfo) {
+ return nodes_iterator(CFGInfo->getFunction()->end());
+ }
+
+ static size_t size(DOTMachineFuncInfo *CFGInfo) {
+ return CFGInfo->getFunction()->size();
+ }
+};
+
+template <>
+struct DOTGraphTraits<DOTMachineFuncInfo *> : public DefaultDOTGraphTraits {
+
+ DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
+
+ static void eraseComment(std::string &OutStr, unsigned &I, unsigned Idx) {
+ OutStr.erase(OutStr.begin() + I, OutStr.begin() + Idx);
+ --I;
+ }
+
+ static std::string getSimpleNodeLabel(const MachineBasicBlock *Node,
+ DOTMachineFuncInfo *) {
+ return SimpleNodeLabelString(Node);
+ }
+
+ static std::string getCompleteNodeLabel(
+ const MachineBasicBlock *Node, DOTMachineFuncInfo *,
+ function_ref<void(raw_string_ostream &, const MachineBasicBlock &)>
+ HandleBasicBlock =
+ [](raw_string_ostream &OS,
+ const MachineBasicBlock &Node) -> void { OS << Node; },
+ function_ref<void(std::string &, unsigned &, unsigned)>
+ HandleComment = eraseComment) {
+ return CompleteNodeLabelString(Node, HandleBasicBlock, HandleComment);
+ }
+
+ std::string getNodeLabel(const MachineBasicBlock *Node,
+ DOTMachineFuncInfo *CFGInfo) {
+ if (isSimple())
+ return getSimpleNodeLabel(Node, CFGInfo);
+
+ return getCompleteNodeLabel(Node, CFGInfo);
+ }
+
+ static std::string getGraphName(DOTMachineFuncInfo *CFGInfo) {
+ return "Machine CFG for '" + CFGInfo->getFunction()->getName().str() +
+ "' function";
+ }
+};
+} // namespace llvm
diff --git a/llvm/include/llvm/CodeGen/MachinePassRegistry.def b/llvm/include/llvm/CodeGen/MachinePassRegistry.def
index 077b71327c04c..617214aaca3c1 100644
--- a/llvm/include/llvm/CodeGen/MachinePassRegistry.def
+++ b/llvm/include/llvm/CodeGen/MachinePassRegistry.def
@@ -159,6 +159,7 @@ DUMMY_MACHINE_FUNCTION_PASS("reg-usage-collector", RegUsageInfoCollectorPass, ()
DUMMY_MACHINE_FUNCTION_PASS("funclet-layout", FuncletLayoutPass, ())
DUMMY_MACHINE_FUNCTION_PASS("stackmap-liveness", StackMapLivenessPass, ())
DUMMY_MACHINE_FUNCTION_PASS("removeredundantdebugvalues", RemoveRedundantDebugValuesPass, ())
+DUMMY_MACHINE_FUNCTION_PASS("dot-machine-cfg", MachineCFGPrinter, ())
DUMMY_MACHINE_FUNCTION_PASS("livedebugvalues", LiveDebugValuesPass, ())
DUMMY_MACHINE_FUNCTION_PASS("early-tailduplication", EarlyTailDuplicatePass, ())
DUMMY_MACHINE_FUNCTION_PASS("opt-phis", OptimizePHIsPass, ())
diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h
index a97fd5cc78c70..2ec803aaa66c5 100644
--- a/llvm/include/llvm/CodeGen/Passes.h
+++ b/llvm/include/llvm/CodeGen/Passes.h
@@ -408,6 +408,9 @@ namespace llvm {
/// RemoveRedundantDebugValues pass.
extern char &RemoveRedundantDebugValuesID;
+ /// MachineCFGPrinter pass.
+ extern char &MachineCFGPrinterID;
+
/// LiveDebugValues pass
extern char &LiveDebugValuesID;
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index b7e5a7f88e299..6a5d91661b03c 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -277,6 +277,7 @@ void initializeMachineBlockFrequencyInfoPass(PassRegistry&);
void initializeMachineBlockPlacementPass(PassRegistry&);
void initializeMachineBlockPlacementStatsPass(PassRegistry&);
void initializeMachineBranchProbabilityInfoPass(PassRegistry&);
+void initializeMachineCFGPrinterPass(PassRegistry &);
void initializeMachineCSEPass(PassRegistry&);
void initializeMachineCombinerPass(PassRegistry&);
void initializeMachineCopyPropagationPass(PassRegistry&);
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index 5ed42c7def2d4..604f2c630f853 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -101,6 +101,7 @@ add_llvm_component_library(LLVMCodeGen
MachineBlockFrequencyInfo.cpp
MachineBlockPlacement.cpp
MachineBranchProbabilityInfo.cpp
+ MachineCFGPrinter.cpp
MachineCombiner.cpp
MachineCopyPropagation.cpp
MachineCSE.cpp
diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp
index 219032e30cc93..87090ec369934 100644
--- a/llvm/lib/CodeGen/CodeGen.cpp
+++ b/llvm/lib/CodeGen/CodeGen.cpp
@@ -69,6 +69,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializeMachineBlockFrequencyInfoPass(Registry);
initializeMachineBlockPlacementPass(Registry);
initializeMachineBlockPlacementStatsPass(Registry);
+ initializeMachineCFGPrinterPass(Registry);
initializeMachineCSEPass(Registry);
initializeMachineCombinerPass(Registry);
initializeMachineCopyPropagationPass(Registry);
diff --git a/llvm/lib/CodeGen/MachineCFGPrinter.cpp b/llvm/lib/CodeGen/MachineCFGPrinter.cpp
new file mode 100644
index 0000000000000..7bfb817713808
--- /dev/null
+++ b/llvm/lib/CodeGen/MachineCFGPrinter.cpp
@@ -0,0 +1,95 @@
+//===- MachineCFGPrinter.cpp - DOT Printer for Machine Functions ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the `-dot-machine-cfg` analysis pass, which emits
+// Machine Function in DOT format in file titled `<prefix>.<function-name>.dot.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MachineCFGPrinter.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/GraphWriter.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "dot-machine-cfg"
+
+static cl::opt<std::string>
+ MCFGFuncName("mcfg-func-name", cl::Hidden,
+ cl::desc("The name of a function (or its substring)"
+ " whose CFG is viewed/printed."));
+
+static cl::opt<std::string> MCFGDotFilenamePrefix(
+ "mcfg-dot-filename-prefix", cl::Hidden,
+ cl::desc("The prefix used for the Machine CFG dot file names."));
+
+static cl::opt<bool>
+ CFGOnly("dot-mcfg-only", cl::init(false), cl::Hidden,
+ cl::desc("Print only the CFG without blocks body"));
+
+static void writeMCFGToDotFile(MachineFunction &MF) {
+ std::string Filename =
+ (MCFGDotFilenamePrefix + "." + MF.getName() + ".dot").str();
+ errs() << "Writing '" << Filename << "'...";
+
+ std::error_code EC;
+ raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);
+
+ DOTMachineFuncInfo MCFGInfo(&MF);
+
+ if (!EC)
+ WriteGraph(File, &MCFGInfo, CFGOnly);
+ else
+ errs() << " error opening file for writing!";
+ errs() << '\n';
+}
+
+namespace {
+
+class MachineCFGPrinter : public MachineFunctionPass {
+public:
+ static char ID;
+
+ MachineCFGPrinter();
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesCFG();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+};
+
+} // namespace
+
+char MachineCFGPrinter::ID = 0;
+
+char &llvm::MachineCFGPrinterID = MachineCFGPrinter::ID;
+
+INITIALIZE_PASS(MachineCFGPrinter, DEBUG_TYPE, "Machine CFG Printer Pass",
+ false, true)
+
+/// Default construct and initialize the pass.
+MachineCFGPrinter::MachineCFGPrinter() : MachineFunctionPass(ID) {
+ initializeMachineCFGPrinterPass(*PassRegistry::getPassRegistry());
+}
+
+bool MachineCFGPrinter::runOnMachineFunction(MachineFunction &MF) {
+ if (!MCFGFuncName.empty() && !MF.getName().contains(MCFGFuncName))
+ return false;
+ errs() << "Writing Machine CFG for function ";
+ errs().write_escaped(MF.getName()) << '\n';
+
+ writeMCFGToDotFile(MF);
+ return false;
+}
diff --git a/llvm/test/Analysis/DotMachineCFG/AMDGPU/functions.mir b/llvm/test/Analysis/DotMachineCFG/AMDGPU/functions.mir
new file mode 100644
index 0000000000000..51daa8637621b
--- /dev/null
+++ b/llvm/test/Analysis/DotMachineCFG/AMDGPU/functions.mir
@@ -0,0 +1,24 @@
+# RUN: llc -mtriple=amdgcn-- -run-pass=dot-machine-cfg -mcfg-dot-filename-prefix=%t -mcfg-func-name=func2 -o - %s 2>&1 > /dev/null
+# RUN: FileCheck %s -input-file=%t.func2.dot --check-prefix=MCFG
+
+# MCFG-NOT: digraph "Machine CFG for 'func1' function"
+name: func1
+body: |
+ bb.0:
+ $sgpr0 = S_LOAD_DWORD_IMM $sgpr10_sgpr11, 0, 0
+ $sgpr1 = S_LOAD_DWORD_IMM $sgpr12_sgpr13, 0, 0
+ S_ENDPGM 0
+...
+
+# 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}"];
+---
+name: func2
+body: |
+ bb.0:
+ $sgpr0 = S_LOAD_DWORD_IMM $sgpr12_sgpr13, 0, 0
+ $sgpr1 = S_LOAD_DWORD_IMM $sgpr6_sgpr7, 0, 0
+ $sgpr2 = S_LOAD_DWORD_IMM $sgpr14_sgpr15, 0, 0
+ S_ENDPGM 0
+...
diff --git a/llvm/test/Analysis/DotMachineCFG/AMDGPU/irreducible.mir b/llvm/test/Analysis/DotMachineCFG/AMDGPU/irreducible.mir
new file mode 100644
index 0000000000000..e06aac2ab3f5a
--- /dev/null
+++ b/llvm/test/Analysis/DotMachineCFG/AMDGPU/irreducible.mir
@@ -0,0 +1,87 @@
+# RUN: llc -mtriple=amdgcn-- -run-pass=dot-machine-cfg -mcfg-dot-filename-prefix=%t -o - %s 2>&1 > /dev/null
+# RUN: FileCheck %s -input-file=%t.irreducible.dot --check-prefix=MCFG
+# RUN: llc -mtriple=amdgcn-- -run-pass=dot-machine-cfg -mcfg-dot-filename-prefix=%t -dot-mcfg-only -o - %s 2>&1 > /dev/null
+# RUN: FileCheck %s -input-file=%t.irreducible.dot --check-prefix=MCFG-ONLY
+
+# 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-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]*}} -> 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]*}} -> 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]*}} -> 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]*}} -> 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]*}} -> 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-ONLY: digraph "Machine CFG for 'irreducible' function"
+# MCFG-ONLY-NEXT: label="Machine CFG for 'irreducible' function"
+# MCFG-ONLY: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.0}"];
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.1}"];
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.2}"];
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.3}"];
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.4}"];
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.5}"];
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} -> Node{{[0-9A-Za-z]*}};
+# MCFG-ONLY-NEXT: Node{{[0-9A-Za-z]*}} [shape=record,label="{%bb.6}"];
+---
+name: irreducible
+tracksRegLiveness: true
+machineFunctionInfo:
+ isEntryFunction: true
+body: |
+ bb.0:
+ successors: %bb.1, %bb.2
+ liveins: $vgpr0, $vgpr1, $vgpr2, $sgpr4_sgpr5, $sgpr6_sgpr7, $sgpr8_sgpr9, $sgpr10_sgpr11, $sgpr14, $sgpr15, $sgpr16
+
+ %0:sreg_32 = IMPLICIT_DEF
+ %2:vgpr_32 = COPY $vgpr0
+ %3:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
+ S_CMP_EQ_U32 %0, 0, implicit-def $scc
+ S_CBRANCH_SCC1 %bb.1, implicit $scc
+ S_BRANCH %bb.2
+
+ bb.1:
+ %28:vgpr_32 = PHI %3, %bb.0, %49, %bb.5
+ %29:vgpr_32 = V_ADD_U32_e64 %28, 1, 0, implicit $exec
+ S_BRANCH %bb.3
+
+ bb.2:
+ %38:vgpr_32 = PHI %3, %bb.0, %49, %bb.4
+ %39:vgpr_32 = V_ADD_U32_e64 %38, 2, 0, implicit $exec
+
+ bb.3:
+ %49:vgpr_32 = PHI %29, %bb.1, %39, %bb.2
+
+ bb.4:
+ successors: %bb.2, %bb.5
+
+ %50:vgpr_32 = V_AND_B32_e32 3, %2, implicit $exec
+ %51:sreg_64 = V_CMP_EQ_U32_e64 %50, 2, implicit $exec
+ %52:sreg_64 = SI_IF killed %51:sreg_64, %bb.2, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+
+ bb.5:
+ successors: %bb.1, %bb.6
+ %61:sreg_64 = V_CMP_EQ_U32_e64 %50, 1, implicit $exec
+ %62:sreg_64 = SI_IF killed %61:sreg_64, %bb.1, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+
+ bb.6:
+ S_ENDPGM 0
+...
+
diff --git a/llvm/test/Analysis/DotMachineCFG/AMDGPU/lit.local.cfg b/llvm/test/Analysis/DotMachineCFG/AMDGPU/lit.local.cfg
new file mode 100644
index 0000000000000..2a665f06be72e
--- /dev/null
+++ b/llvm/test/Analysis/DotMachineCFG/AMDGPU/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'AMDGPU' in config.root.targets:
+ config.unsupported = True
More information about the llvm-commits
mailing list