LLVM 24.0.0git
DDG.cpp
Go to the documentation of this file.
1//===- DDG.cpp - Data Dependence Graph -------------------------------------==//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// The implementation for the data dependence graph.
10//===----------------------------------------------------------------------===//
11#include "llvm/Analysis/DDG.h"
12#include "AnalysisOptions.h"
16
17using namespace llvm;
18
19#define DEBUG_TYPE "ddg"
20
24
25//===--------------------------------------------------------------------===//
26// DDGNode implementation
27//===--------------------------------------------------------------------===//
28DDGNode::~DDGNode() = default;
29
31 llvm::function_ref<bool(Instruction *)> const &Pred,
32 InstructionListType &IList) const {
33 assert(IList.empty() && "Expected the IList to be empty on entry.");
34 if (isa<SimpleDDGNode>(this)) {
35 for (Instruction *I : cast<const SimpleDDGNode>(this)->getInstructions())
36 if (Pred(I))
37 IList.push_back(I);
38 } else if (isa<PiBlockDDGNode>(this)) {
39 for (const DDGNode *PN : cast<const PiBlockDDGNode>(this)->getNodes()) {
40 assert(!isa<PiBlockDDGNode>(PN) && "Nested PiBlocks are not supported.");
42 PN->collectInstructions(Pred, TmpIList);
43 llvm::append_range(IList, TmpIList);
44 }
45 } else
46 llvm_unreachable("unimplemented type of node");
47 return !IList.empty();
48}
49
51 const char *Out;
52 switch (K) {
54 Out = "single-instruction";
55 break;
57 Out = "multi-instruction";
58 break;
60 Out = "pi-block";
61 break;
63 Out = "root";
64 break;
66 Out = "?? (error)";
67 break;
68 }
69 OS << Out;
70 return OS;
71}
72
74 OS << "Node Address:" << &N << ":" << N.getKind() << "\n";
75 if (isa<SimpleDDGNode>(N)) {
76 OS << " Instructions:\n";
77 for (const Instruction *I : cast<const SimpleDDGNode>(N).getInstructions())
78 OS.indent(2) << *I << "\n";
79 } else if (isa<PiBlockDDGNode>(&N)) {
80 OS << "--- start of nodes in pi-block ---\n";
81 auto &Nodes = cast<const PiBlockDDGNode>(&N)->getNodes();
82 unsigned Count = 0;
83 for (const DDGNode *N : Nodes)
84 OS << *N << (++Count == Nodes.size() ? "" : "\n");
85 OS << "--- end of nodes in pi-block ---\n";
86 } else if (!isa<RootDDGNode>(N))
87 llvm_unreachable("unimplemented type of node");
88
89 OS << (N.getEdges().empty() ? " Edges:none!\n" : " Edges:\n");
90 for (const auto &E : N.getEdges())
91 OS.indent(2) << *E;
92 return OS;
93}
94
95//===--------------------------------------------------------------------===//
96// SimpleDDGNode implementation
97//===--------------------------------------------------------------------===//
98
101 assert(InstList.empty() && "Expected empty list.");
102 InstList.push_back(&I);
103}
104
106 : DDGNode(N), InstList(N.InstList) {
107 assert(((getKind() == NodeKind::SingleInstruction && InstList.size() == 1) ||
108 (getKind() == NodeKind::MultiInstruction && InstList.size() > 1)) &&
109 "constructing from invalid simple node.");
110}
111
113 : DDGNode(std::move(N)), InstList(std::move(N.InstList)) {
114 assert(((getKind() == NodeKind::SingleInstruction && InstList.size() == 1) ||
115 (getKind() == NodeKind::MultiInstruction && InstList.size() > 1)) &&
116 "constructing from invalid simple node.");
117}
118
119SimpleDDGNode::~SimpleDDGNode() { InstList.clear(); }
120
121//===--------------------------------------------------------------------===//
122// PiBlockDDGNode implementation
123//===--------------------------------------------------------------------===//
124
126 : DDGNode(NodeKind::PiBlock), NodeList(List) {
127 assert(!NodeList.empty() && "pi-block node constructed with an empty list.");
128}
129
131 : DDGNode(N), NodeList(N.NodeList) {
132 assert(getKind() == NodeKind::PiBlock && !NodeList.empty() &&
133 "constructing from invalid pi-block node.");
134}
135
137 : DDGNode(std::move(N)), NodeList(std::move(N.NodeList)) {
138 assert(getKind() == NodeKind::PiBlock && !NodeList.empty() &&
139 "constructing from invalid pi-block node.");
140}
141
142PiBlockDDGNode::~PiBlockDDGNode() { NodeList.clear(); }
143
144//===--------------------------------------------------------------------===//
145// DDGEdge implementation
146//===--------------------------------------------------------------------===//
147
149 const char *Out;
150 switch (K) {
152 Out = "def-use";
153 break;
155 Out = "memory";
156 break;
158 Out = "rooted";
159 break;
161 Out = "?? (error)";
162 break;
163 }
164 OS << Out;
165 return OS;
166}
167
169 OS << "[" << E.getKind() << "] to " << &E.getTargetNode() << "\n";
170 return OS;
171}
172
173//===--------------------------------------------------------------------===//
174// DataDependenceGraph implementation
175//===--------------------------------------------------------------------===//
177
179 : DependenceGraphInfo(F.getName().str(), D) {
180 // Put the basic blocks in program order for correct dependence
181 // directions.
182 BasicBlockListType BBList;
183 for (const auto &SCC : make_range(scc_begin(&F), scc_end(&F)))
184 append_range(BBList, SCC);
185 std::reverse(BBList.begin(), BBList.end());
186 DDGBuilder(*this, D, BBList).populate();
187}
188
191 : DependenceGraphInfo(Twine(L.getHeader()->getParent()->getName() + "." +
192 L.getHeader()->getName())
193 .str(),
194 D) {
195 // Put the basic blocks in program order for correct dependence
196 // directions.
197 LoopBlocksDFS DFS(&L);
198 DFS.perform(&LI);
199 BasicBlockListType BBList;
200 append_range(BBList, make_range(DFS.beginRPO(), DFS.endRPO()));
201 DDGBuilder(*this, D, BBList).populate();
202}
203
205 for (auto *N : Nodes) {
206 for (auto *E : *N)
207 delete E;
208 delete N;
209 }
210}
211
213 if (!DDGBase::addNode(N))
214 return false;
215
216 // In general, if the root node is already created and linked, it is not safe
217 // to add new nodes since they may be unreachable by the root. However,
218 // pi-block nodes need to be added after the root node is linked, and they are
219 // always reachable by the root, because they represent components that are
220 // already reachable by root.
221 auto *Pi = dyn_cast<PiBlockDDGNode>(&N);
222 assert((!Root || Pi) &&
223 "Root node is already added. No more nodes can be added.");
224
225 if (isa<RootDDGNode>(N))
226 Root = &N;
227
228 if (Pi)
229 for (DDGNode *NI : Pi->getNodes())
230 PiBlockMap.insert(std::make_pair(NI, Pi));
231
232 return true;
233}
234
236 auto It = PiBlockMap.find(&N);
237 if (It == PiBlockMap.end())
238 return nullptr;
239 auto *Pi = It->second;
240 assert(!PiBlockMap.contains(Pi) && "Nested pi-blocks detected.");
241 return Pi;
242}
243
245 for (DDGNode *Node : G)
246 // Avoid printing nodes that are part of a pi-block twice. They will get
247 // printed when the pi-block is printed.
248 if (!G.getPiBlock(*Node))
249 OS << *Node << "\n";
250 OS << "\n";
251 return OS;
252}
253
254//===--------------------------------------------------------------------===//
255// DDGBuilder implementation
256//===--------------------------------------------------------------------===//
257
259 const DDGNode &Tgt) const {
260 // Only merge two nodes if they are both simple nodes and the consecutive
261 // instructions after merging belong to the same BB.
262 const auto *SimpleSrc = dyn_cast<const SimpleDDGNode>(&Src);
263 const auto *SimpleTgt = dyn_cast<const SimpleDDGNode>(&Tgt);
264 if (!SimpleSrc || !SimpleTgt)
265 return false;
266
267 return SimpleSrc->getLastInstruction()->getParent() ==
268 SimpleTgt->getFirstInstruction()->getParent();
269}
270
272 DDGEdge &EdgeToFold = A.back();
273 assert(A.getEdges().size() == 1 && EdgeToFold.getTargetNode() == B &&
274 "Expected A to have a single edge to B.");
276 "Expected simple nodes");
277
278 // Copy instructions from B to the end of A.
279 cast<SimpleDDGNode>(&A)->appendInstructions(*cast<SimpleDDGNode>(&B));
280
281 // Move to A any outgoing edges from B.
282 for (DDGEdge *BE : B)
283 Graph.connect(A, BE->getTargetNode(), *BE);
284
285 A.removeEdge(EdgeToFold);
286 destroyEdge(EdgeToFold);
287 Graph.removeNode(B);
288 destroyNode(B);
289}
290
292 return getAnalysisOptions(*DI.getFunction()).ddg_simplify;
293}
294
296 return getAnalysisOptions(*DI.getFunction()).ddg_pi_blocks;
297}
298
299//===--------------------------------------------------------------------===//
300// DDG Analysis Passes
301//===--------------------------------------------------------------------===//
302
303/// DDG as a loop pass.
306 Function *F = L.getHeader()->getParent();
307 DependenceInfo DI(F, &AR.AA, &AR.SE, &AR.LI);
308 return std::make_unique<DataDependenceGraph>(L, AR.LI, DI);
309}
310AnalysisKey DDGAnalysis::Key;
311
314 LPMUpdater &U) {
315 OS << "'DDG' for loop '" << L.getHeader()->getName() << "':\n";
316 OS << *AM.getResult<DDGAnalysis>(L, AR);
317 return PreservedAnalyses::all();
318}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
SmallVector< BasicBlock *, 8 > BasicBlockListType
Definition DDG.cpp:176
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM_ABI PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U)
Definition DDG.cpp:312
Analysis pass that builds the DDG for a loop.
Definition DDG.h:412
LLVM_ABI Result run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR)
DDG as a loop pass.
Definition DDG.cpp:304
std::unique_ptr< DataDependenceGraph > Result
Definition DDG.h:414
bool areNodesMergeable(const DDGNode &Src, const DDGNode &Tgt) const final
Return true if the two nodes \pSrc and \pTgt are both simple nodes and the consecutive instructions a...
Definition DDG.cpp:258
bool shouldCreatePiBlocks() const final
Return true if creation of pi-blocks are supported and desired, and false otherwise.
Definition DDG.cpp:295
bool shouldSimplify() const final
Return true if graph simplification step is requested, and false otherwise.
Definition DDG.cpp:291
void mergeNodes(DDGNode &Src, DDGNode &Tgt) final
Append the content of node B into node A and remove B and the edge between A and B from the graph.
Definition DDG.cpp:271
Data Dependency Graph Edge.
Definition DDG.h:210
EdgeKind
The kind of edge in the DDG.
Definition DDG.h:213
Data Dependence Graph Node The graph can represent the following types of nodes:
Definition DDG.h:45
SmallVectorImpl< Instruction * > InstructionListType
Definition DDG.h:47
NodeKind getKind() const
Getter for the kind of this node.
Definition DDG.h:72
DDGNode()=delete
virtual ~DDGNode()=0
bool collectInstructions(llvm::function_ref< bool(Instruction *)> const &Pred, InstructionListType &IList) const
Collect a list of instructions, in IList, for which predicate Pred evaluates to true when iterating o...
Definition DDG.cpp:30
Represent an edge in the directed graph.
const NodeType & getTargetNode() const
Retrieve the target node this edge connects to.
Represent a node in the directed graph.
Data Dependency Graph.
Definition DDG.h:303
const PiBlockDDGNode * getPiBlock(const NodeType &N) const
If node N belongs to a pi-block return a pointer to the pi-block, otherwise return null.
Definition DDG.cpp:235
~DataDependenceGraph() override
Definition DDG.cpp:204
bool addNode(NodeType &N)
Add node N to the graph, if it's not added yet, and keep track of the root node as well as pi-blocks ...
Definition DDG.cpp:212
friend class DDGBuilder
Definition DDG.h:305
StringRef getName() const
Definition DDG.h:265
DependenceInfo - This class is the main dependence-analysis driver.
Directed graph.
This class provides an interface for updating the loop pass manager based on mutations to the loop ne...
Store the result of a depth first search within basic blocks contained by a single loop.
RPOIterator beginRPO() const
Reverse iterate over the cached postorder blocks.
LLVM_ABI void perform(const LoopInfo *LI)
Traverse the loop blocks and store the DFS result.
RPOIterator endRPO() const
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Subclass of DDGNode representing a pi-block.
Definition DDG.h:167
~PiBlockDDGNode() override
Definition DDG.cpp:142
SmallVector< DDGNode *, 4 > PiNodeList
Definition DDG.h:169
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
~SimpleDDGNode() override
Definition DDG.cpp:119
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
AnalysisManager< Loop, LoopStandardAnalysisResults & > LoopAnalysisManager
The loop analysis manager.
const AnalysisOptions & getAnalysisOptions(const LLVMContext &C)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
scc_iterator< T > scc_end(const T &G)
Construct the end iterator for a deduced graph type T.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...