xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/EdgeBundles.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===-------- EdgeBundles.cpp - Bundles of CFG edges ----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file provides the implementation of the EdgeBundles analysis.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/CodeGen/EdgeBundles.h"
145ffd83dbSDimitry Andric #include "llvm/ADT/Twine.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
18480093f4SDimitry Andric #include "llvm/InitializePasses.h"
190b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
200b57cec5SDimitry Andric #include "llvm/Support/GraphWriter.h"
210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric static cl::opt<bool>
260b57cec5SDimitry Andric ViewEdgeBundles("view-edge-bundles", cl::Hidden,
270b57cec5SDimitry Andric                 cl::desc("Pop up a window to show edge bundle graphs"));
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric char EdgeBundles::ID = 0;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric INITIALIZE_PASS(EdgeBundles, "edge-bundles", "Bundle Machine CFG Edges",
320b57cec5SDimitry Andric                 /* cfg = */true, /* is_analysis = */ true)
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric char &llvm::EdgeBundlesID = EdgeBundles::ID;
350b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const360b57cec5SDimitry Andric void EdgeBundles::getAnalysisUsage(AnalysisUsage &AU) const {
370b57cec5SDimitry Andric   AU.setPreservesAll();
380b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & mf)410b57cec5SDimitry Andric bool EdgeBundles::runOnMachineFunction(MachineFunction &mf) {
420b57cec5SDimitry Andric   MF = &mf;
430b57cec5SDimitry Andric   EC.clear();
440b57cec5SDimitry Andric   EC.grow(2 * MF->getNumBlockIDs());
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   for (const auto &MBB : *MF) {
470b57cec5SDimitry Andric     unsigned OutE = 2 * MBB.getNumber() + 1;
480b57cec5SDimitry Andric     // Join the outgoing bundle with the ingoing bundles of all successors.
49*fe6060f1SDimitry Andric     for (const MachineBasicBlock *Succ : MBB.successors())
50*fe6060f1SDimitry Andric       EC.join(OutE, 2 * Succ->getNumber());
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric   EC.compress();
530b57cec5SDimitry Andric   if (ViewEdgeBundles)
540b57cec5SDimitry Andric     view();
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   // Compute the reverse mapping.
570b57cec5SDimitry Andric   Blocks.clear();
580b57cec5SDimitry Andric   Blocks.resize(getNumBundles());
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   for (unsigned i = 0, e = MF->getNumBlockIDs(); i != e; ++i) {
610b57cec5SDimitry Andric     unsigned b0 = getBundle(i, false);
620b57cec5SDimitry Andric     unsigned b1 = getBundle(i, true);
630b57cec5SDimitry Andric     Blocks[b0].push_back(i);
640b57cec5SDimitry Andric     if (b1 != b0)
650b57cec5SDimitry Andric       Blocks[b1].push_back(i);
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   return false;
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric namespace llvm {
720b57cec5SDimitry Andric 
73*fe6060f1SDimitry Andric /// Specialize WriteGraph, the standard implementation won't work.
740b57cec5SDimitry Andric template<>
WriteGraph(raw_ostream & O,const EdgeBundles & G,bool ShortNames,const Twine & Title)750b57cec5SDimitry Andric raw_ostream &WriteGraph<>(raw_ostream &O, const EdgeBundles &G,
760b57cec5SDimitry Andric                           bool ShortNames,
770b57cec5SDimitry Andric                           const Twine &Title) {
780b57cec5SDimitry Andric   const MachineFunction *MF = G.getMachineFunction();
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   O << "digraph {\n";
810b57cec5SDimitry Andric   for (const auto &MBB : *MF) {
820b57cec5SDimitry Andric     unsigned BB = MBB.getNumber();
830b57cec5SDimitry Andric     O << "\t\"" << printMBBReference(MBB) << "\" [ shape=box ]\n"
840b57cec5SDimitry Andric       << '\t' << G.getBundle(BB, false) << " -> \"" << printMBBReference(MBB)
850b57cec5SDimitry Andric       << "\"\n"
860b57cec5SDimitry Andric       << "\t\"" << printMBBReference(MBB) << "\" -> " << G.getBundle(BB, true)
870b57cec5SDimitry Andric       << '\n';
88*fe6060f1SDimitry Andric     for (const MachineBasicBlock *Succ : MBB.successors())
890b57cec5SDimitry Andric       O << "\t\"" << printMBBReference(MBB) << "\" -> \""
90*fe6060f1SDimitry Andric         << printMBBReference(*Succ) << "\" [ color=lightgray ]\n";
910b57cec5SDimitry Andric   }
920b57cec5SDimitry Andric   O << "}\n";
930b57cec5SDimitry Andric   return O;
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric } // end namespace llvm
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric /// view - Visualize the annotated bipartite CFG with Graphviz.
view() const990b57cec5SDimitry Andric void EdgeBundles::view() const {
1000b57cec5SDimitry Andric   ViewGraph(*this, "EdgeBundles");
1010b57cec5SDimitry Andric }
102