xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/DDG.cpp (revision 8bcb0991864975618c09697b1aca10683346d9f0)
1*8bcb0991SDimitry Andric //===- DDG.cpp - Data Dependence Graph -------------------------------------==//
2*8bcb0991SDimitry Andric //
3*8bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*8bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*8bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*8bcb0991SDimitry Andric //
7*8bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
8*8bcb0991SDimitry Andric //
9*8bcb0991SDimitry Andric // The implementation for the data dependence graph.
10*8bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
11*8bcb0991SDimitry Andric #include "llvm/Analysis/DDG.h"
12*8bcb0991SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
13*8bcb0991SDimitry Andric 
14*8bcb0991SDimitry Andric using namespace llvm;
15*8bcb0991SDimitry Andric 
16*8bcb0991SDimitry Andric #define DEBUG_TYPE "ddg"
17*8bcb0991SDimitry Andric 
18*8bcb0991SDimitry Andric template class llvm::DGEdge<DDGNode, DDGEdge>;
19*8bcb0991SDimitry Andric template class llvm::DGNode<DDGNode, DDGEdge>;
20*8bcb0991SDimitry Andric template class llvm::DirectedGraph<DDGNode, DDGEdge>;
21*8bcb0991SDimitry Andric 
22*8bcb0991SDimitry Andric //===--------------------------------------------------------------------===//
23*8bcb0991SDimitry Andric // DDGNode implementation
24*8bcb0991SDimitry Andric //===--------------------------------------------------------------------===//
25*8bcb0991SDimitry Andric DDGNode::~DDGNode() {}
26*8bcb0991SDimitry Andric 
27*8bcb0991SDimitry Andric bool DDGNode::collectInstructions(
28*8bcb0991SDimitry Andric     llvm::function_ref<bool(Instruction *)> const &Pred,
29*8bcb0991SDimitry Andric     InstructionListType &IList) const {
30*8bcb0991SDimitry Andric   assert(IList.empty() && "Expected the IList to be empty on entry.");
31*8bcb0991SDimitry Andric   if (isa<SimpleDDGNode>(this)) {
32*8bcb0991SDimitry Andric     for (auto *I : cast<const SimpleDDGNode>(this)->getInstructions())
33*8bcb0991SDimitry Andric       if (Pred(I))
34*8bcb0991SDimitry Andric         IList.push_back(I);
35*8bcb0991SDimitry Andric   } else
36*8bcb0991SDimitry Andric     llvm_unreachable("unimplemented type of node");
37*8bcb0991SDimitry Andric   return !IList.empty();
38*8bcb0991SDimitry Andric }
39*8bcb0991SDimitry Andric 
40*8bcb0991SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const DDGNode::NodeKind K) {
41*8bcb0991SDimitry Andric   const char *Out;
42*8bcb0991SDimitry Andric   switch (K) {
43*8bcb0991SDimitry Andric   case DDGNode::NodeKind::SingleInstruction:
44*8bcb0991SDimitry Andric     Out = "single-instruction";
45*8bcb0991SDimitry Andric     break;
46*8bcb0991SDimitry Andric   case DDGNode::NodeKind::MultiInstruction:
47*8bcb0991SDimitry Andric     Out = "multi-instruction";
48*8bcb0991SDimitry Andric     break;
49*8bcb0991SDimitry Andric   case DDGNode::NodeKind::Root:
50*8bcb0991SDimitry Andric     Out = "root";
51*8bcb0991SDimitry Andric     break;
52*8bcb0991SDimitry Andric   case DDGNode::NodeKind::Unknown:
53*8bcb0991SDimitry Andric     Out = "??";
54*8bcb0991SDimitry Andric     break;
55*8bcb0991SDimitry Andric   }
56*8bcb0991SDimitry Andric   OS << Out;
57*8bcb0991SDimitry Andric   return OS;
58*8bcb0991SDimitry Andric }
59*8bcb0991SDimitry Andric 
60*8bcb0991SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const DDGNode &N) {
61*8bcb0991SDimitry Andric   OS << "Node Address:" << &N << ":" << N.getKind() << "\n";
62*8bcb0991SDimitry Andric   if (isa<SimpleDDGNode>(N)) {
63*8bcb0991SDimitry Andric     OS << " Instructions:\n";
64*8bcb0991SDimitry Andric     for (auto *I : cast<const SimpleDDGNode>(N).getInstructions())
65*8bcb0991SDimitry Andric       OS.indent(2) << *I << "\n";
66*8bcb0991SDimitry Andric   } else if (!isa<RootDDGNode>(N))
67*8bcb0991SDimitry Andric     llvm_unreachable("unimplemented type of node");
68*8bcb0991SDimitry Andric 
69*8bcb0991SDimitry Andric   OS << (N.getEdges().empty() ? " Edges:none!\n" : " Edges:\n");
70*8bcb0991SDimitry Andric   for (auto &E : N.getEdges())
71*8bcb0991SDimitry Andric     OS.indent(2) << *E;
72*8bcb0991SDimitry Andric   return OS;
73*8bcb0991SDimitry Andric }
74*8bcb0991SDimitry Andric 
75*8bcb0991SDimitry Andric //===--------------------------------------------------------------------===//
76*8bcb0991SDimitry Andric // SimpleDDGNode implementation
77*8bcb0991SDimitry Andric //===--------------------------------------------------------------------===//
78*8bcb0991SDimitry Andric 
79*8bcb0991SDimitry Andric SimpleDDGNode::SimpleDDGNode(Instruction &I)
80*8bcb0991SDimitry Andric   : DDGNode(NodeKind::SingleInstruction), InstList() {
81*8bcb0991SDimitry Andric   assert(InstList.empty() && "Expected empty list.");
82*8bcb0991SDimitry Andric   InstList.push_back(&I);
83*8bcb0991SDimitry Andric }
84*8bcb0991SDimitry Andric 
85*8bcb0991SDimitry Andric SimpleDDGNode::SimpleDDGNode(const SimpleDDGNode &N)
86*8bcb0991SDimitry Andric     : DDGNode(N), InstList(N.InstList) {
87*8bcb0991SDimitry Andric   assert(((getKind() == NodeKind::SingleInstruction && InstList.size() == 1) ||
88*8bcb0991SDimitry Andric           (getKind() == NodeKind::MultiInstruction && InstList.size() > 1)) &&
89*8bcb0991SDimitry Andric          "constructing from invalid simple node.");
90*8bcb0991SDimitry Andric }
91*8bcb0991SDimitry Andric 
92*8bcb0991SDimitry Andric SimpleDDGNode::SimpleDDGNode(SimpleDDGNode &&N)
93*8bcb0991SDimitry Andric     : DDGNode(std::move(N)), InstList(std::move(N.InstList)) {
94*8bcb0991SDimitry Andric   assert(((getKind() == NodeKind::SingleInstruction && InstList.size() == 1) ||
95*8bcb0991SDimitry Andric           (getKind() == NodeKind::MultiInstruction && InstList.size() > 1)) &&
96*8bcb0991SDimitry Andric          "constructing from invalid simple node.");
97*8bcb0991SDimitry Andric }
98*8bcb0991SDimitry Andric 
99*8bcb0991SDimitry Andric SimpleDDGNode::~SimpleDDGNode() { InstList.clear(); }
100*8bcb0991SDimitry Andric 
101*8bcb0991SDimitry Andric //===--------------------------------------------------------------------===//
102*8bcb0991SDimitry Andric // DDGEdge implementation
103*8bcb0991SDimitry Andric //===--------------------------------------------------------------------===//
104*8bcb0991SDimitry Andric 
105*8bcb0991SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const DDGEdge::EdgeKind K) {
106*8bcb0991SDimitry Andric   const char *Out;
107*8bcb0991SDimitry Andric   switch (K) {
108*8bcb0991SDimitry Andric   case DDGEdge::EdgeKind::RegisterDefUse:
109*8bcb0991SDimitry Andric     Out = "def-use";
110*8bcb0991SDimitry Andric     break;
111*8bcb0991SDimitry Andric   case DDGEdge::EdgeKind::MemoryDependence:
112*8bcb0991SDimitry Andric     Out = "memory";
113*8bcb0991SDimitry Andric     break;
114*8bcb0991SDimitry Andric   case DDGEdge::EdgeKind::Rooted:
115*8bcb0991SDimitry Andric     Out = "rooted";
116*8bcb0991SDimitry Andric     break;
117*8bcb0991SDimitry Andric   case DDGEdge::EdgeKind::Unknown:
118*8bcb0991SDimitry Andric     Out = "??";
119*8bcb0991SDimitry Andric     break;
120*8bcb0991SDimitry Andric   }
121*8bcb0991SDimitry Andric   OS << Out;
122*8bcb0991SDimitry Andric   return OS;
123*8bcb0991SDimitry Andric }
124*8bcb0991SDimitry Andric 
125*8bcb0991SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const DDGEdge &E) {
126*8bcb0991SDimitry Andric   OS << "[" << E.getKind() << "] to " << &E.getTargetNode() << "\n";
127*8bcb0991SDimitry Andric   return OS;
128*8bcb0991SDimitry Andric }
129*8bcb0991SDimitry Andric 
130*8bcb0991SDimitry Andric //===--------------------------------------------------------------------===//
131*8bcb0991SDimitry Andric // DataDependenceGraph implementation
132*8bcb0991SDimitry Andric //===--------------------------------------------------------------------===//
133*8bcb0991SDimitry Andric using BasicBlockListType = SmallVector<BasicBlock *, 8>;
134*8bcb0991SDimitry Andric 
135*8bcb0991SDimitry Andric DataDependenceGraph::DataDependenceGraph(Function &F, DependenceInfo &D)
136*8bcb0991SDimitry Andric     : DependenceGraphInfo(F.getName().str(), D) {
137*8bcb0991SDimitry Andric   BasicBlockListType BBList;
138*8bcb0991SDimitry Andric   for (auto &BB : F.getBasicBlockList())
139*8bcb0991SDimitry Andric     BBList.push_back(&BB);
140*8bcb0991SDimitry Andric   DDGBuilder(*this, D, BBList).populate();
141*8bcb0991SDimitry Andric }
142*8bcb0991SDimitry Andric 
143*8bcb0991SDimitry Andric DataDependenceGraph::DataDependenceGraph(const Loop &L, DependenceInfo &D)
144*8bcb0991SDimitry Andric     : DependenceGraphInfo(Twine(L.getHeader()->getParent()->getName() + "." +
145*8bcb0991SDimitry Andric                                 L.getHeader()->getName())
146*8bcb0991SDimitry Andric                               .str(),
147*8bcb0991SDimitry Andric                           D) {
148*8bcb0991SDimitry Andric   BasicBlockListType BBList;
149*8bcb0991SDimitry Andric   for (BasicBlock *BB : L.blocks())
150*8bcb0991SDimitry Andric     BBList.push_back(BB);
151*8bcb0991SDimitry Andric   DDGBuilder(*this, D, BBList).populate();
152*8bcb0991SDimitry Andric }
153*8bcb0991SDimitry Andric 
154*8bcb0991SDimitry Andric DataDependenceGraph::~DataDependenceGraph() {
155*8bcb0991SDimitry Andric   for (auto *N : Nodes) {
156*8bcb0991SDimitry Andric     for (auto *E : *N)
157*8bcb0991SDimitry Andric       delete E;
158*8bcb0991SDimitry Andric     delete N;
159*8bcb0991SDimitry Andric   }
160*8bcb0991SDimitry Andric }
161*8bcb0991SDimitry Andric 
162*8bcb0991SDimitry Andric bool DataDependenceGraph::addNode(DDGNode &N) {
163*8bcb0991SDimitry Andric   if (!DDGBase::addNode(N))
164*8bcb0991SDimitry Andric     return false;
165*8bcb0991SDimitry Andric 
166*8bcb0991SDimitry Andric   // In general, if the root node is already created and linked, it is not safe
167*8bcb0991SDimitry Andric   // to add new nodes since they may be unreachable by the root.
168*8bcb0991SDimitry Andric   // TODO: Allow adding Pi-block nodes after root is created. Pi-blocks are an
169*8bcb0991SDimitry Andric   // exception because they represent components that are already reachable by
170*8bcb0991SDimitry Andric   // root.
171*8bcb0991SDimitry Andric   assert(!Root && "Root node is already added. No more nodes can be added.");
172*8bcb0991SDimitry Andric   if (isa<RootDDGNode>(N))
173*8bcb0991SDimitry Andric     Root = &N;
174*8bcb0991SDimitry Andric 
175*8bcb0991SDimitry Andric   return true;
176*8bcb0991SDimitry Andric }
177*8bcb0991SDimitry Andric 
178*8bcb0991SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const DataDependenceGraph &G) {
179*8bcb0991SDimitry Andric   for (auto *Node : G)
180*8bcb0991SDimitry Andric     OS << *Node << "\n";
181*8bcb0991SDimitry Andric   return OS;
182*8bcb0991SDimitry Andric }
183*8bcb0991SDimitry Andric 
184*8bcb0991SDimitry Andric //===--------------------------------------------------------------------===//
185*8bcb0991SDimitry Andric // DDG Analysis Passes
186*8bcb0991SDimitry Andric //===--------------------------------------------------------------------===//
187*8bcb0991SDimitry Andric 
188*8bcb0991SDimitry Andric /// DDG as a loop pass.
189*8bcb0991SDimitry Andric DDGAnalysis::Result DDGAnalysis::run(Loop &L, LoopAnalysisManager &AM,
190*8bcb0991SDimitry Andric                                      LoopStandardAnalysisResults &AR) {
191*8bcb0991SDimitry Andric   Function *F = L.getHeader()->getParent();
192*8bcb0991SDimitry Andric   DependenceInfo DI(F, &AR.AA, &AR.SE, &AR.LI);
193*8bcb0991SDimitry Andric   return std::make_unique<DataDependenceGraph>(L, DI);
194*8bcb0991SDimitry Andric }
195*8bcb0991SDimitry Andric AnalysisKey DDGAnalysis::Key;
196*8bcb0991SDimitry Andric 
197*8bcb0991SDimitry Andric PreservedAnalyses DDGAnalysisPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
198*8bcb0991SDimitry Andric                                               LoopStandardAnalysisResults &AR,
199*8bcb0991SDimitry Andric                                               LPMUpdater &U) {
200*8bcb0991SDimitry Andric   OS << "'DDG' for loop '" << L.getHeader()->getName() << "':\n";
201*8bcb0991SDimitry Andric   OS << *AM.getResult<DDGAnalysis>(L, AR);
202*8bcb0991SDimitry Andric   return PreservedAnalyses::all();
203*8bcb0991SDimitry Andric }
204