| 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 EdgeBundlesWrapperLegacy::ID = 0; |
| 30 | |
| 31 | INITIALIZE_PASS(EdgeBundlesWrapperLegacy, "edge-bundles" , |
| 32 | "Bundle Machine CFG Edges" , |
| 33 | /* cfg = */ true, /* is_analysis = */ true) |
| 34 | |
| 35 | char &llvm::EdgeBundlesWrapperLegacyID = EdgeBundlesWrapperLegacy::ID; |
| 36 | |
| 37 | void EdgeBundlesWrapperLegacy::getAnalysisUsage(AnalysisUsage &AU) const { |
| 38 | AU.setPreservesAll(); |
| 39 | MachineFunctionPass::getAnalysisUsage(AU); |
| 40 | } |
| 41 | |
| 42 | AnalysisKey EdgeBundlesAnalysis::Key; |
| 43 | |
| 44 | EdgeBundles EdgeBundlesAnalysis::run(MachineFunction &MF, |
| 45 | MachineFunctionAnalysisManager &MFAM) { |
| 46 | EdgeBundles Impl(MF); |
| 47 | return Impl; |
| 48 | } |
| 49 | |
| 50 | bool EdgeBundlesWrapperLegacy::runOnMachineFunction(MachineFunction &MF) { |
| 51 | Impl.reset(p: new EdgeBundles(MF)); |
| 52 | return false; |
| 53 | } |
| 54 | |
| 55 | EdgeBundles::EdgeBundles(MachineFunction &MF) : MF(&MF) { init(); } |
| 56 | |
| 57 | void EdgeBundles::init() { |
| 58 | EC.clear(); |
| 59 | EC.grow(N: 2 * MF->getNumBlockIDs()); |
| 60 | |
| 61 | for (const auto &MBB : *MF) { |
| 62 | unsigned OutE = 2 * MBB.getNumber() + 1; |
| 63 | // Join the outgoing bundle with the ingoing bundles of all successors. |
| 64 | for (const MachineBasicBlock *Succ : MBB.successors()) |
| 65 | EC.join(a: OutE, b: 2 * Succ->getNumber()); |
| 66 | } |
| 67 | EC.compress(); |
| 68 | if (ViewEdgeBundles) |
| 69 | view(); |
| 70 | |
| 71 | // Compute the reverse mapping. |
| 72 | Blocks.clear(); |
| 73 | Blocks.resize(N: getNumBundles()); |
| 74 | |
| 75 | for (unsigned i = 0, e = MF->getNumBlockIDs(); i != e; ++i) { |
| 76 | unsigned b0 = getBundle(N: i, Out: false); |
| 77 | unsigned b1 = getBundle(N: i, Out: true); |
| 78 | Blocks[b0].push_back(Elt: i); |
| 79 | if (b1 != b0) |
| 80 | Blocks[b1].push_back(Elt: i); |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | namespace llvm { |
| 85 | |
| 86 | /// Specialize WriteGraph, the standard implementation won't work. |
| 87 | template<> |
| 88 | raw_ostream &WriteGraph<>(raw_ostream &O, const EdgeBundles &G, |
| 89 | bool ShortNames, |
| 90 | const Twine &Title) { |
| 91 | const MachineFunction *MF = G.getMachineFunction(); |
| 92 | |
| 93 | O << "digraph {\n" ; |
| 94 | for (const auto &MBB : *MF) { |
| 95 | unsigned BB = MBB.getNumber(); |
| 96 | O << "\t\"" << printMBBReference(MBB) << "\" [ shape=box, label=\"" |
| 97 | << printMBBReference(MBB) << "\" ]\n" |
| 98 | << '\t' << G.getBundle(N: BB, Out: false) << " -> \"" << printMBBReference(MBB) |
| 99 | << "\"\n" |
| 100 | << "\t\"" << printMBBReference(MBB) << "\" -> " << G.getBundle(N: BB, Out: true) |
| 101 | << '\n'; |
| 102 | for (const MachineBasicBlock *Succ : MBB.successors()) |
| 103 | O << "\t\"" << printMBBReference(MBB) << "\" -> \"" |
| 104 | << printMBBReference(MBB: *Succ) << "\" [ color=lightgray ]\n" ; |
| 105 | } |
| 106 | O << "}\n" ; |
| 107 | return O; |
| 108 | } |
| 109 | |
| 110 | } // end namespace llvm |
| 111 | |
| 112 | /// view - Visualize the annotated bipartite CFG with Graphviz. |
| 113 | void EdgeBundles::view() const { |
| 114 | ViewGraph(G: *this, Name: "EdgeBundles" ); |
| 115 | } |
| 116 | |
| 117 | bool EdgeBundles::invalidate(MachineFunction &MF, const PreservedAnalyses &PA, |
| 118 | MachineFunctionAnalysisManager::Invalidator &Inv) { |
| 119 | // Invalidated when CFG is not preserved |
| 120 | auto PAC = PA.getChecker<EdgeBundlesAnalysis>(); |
| 121 | return !PAC.preserved() && !PAC.preservedSet<CFGAnalyses>() && |
| 122 | !PAC.preservedSet<AllAnalysesOn<MachineFunction>>(); |
| 123 | } |
| 124 | |