blob: ed21cc7134fc68565729a374bb1114afe106d946 [file] [log] [blame]
Bardia Mahjourdb800c22019-09-18 17:43:45 +00001//===- DependenceGraphBuilder.cpp ------------------------------------------==//
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// This file implements common steps of the build algorithm for construction
9// of dependence graphs such as DDG and PDG.
10//===----------------------------------------------------------------------===//
11
12#include "llvm/Analysis/DependenceGraphBuilder.h"
13#include "llvm/ADT/SCCIterator.h"
14#include "llvm/ADT/Statistic.h"
15#include "llvm/Analysis/DDG.h"
16
17using namespace llvm;
18
19#define DEBUG_TYPE "dgb"
20
21STATISTIC(TotalGraphs, "Number of dependence graphs created.");
22STATISTIC(TotalDefUseEdges, "Number of def-use edges created.");
23STATISTIC(TotalMemoryEdges, "Number of memory dependence edges created.");
24STATISTIC(TotalFineGrainedNodes, "Number of fine-grained nodes created.");
25STATISTIC(TotalConfusedEdges,
26 "Number of confused memory dependencies between two nodes.");
27STATISTIC(TotalEdgeReversals,
28 "Number of times the source and sink of dependence was reversed to "
29 "expose cycles in the graph.");
30
31using InstructionListType = SmallVector<Instruction *, 2>;
32
33//===--------------------------------------------------------------------===//
34// AbstractDependenceGraphBuilder implementation
35//===--------------------------------------------------------------------===//
36
37template <class G>
38void AbstractDependenceGraphBuilder<G>::createFineGrainedNodes() {
39 ++TotalGraphs;
40 assert(IMap.empty() && "Expected empty instruction map at start");
41 for (BasicBlock *BB : BBList)
42 for (Instruction &I : *BB) {
43 auto &NewNode = createFineGrainedNode(I);
44 IMap.insert(std::make_pair(&I, &NewNode));
45 ++TotalFineGrainedNodes;
46 }
47}
48
49template <class G> void AbstractDependenceGraphBuilder<G>::createDefUseEdges() {
50 for (NodeType *N : Graph) {
51 InstructionListType SrcIList;
52 N->collectInstructions([](const Instruction *I) { return true; }, SrcIList);
53
54 // Use a set to mark the targets that we link to N, so we don't add
55 // duplicate def-use edges when more than one instruction in a target node
56 // use results of instructions that are contained in N.
57 SmallPtrSet<NodeType *, 4> VisitedTargets;
58
59 for (Instruction *II : SrcIList) {
60 for (User *U : II->users()) {
61 Instruction *UI = dyn_cast<Instruction>(U);
62 if (!UI)
63 continue;
64 NodeType *DstNode = nullptr;
65 if (IMap.find(UI) != IMap.end())
66 DstNode = IMap.find(UI)->second;
67
68 // In the case of loops, the scope of the subgraph is all the
69 // basic blocks (and instructions within them) belonging to the loop. We
70 // simply ignore all the edges coming from (or going into) instructions
71 // or basic blocks outside of this range.
72 if (!DstNode) {
73 LLVM_DEBUG(
74 dbgs()
75 << "skipped def-use edge since the sink" << *UI
76 << " is outside the range of instructions being considered.\n");
77 continue;
78 }
79
80 // Self dependencies are ignored because they are redundant and
81 // uninteresting.
82 if (DstNode == N) {
83 LLVM_DEBUG(dbgs()
84 << "skipped def-use edge since the sink and the source ("
85 << N << ") are the same.\n");
86 continue;
87 }
88
89 if (VisitedTargets.insert(DstNode).second) {
90 createDefUseEdge(*N, *DstNode);
91 ++TotalDefUseEdges;
92 }
93 }
94 }
95 }
96}
97
98template <class G>
99void AbstractDependenceGraphBuilder<G>::createMemoryDependencyEdges() {
100 using DGIterator = typename G::iterator;
101 auto isMemoryAccess = [](const Instruction *I) {
102 return I->mayReadOrWriteMemory();
103 };
104 for (DGIterator SrcIt = Graph.begin(), E = Graph.end(); SrcIt != E; ++SrcIt) {
105 InstructionListType SrcIList;
106 (*SrcIt)->collectInstructions(isMemoryAccess, SrcIList);
107 if (SrcIList.empty())
108 continue;
109
110 for (DGIterator DstIt = SrcIt; DstIt != E; ++DstIt) {
111 if (**SrcIt == **DstIt)
112 continue;
113 InstructionListType DstIList;
114 (*DstIt)->collectInstructions(isMemoryAccess, DstIList);
115 if (DstIList.empty())
116 continue;
117 bool ForwardEdgeCreated = false;
118 bool BackwardEdgeCreated = false;
119 for (Instruction *ISrc : SrcIList) {
120 for (Instruction *IDst : DstIList) {
121 auto D = DI.depends(ISrc, IDst, true);
122 if (!D)
123 continue;
124
125 // If we have a dependence with its left-most non-'=' direction
126 // being '>' we need to reverse the direction of the edge, because
127 // the source of the dependence cannot occur after the sink. For
128 // confused dependencies, we will create edges in both directions to
129 // represent the possibility of a cycle.
130
131 auto createConfusedEdges = [&](NodeType &Src, NodeType &Dst) {
132 if (!ForwardEdgeCreated) {
133 createMemoryEdge(Src, Dst);
134 ++TotalMemoryEdges;
135 }
136 if (!BackwardEdgeCreated) {
137 createMemoryEdge(Dst, Src);
138 ++TotalMemoryEdges;
139 }
140 ForwardEdgeCreated = BackwardEdgeCreated = true;
141 ++TotalConfusedEdges;
142 };
143
144 auto createForwardEdge = [&](NodeType &Src, NodeType &Dst) {
145 if (!ForwardEdgeCreated) {
146 createMemoryEdge(Src, Dst);
147 ++TotalMemoryEdges;
148 }
149 ForwardEdgeCreated = true;
150 };
151
152 auto createBackwardEdge = [&](NodeType &Src, NodeType &Dst) {
153 if (!BackwardEdgeCreated) {
154 createMemoryEdge(Dst, Src);
155 ++TotalMemoryEdges;
156 }
157 BackwardEdgeCreated = true;
158 };
159
160 if (D->isConfused())
161 createConfusedEdges(**SrcIt, **DstIt);
162 else if (D->isOrdered() && !D->isLoopIndependent()) {
163 bool ReversedEdge = false;
164 for (unsigned Level = 1; Level <= D->getLevels(); ++Level) {
165 if (D->getDirection(Level) == Dependence::DVEntry::EQ)
166 continue;
167 else if (D->getDirection(Level) == Dependence::DVEntry::GT) {
168 createBackwardEdge(**SrcIt, **DstIt);
169 ReversedEdge = true;
170 ++TotalEdgeReversals;
171 break;
172 } else if (D->getDirection(Level) == Dependence::DVEntry::LT)
173 break;
174 else {
175 createConfusedEdges(**SrcIt, **DstIt);
176 break;
177 }
178 }
179 if (!ReversedEdge)
180 createForwardEdge(**SrcIt, **DstIt);
181 } else
182 createForwardEdge(**SrcIt, **DstIt);
183
184 // Avoid creating duplicate edges.
185 if (ForwardEdgeCreated && BackwardEdgeCreated)
186 break;
187 }
188
189 // If we've created edges in both directions, there is no more
190 // unique edge that we can create between these two nodes, so we
191 // can exit early.
192 if (ForwardEdgeCreated && BackwardEdgeCreated)
193 break;
194 }
195 }
196 }
197}
198
199template class llvm::AbstractDependenceGraphBuilder<DataDependenceGraph>;
200template class llvm::DependenceGraphInfo<DDGNode>;