aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/EdgeBundles.cpp
blob: f43353969834971d1c5a546b5fb4e7846db979fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//===-------- EdgeBundles.cpp - Bundles of CFG edges ----------------------===//
//
// 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 provides the implementation of the EdgeBundles analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/EdgeBundles.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<bool>
ViewEdgeBundles("view-edge-bundles", cl::Hidden,
                cl::desc("Pop up a window to show edge bundle graphs"));

char EdgeBundlesWrapperLegacy::ID = 0;

INITIALIZE_PASS(EdgeBundlesWrapperLegacy, "edge-bundles",
                "Bundle Machine CFG Edges",
                /* cfg = */ true, /* is_analysis = */ true)

char &llvm::EdgeBundlesWrapperLegacyID = EdgeBundlesWrapperLegacy::ID;

void EdgeBundlesWrapperLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  MachineFunctionPass::getAnalysisUsage(AU);
}

AnalysisKey EdgeBundlesAnalysis::Key;

EdgeBundles EdgeBundlesAnalysis::run(MachineFunction &MF,
                                     MachineFunctionAnalysisManager &MFAM) {
  EdgeBundles Impl(MF);
  return Impl;
}

bool EdgeBundlesWrapperLegacy::runOnMachineFunction(MachineFunction &MF) {
  Impl.reset(new EdgeBundles(MF));
  return false;
}

EdgeBundles::EdgeBundles(MachineFunction &MF) : MF(&MF) { init(); }

void EdgeBundles::init() {
  EC.clear();
  EC.grow(2 * MF->getNumBlockIDs());

  for (const auto &MBB : *MF) {
    unsigned OutE = 2 * MBB.getNumber() + 1;
    // Join the outgoing bundle with the ingoing bundles of all successors.
    for (const MachineBasicBlock *Succ : MBB.successors())
      EC.join(OutE, 2 * Succ->getNumber());
  }
  EC.compress();
  if (ViewEdgeBundles)
    view();

  // Compute the reverse mapping.
  Blocks.clear();
  Blocks.resize(getNumBundles());

  for (unsigned i = 0, e = MF->getNumBlockIDs(); i != e; ++i) {
    unsigned b0 = getBundle(i, false);
    unsigned b1 = getBundle(i, true);
    Blocks[b0].push_back(i);
    if (b1 != b0)
      Blocks[b1].push_back(i);
  }
}

namespace llvm {

/// Specialize WriteGraph, the standard implementation won't work.
template<>
raw_ostream &WriteGraph<>(raw_ostream &O, const EdgeBundles &G,
                          bool ShortNames,
                          const Twine &Title) {
  const MachineFunction *MF = G.getMachineFunction();

  O << "digraph {\n";
  for (const auto &MBB : *MF) {
    unsigned BB = MBB.getNumber();
    O << "\t\"" << printMBBReference(MBB) << "\" [ shape=box, label=\""
      << printMBBReference(MBB) << "\" ]\n"
      << '\t' << G.getBundle(BB, false) << " -> \"" << printMBBReference(MBB)
      << "\"\n"
      << "\t\"" << printMBBReference(MBB) << "\" -> " << G.getBundle(BB, true)
      << '\n';
    for (const MachineBasicBlock *Succ : MBB.successors())
      O << "\t\"" << printMBBReference(MBB) << "\" -> \""
        << printMBBReference(*Succ) << "\" [ color=lightgray ]\n";
  }
  O << "}\n";
  return O;
}

} // end namespace llvm

/// view - Visualize the annotated bipartite CFG with Graphviz.
void EdgeBundles::view() const {
  ViewGraph(*this, "EdgeBundles");
}

bool EdgeBundles::invalidate(MachineFunction &MF, const PreservedAnalyses &PA,
                             MachineFunctionAnalysisManager::Invalidator &Inv) {
  // Invalidated when CFG is not preserved
  auto PAC = PA.getChecker<EdgeBundlesAnalysis>();
  return !PAC.preserved() && !PAC.preservedSet<CFGAnalyses>() &&
         !PAC.preservedSet<AllAnalysesOn<MachineFunction>>();
}