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