1faab8c14STres Popp //======- BufferViewFlowAnalysis.cpp - Buffer alias analysis -*- C++ -*-======//
2faab8c14STres Popp //
3faab8c14STres Popp // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4faab8c14STres Popp // See https://llvm.org/LICENSE.txt for license information.
5faab8c14STres Popp // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6faab8c14STres Popp //
7faab8c14STres Popp //===----------------------------------------------------------------------===//
8faab8c14STres Popp 
9faab8c14STres Popp #include "mlir/Analysis/BufferViewFlowAnalysis.h"
10faab8c14STres Popp 
11faab8c14STres Popp #include "mlir/Interfaces/ControlFlowInterfaces.h"
12faab8c14STres Popp #include "mlir/Interfaces/ViewLikeInterface.h"
13faab8c14STres Popp #include "llvm/ADT/SetOperations.h"
14faab8c14STres Popp 
15faab8c14STres Popp using namespace mlir;
16faab8c14STres Popp 
17faab8c14STres Popp /// Constructs a new alias analysis using the op provided.
BufferViewFlowAnalysis(Operation * op)18faab8c14STres Popp BufferViewFlowAnalysis::BufferViewFlowAnalysis(Operation *op) { build(op); }
19faab8c14STres Popp 
20faab8c14STres Popp /// Find all immediate and indirect dependent buffers this value could
21faab8c14STres Popp /// potentially have. Note that the resulting set will also contain the value
22faab8c14STres Popp /// provided as it is a dependent alias of itself.
23faab8c14STres Popp BufferViewFlowAnalysis::ValueSetT
resolve(Value rootValue) const24faab8c14STres Popp BufferViewFlowAnalysis::resolve(Value rootValue) const {
25faab8c14STres Popp   ValueSetT result;
26faab8c14STres Popp   SmallVector<Value, 8> queue;
27faab8c14STres Popp   queue.push_back(rootValue);
28faab8c14STres Popp   while (!queue.empty()) {
29faab8c14STres Popp     Value currentValue = queue.pop_back_val();
30faab8c14STres Popp     if (result.insert(currentValue).second) {
31faab8c14STres Popp       auto it = dependencies.find(currentValue);
32faab8c14STres Popp       if (it != dependencies.end()) {
33faab8c14STres Popp         for (Value aliasValue : it->second)
34faab8c14STres Popp           queue.push_back(aliasValue);
35faab8c14STres Popp       }
36faab8c14STres Popp     }
37faab8c14STres Popp   }
38faab8c14STres Popp   return result;
39faab8c14STres Popp }
40faab8c14STres Popp 
41faab8c14STres Popp /// Removes the given values from all alias sets.
remove(const SmallPtrSetImpl<Value> & aliasValues)42faab8c14STres Popp void BufferViewFlowAnalysis::remove(const SmallPtrSetImpl<Value> &aliasValues) {
43faab8c14STres Popp   for (auto &entry : dependencies)
44faab8c14STres Popp     llvm::set_subtract(entry.second, aliasValues);
45faab8c14STres Popp }
46faab8c14STres Popp 
47faab8c14STres Popp /// This function constructs a mapping from values to its immediate
48faab8c14STres Popp /// dependencies. It iterates over all blocks, gets their predecessors,
49faab8c14STres Popp /// determines the values that will be passed to the corresponding block
50faab8c14STres Popp /// arguments and inserts them into the underlying map. Furthermore, it wires
51faab8c14STres Popp /// successor regions and branch-like return operations from nested regions.
build(Operation * op)52faab8c14STres Popp void BufferViewFlowAnalysis::build(Operation *op) {
53faab8c14STres Popp   // Registers all dependencies of the given values.
54faab8c14STres Popp   auto registerDependencies = [&](auto values, auto dependencies) {
55faab8c14STres Popp     for (auto entry : llvm::zip(values, dependencies))
56faab8c14STres Popp       this->dependencies[std::get<0>(entry)].insert(std::get<1>(entry));
57faab8c14STres Popp   };
58faab8c14STres Popp 
59faab8c14STres Popp   // Add additional dependencies created by view changes to the alias list.
60faab8c14STres Popp   op->walk([&](ViewLikeOpInterface viewInterface) {
61faab8c14STres Popp     dependencies[viewInterface.getViewSource()].insert(
62faab8c14STres Popp         viewInterface->getResult(0));
63faab8c14STres Popp   });
64faab8c14STres Popp 
65faab8c14STres Popp   // Query all branch interfaces to link block argument dependencies.
66faab8c14STres Popp   op->walk([&](BranchOpInterface branchInterface) {
67faab8c14STres Popp     Block *parentBlock = branchInterface->getBlock();
68faab8c14STres Popp     for (auto it = parentBlock->succ_begin(), e = parentBlock->succ_end();
69faab8c14STres Popp          it != e; ++it) {
70faab8c14STres Popp       // Query the branch op interface to get the successor operands.
71faab8c14STres Popp       auto successorOperands =
72faab8c14STres Popp           branchInterface.getSuccessorOperands(it.getIndex());
73faab8c14STres Popp       // Build the actual mapping of values to their immediate dependencies.
74*0c789db5SMarkus Böck       registerDependencies(successorOperands.getForwardedOperands(),
75*0c789db5SMarkus Böck                            (*it)->getArguments().drop_front(
76*0c789db5SMarkus Böck                                successorOperands.getProducedOperandCount()));
77faab8c14STres Popp     }
78faab8c14STres Popp   });
79faab8c14STres Popp 
80faab8c14STres Popp   // Query the RegionBranchOpInterface to find potential successor regions.
81faab8c14STres Popp   op->walk([&](RegionBranchOpInterface regionInterface) {
82faab8c14STres Popp     // Extract all entry regions and wire all initial entry successor inputs.
83faab8c14STres Popp     SmallVector<RegionSuccessor, 2> entrySuccessors;
84faab8c14STres Popp     regionInterface.getSuccessorRegions(/*index=*/llvm::None, entrySuccessors);
85faab8c14STres Popp     for (RegionSuccessor &entrySuccessor : entrySuccessors) {
86faab8c14STres Popp       // Wire the entry region's successor arguments with the initial
87faab8c14STres Popp       // successor inputs.
88faab8c14STres Popp       assert(entrySuccessor.getSuccessor() &&
89faab8c14STres Popp              "Invalid entry region without an attached successor region");
90faab8c14STres Popp       registerDependencies(
91faab8c14STres Popp           regionInterface.getSuccessorEntryOperands(
92faab8c14STres Popp               entrySuccessor.getSuccessor()->getRegionNumber()),
93faab8c14STres Popp           entrySuccessor.getSuccessorInputs());
94faab8c14STres Popp     }
95faab8c14STres Popp 
96faab8c14STres Popp     // Wire flow between regions and from region exits.
97faab8c14STres Popp     for (Region &region : regionInterface->getRegions()) {
98faab8c14STres Popp       // Iterate over all successor region entries that are reachable from the
99faab8c14STres Popp       // current region.
100faab8c14STres Popp       SmallVector<RegionSuccessor, 2> successorRegions;
101faab8c14STres Popp       regionInterface.getSuccessorRegions(region.getRegionNumber(),
102faab8c14STres Popp                                           successorRegions);
103faab8c14STres Popp       for (RegionSuccessor &successorRegion : successorRegions) {
10404253320SMarcel Koester         // Determine the current region index (if any).
10504253320SMarcel Koester         Optional<unsigned> regionIndex;
10604253320SMarcel Koester         Region *regionSuccessor = successorRegion.getSuccessor();
10704253320SMarcel Koester         if (regionSuccessor)
10804253320SMarcel Koester           regionIndex = regionSuccessor->getRegionNumber();
109faab8c14STres Popp         // Iterate over all immediate terminator operations and wire the
11004253320SMarcel Koester         // successor inputs with the successor operands of each terminator.
111faab8c14STres Popp         for (Block &block : region) {
11204253320SMarcel Koester           auto successorOperands = getRegionBranchSuccessorOperands(
11304253320SMarcel Koester               block.getTerminator(), regionIndex);
11404253320SMarcel Koester           if (successorOperands) {
11504253320SMarcel Koester             registerDependencies(*successorOperands,
116faab8c14STres Popp                                  successorRegion.getSuccessorInputs());
117faab8c14STres Popp           }
118faab8c14STres Popp         }
119faab8c14STres Popp       }
120faab8c14STres Popp     }
121faab8c14STres Popp   });
122faab8c14STres Popp }
123