1 //===- DDG.cpp - Data Dependence Graph -------------------------------------==//
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
7 //===----------------------------------------------------------------------===//
9 // The implementation for the data dependence graph.
10 //===----------------------------------------------------------------------===//
11 #include "llvm/Analysis/DDG.h"
12 #include "llvm/Analysis/LoopInfo.h"
16 #define DEBUG_TYPE "ddg"
18 template class llvm::DGEdge
<DDGNode
, DDGEdge
>;
19 template class llvm::DGNode
<DDGNode
, DDGEdge
>;
20 template class llvm::DirectedGraph
<DDGNode
, DDGEdge
>;
22 //===--------------------------------------------------------------------===//
23 // DDGNode implementation
24 //===--------------------------------------------------------------------===//
25 DDGNode::~DDGNode() {}
27 bool DDGNode::collectInstructions(
28 llvm::function_ref
<bool(Instruction
*)> const &Pred
,
29 InstructionListType
&IList
) const {
30 assert(IList
.empty() && "Expected the IList to be empty on entry.");
31 if (isa
<SimpleDDGNode
>(this)) {
32 for (auto *I
: cast
<const SimpleDDGNode
>(this)->getInstructions())
36 llvm_unreachable("unimplemented type of node");
37 return !IList
.empty();
40 raw_ostream
&llvm::operator<<(raw_ostream
&OS
, const DDGNode::NodeKind K
) {
43 case DDGNode::NodeKind::SingleInstruction
:
44 Out
= "single-instruction";
46 case DDGNode::NodeKind::MultiInstruction
:
47 Out
= "multi-instruction";
49 case DDGNode::NodeKind::Root
:
52 case DDGNode::NodeKind::Unknown
:
60 raw_ostream
&llvm::operator<<(raw_ostream
&OS
, const DDGNode
&N
) {
61 OS
<< "Node Address:" << &N
<< ":" << N
.getKind() << "\n";
62 if (isa
<SimpleDDGNode
>(N
)) {
63 OS
<< " Instructions:\n";
64 for (auto *I
: cast
<const SimpleDDGNode
>(N
).getInstructions())
65 OS
.indent(2) << *I
<< "\n";
66 } else if (!isa
<RootDDGNode
>(N
))
67 llvm_unreachable("unimplemented type of node");
69 OS
<< (N
.getEdges().empty() ? " Edges:none!\n" : " Edges:\n");
70 for (auto &E
: N
.getEdges())
75 //===--------------------------------------------------------------------===//
76 // SimpleDDGNode implementation
77 //===--------------------------------------------------------------------===//
79 SimpleDDGNode::SimpleDDGNode(Instruction
&I
)
80 : DDGNode(NodeKind::SingleInstruction
), InstList() {
81 assert(InstList
.empty() && "Expected empty list.");
82 InstList
.push_back(&I
);
85 SimpleDDGNode::SimpleDDGNode(const SimpleDDGNode
&N
)
86 : DDGNode(N
), InstList(N
.InstList
) {
87 assert(((getKind() == NodeKind::SingleInstruction
&& InstList
.size() == 1) ||
88 (getKind() == NodeKind::MultiInstruction
&& InstList
.size() > 1)) &&
89 "constructing from invalid simple node.");
92 SimpleDDGNode::SimpleDDGNode(SimpleDDGNode
&&N
)
93 : DDGNode(std::move(N
)), InstList(std::move(N
.InstList
)) {
94 assert(((getKind() == NodeKind::SingleInstruction
&& InstList
.size() == 1) ||
95 (getKind() == NodeKind::MultiInstruction
&& InstList
.size() > 1)) &&
96 "constructing from invalid simple node.");
99 SimpleDDGNode::~SimpleDDGNode() { InstList
.clear(); }
101 //===--------------------------------------------------------------------===//
102 // DDGEdge implementation
103 //===--------------------------------------------------------------------===//
105 raw_ostream
&llvm::operator<<(raw_ostream
&OS
, const DDGEdge::EdgeKind K
) {
108 case DDGEdge::EdgeKind::RegisterDefUse
:
111 case DDGEdge::EdgeKind::MemoryDependence
:
114 case DDGEdge::EdgeKind::Rooted
:
117 case DDGEdge::EdgeKind::Unknown
:
125 raw_ostream
&llvm::operator<<(raw_ostream
&OS
, const DDGEdge
&E
) {
126 OS
<< "[" << E
.getKind() << "] to " << &E
.getTargetNode() << "\n";
130 //===--------------------------------------------------------------------===//
131 // DataDependenceGraph implementation
132 //===--------------------------------------------------------------------===//
133 using BasicBlockListType
= SmallVector
<BasicBlock
*, 8>;
135 DataDependenceGraph::DataDependenceGraph(Function
&F
, DependenceInfo
&D
)
136 : DependenceGraphInfo(F
.getName().str(), D
) {
137 BasicBlockListType BBList
;
138 for (auto &BB
: F
.getBasicBlockList())
139 BBList
.push_back(&BB
);
140 DDGBuilder(*this, D
, BBList
).populate();
143 DataDependenceGraph::DataDependenceGraph(const Loop
&L
, DependenceInfo
&D
)
144 : DependenceGraphInfo(Twine(L
.getHeader()->getParent()->getName() + "." +
145 L
.getHeader()->getName())
148 BasicBlockListType BBList
;
149 for (BasicBlock
*BB
: L
.blocks())
150 BBList
.push_back(BB
);
151 DDGBuilder(*this, D
, BBList
).populate();
154 DataDependenceGraph::~DataDependenceGraph() {
155 for (auto *N
: Nodes
) {
162 bool DataDependenceGraph::addNode(DDGNode
&N
) {
163 if (!DDGBase::addNode(N
))
166 // In general, if the root node is already created and linked, it is not safe
167 // to add new nodes since they may be unreachable by the root.
168 // TODO: Allow adding Pi-block nodes after root is created. Pi-blocks are an
169 // exception because they represent components that are already reachable by
171 assert(!Root
&& "Root node is already added. No more nodes can be added.");
172 if (isa
<RootDDGNode
>(N
))
178 raw_ostream
&llvm::operator<<(raw_ostream
&OS
, const DataDependenceGraph
&G
) {
184 //===--------------------------------------------------------------------===//
185 // DDG Analysis Passes
186 //===--------------------------------------------------------------------===//
188 /// DDG as a loop pass.
189 DDGAnalysis::Result
DDGAnalysis::run(Loop
&L
, LoopAnalysisManager
&AM
,
190 LoopStandardAnalysisResults
&AR
) {
191 Function
*F
= L
.getHeader()->getParent();
192 DependenceInfo
DI(F
, &AR
.AA
, &AR
.SE
, &AR
.LI
);
193 return std::make_unique
<DataDependenceGraph
>(L
, DI
);
195 AnalysisKey
DDGAnalysis::Key
;
197 PreservedAnalyses
DDGAnalysisPrinterPass::run(Loop
&L
, LoopAnalysisManager
&AM
,
198 LoopStandardAnalysisResults
&AR
,
200 OS
<< "'DDG' for loop '" << L
.getHeader()->getName() << "':\n";
201 OS
<< *AM
.getResult
<DDGAnalysis
>(L
, AR
);
202 return PreservedAnalyses::all();