1 | //===-------- EdgeBundles.cpp - Bundles of CFG edges ----------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file provides the implementation of the EdgeBundles analysis. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/CodeGen/EdgeBundles.h" |
14 | #include "llvm/ADT/Twine.h" |
15 | #include "llvm/CodeGen/MachineBasicBlock.h" |
16 | #include "llvm/CodeGen/MachineFunction.h" |
17 | #include "llvm/CodeGen/Passes.h" |
18 | #include "llvm/InitializePasses.h" |
19 | #include "llvm/Support/CommandLine.h" |
20 | #include "llvm/Support/GraphWriter.h" |
21 | #include "llvm/Support/raw_ostream.h" |
22 | |
23 | using namespace llvm; |
24 | |
25 | static cl::opt<bool> |
26 | ViewEdgeBundles("view-edge-bundles" , cl::Hidden, |
27 | cl::desc("Pop up a window to show edge bundle graphs" )); |
28 | |
29 | char EdgeBundles::ID = 0; |
30 | |
31 | INITIALIZE_PASS(EdgeBundles, "edge-bundles" , "Bundle Machine CFG Edges" , |
32 | /* cfg = */true, /* is_analysis = */ true) |
33 | |
34 | char &llvm::EdgeBundlesID = EdgeBundles::ID; |
35 | |
36 | void EdgeBundles::getAnalysisUsage(AnalysisUsage &AU) const { |
37 | AU.setPreservesAll(); |
38 | MachineFunctionPass::getAnalysisUsage(AU); |
39 | } |
40 | |
41 | bool EdgeBundles::runOnMachineFunction(MachineFunction &mf) { |
42 | MF = &mf; |
43 | EC.clear(); |
44 | EC.grow(N: 2 * MF->getNumBlockIDs()); |
45 | |
46 | for (const auto &MBB : *MF) { |
47 | unsigned OutE = 2 * MBB.getNumber() + 1; |
48 | // Join the outgoing bundle with the ingoing bundles of all successors. |
49 | for (const MachineBasicBlock *Succ : MBB.successors()) |
50 | EC.join(a: OutE, b: 2 * Succ->getNumber()); |
51 | } |
52 | EC.compress(); |
53 | if (ViewEdgeBundles) |
54 | view(); |
55 | |
56 | // Compute the reverse mapping. |
57 | Blocks.clear(); |
58 | Blocks.resize(N: getNumBundles()); |
59 | |
60 | for (unsigned i = 0, e = MF->getNumBlockIDs(); i != e; ++i) { |
61 | unsigned b0 = getBundle(N: i, Out: false); |
62 | unsigned b1 = getBundle(N: i, Out: true); |
63 | Blocks[b0].push_back(Elt: i); |
64 | if (b1 != b0) |
65 | Blocks[b1].push_back(Elt: i); |
66 | } |
67 | |
68 | return false; |
69 | } |
70 | |
71 | namespace llvm { |
72 | |
73 | /// Specialize WriteGraph, the standard implementation won't work. |
74 | template<> |
75 | raw_ostream &WriteGraph<>(raw_ostream &O, const EdgeBundles &G, |
76 | bool ShortNames, |
77 | const Twine &Title) { |
78 | const MachineFunction *MF = G.getMachineFunction(); |
79 | |
80 | O << "digraph {\n" ; |
81 | for (const auto &MBB : *MF) { |
82 | unsigned BB = MBB.getNumber(); |
83 | O << "\t\"" << printMBBReference(MBB) << "\" [ shape=box ]\n" |
84 | << '\t' << G.getBundle(N: BB, Out: false) << " -> \"" << printMBBReference(MBB) |
85 | << "\"\n" |
86 | << "\t\"" << printMBBReference(MBB) << "\" -> " << G.getBundle(N: BB, Out: true) |
87 | << '\n'; |
88 | for (const MachineBasicBlock *Succ : MBB.successors()) |
89 | O << "\t\"" << printMBBReference(MBB) << "\" -> \"" |
90 | << printMBBReference(MBB: *Succ) << "\" [ color=lightgray ]\n" ; |
91 | } |
92 | O << "}\n" ; |
93 | return O; |
94 | } |
95 | |
96 | } // end namespace llvm |
97 | |
98 | /// view - Visualize the annotated bipartite CFG with Graphviz. |
99 | void EdgeBundles::view() const { |
100 | ViewGraph(G: *this, Name: "EdgeBundles" ); |
101 | } |
102 | |