|
27 | 27 | #include "llvm/ADT/DenseMap.h"
|
28 | 28 | #include "llvm/ADT/DenseSet.h"
|
29 | 29 | #include "llvm/ADT/STLExtras.h"
|
30 |
| -#include "llvm/ADT/SetVector.h" |
31 | 30 | #include "llvm/Support/CommandLine.h"
|
32 | 31 | #include "llvm/Support/Debug.h"
|
33 | 32 | #include "llvm/Support/raw_ostream.h"
|
@@ -226,127 +225,6 @@ static void gatherEscapingMemrefs(unsigned id, MemRefDependenceGraph *mdg,
|
226 | 225 | }
|
227 | 226 | }
|
228 | 227 |
|
229 |
| -// Initializes the data dependence graph by walking operations in `block`. |
230 |
| -// Assigns each node in the graph a node id based on program order in 'f'. |
231 |
| -bool MemRefDependenceGraph::init() { |
232 |
| - LLVM_DEBUG(llvm::dbgs() << "--- Initializing MDG ---\n"); |
233 |
| - // Map from a memref to the set of ids of the nodes that have ops accessing |
234 |
| - // the memref. |
235 |
| - DenseMap<Value, SetVector<unsigned>> memrefAccesses; |
236 |
| - |
237 |
| - DenseMap<Operation *, unsigned> forToNodeMap; |
238 |
| - for (Operation &op : block) { |
239 |
| - if (dyn_cast<AffineForOp>(op)) { |
240 |
| - // Create graph node 'id' to represent top-level 'forOp' and record |
241 |
| - // all loads and store accesses it contains. |
242 |
| - LoopNestStateCollector collector; |
243 |
| - collector.collect(&op); |
244 |
| - // Return false if a region holding op other than 'affine.for' and |
245 |
| - // 'affine.if' was found (not currently supported). |
246 |
| - if (collector.hasNonAffineRegionOp) |
247 |
| - return false; |
248 |
| - Node node(nextNodeId++, &op); |
249 |
| - for (auto *opInst : collector.loadOpInsts) { |
250 |
| - node.loads.push_back(opInst); |
251 |
| - auto memref = cast<AffineReadOpInterface>(opInst).getMemRef(); |
252 |
| - memrefAccesses[memref].insert(node.id); |
253 |
| - } |
254 |
| - for (auto *opInst : collector.storeOpInsts) { |
255 |
| - node.stores.push_back(opInst); |
256 |
| - auto memref = cast<AffineWriteOpInterface>(opInst).getMemRef(); |
257 |
| - memrefAccesses[memref].insert(node.id); |
258 |
| - } |
259 |
| - forToNodeMap[&op] = node.id; |
260 |
| - nodes.insert({node.id, node}); |
261 |
| - } else if (dyn_cast<AffineReadOpInterface>(op)) { |
262 |
| - // Create graph node for top-level load op. |
263 |
| - Node node(nextNodeId++, &op); |
264 |
| - node.loads.push_back(&op); |
265 |
| - auto memref = cast<AffineReadOpInterface>(op).getMemRef(); |
266 |
| - memrefAccesses[memref].insert(node.id); |
267 |
| - nodes.insert({node.id, node}); |
268 |
| - } else if (dyn_cast<AffineWriteOpInterface>(op)) { |
269 |
| - // Create graph node for top-level store op. |
270 |
| - Node node(nextNodeId++, &op); |
271 |
| - node.stores.push_back(&op); |
272 |
| - auto memref = cast<AffineWriteOpInterface>(op).getMemRef(); |
273 |
| - memrefAccesses[memref].insert(node.id); |
274 |
| - nodes.insert({node.id, node}); |
275 |
| - } else if (op.getNumRegions() != 0) { |
276 |
| - // Return false if another region is found (not currently supported). |
277 |
| - return false; |
278 |
| - } else if (op.getNumResults() > 0 && !op.use_empty()) { |
279 |
| - // Create graph node for top-level producer of SSA values, which |
280 |
| - // could be used by loop nest nodes. |
281 |
| - Node node(nextNodeId++, &op); |
282 |
| - nodes.insert({node.id, node}); |
283 |
| - } else if (isa<CallOpInterface>(op)) { |
284 |
| - // Create graph node for top-level Call Op that takes any argument of |
285 |
| - // memref type. Call Op that returns one or more memref type results |
286 |
| - // is already taken care of, by the previous conditions. |
287 |
| - if (llvm::any_of(op.getOperandTypes(), |
288 |
| - [&](Type t) { return isa<MemRefType>(t); })) { |
289 |
| - Node node(nextNodeId++, &op); |
290 |
| - nodes.insert({node.id, node}); |
291 |
| - } |
292 |
| - } else if (hasEffect<MemoryEffects::Write, MemoryEffects::Free>(&op)) { |
293 |
| - // Create graph node for top-level op, which could have a memory write |
294 |
| - // side effect. |
295 |
| - Node node(nextNodeId++, &op); |
296 |
| - nodes.insert({node.id, node}); |
297 |
| - } |
298 |
| - } |
299 |
| - |
300 |
| - for (auto &idAndNode : nodes) { |
301 |
| - LLVM_DEBUG(llvm::dbgs() << "Create node " << idAndNode.first << " for:\n" |
302 |
| - << *(idAndNode.second.op) << "\n"); |
303 |
| - (void)idAndNode; |
304 |
| - } |
305 |
| - |
306 |
| - // Add dependence edges between nodes which produce SSA values and their |
307 |
| - // users. Load ops can be considered as the ones producing SSA values. |
308 |
| - for (auto &idAndNode : nodes) { |
309 |
| - const Node &node = idAndNode.second; |
310 |
| - // Stores don't define SSA values, skip them. |
311 |
| - if (!node.stores.empty()) |
312 |
| - continue; |
313 |
| - Operation *opInst = node.op; |
314 |
| - for (Value value : opInst->getResults()) { |
315 |
| - for (Operation *user : value.getUsers()) { |
316 |
| - // Ignore users outside of the block. |
317 |
| - if (block.getParent()->findAncestorOpInRegion(*user)->getBlock() != |
318 |
| - &block) |
319 |
| - continue; |
320 |
| - SmallVector<AffineForOp, 4> loops; |
321 |
| - getAffineForIVs(*user, &loops); |
322 |
| - if (loops.empty()) |
323 |
| - continue; |
324 |
| - assert(forToNodeMap.count(loops[0]) > 0 && "missing mapping"); |
325 |
| - unsigned userLoopNestId = forToNodeMap[loops[0]]; |
326 |
| - addEdge(node.id, userLoopNestId, value); |
327 |
| - } |
328 |
| - } |
329 |
| - } |
330 |
| - |
331 |
| - // Walk memref access lists and add graph edges between dependent nodes. |
332 |
| - for (auto &memrefAndList : memrefAccesses) { |
333 |
| - unsigned n = memrefAndList.second.size(); |
334 |
| - for (unsigned i = 0; i < n; ++i) { |
335 |
| - unsigned srcId = memrefAndList.second[i]; |
336 |
| - bool srcHasStore = |
337 |
| - getNode(srcId)->getStoreOpCount(memrefAndList.first) > 0; |
338 |
| - for (unsigned j = i + 1; j < n; ++j) { |
339 |
| - unsigned dstId = memrefAndList.second[j]; |
340 |
| - bool dstHasStore = |
341 |
| - getNode(dstId)->getStoreOpCount(memrefAndList.first) > 0; |
342 |
| - if (srcHasStore || dstHasStore) |
343 |
| - addEdge(srcId, dstId, memrefAndList.first); |
344 |
| - } |
345 |
| - } |
346 |
| - } |
347 |
| - return true; |
348 |
| -} |
349 |
| - |
350 | 228 | // Sinks all sequential loops to the innermost levels (while preserving
|
351 | 229 | // relative order among them) and moves all parallel loops to the
|
352 | 230 | // outermost (while again preserving relative order among them).
|
|
0 commit comments