16 #include "mlir/Dialect/Affine/IR/AffineOps.h"
17 #include "mlir/Dialect/Affine/LoopUtils.h"
18 #include "mlir/Dialect/Func/IR/FuncOps.h"
19 #include "mlir/Dialect/MemRef/IR/MemRef.h"
20 #include "mlir/Dialect/SCF/IR/SCF.h"
21 #include "mlir/IR/BuiltinOps.h"
22 #include "mlir/Pass/AnalysisManager.h"
33 Operation *op, AnalysisManager &am) {
34 auto funcOp = cast<func::FuncOp>(op);
40 for (
auto root : funcOp.getOps<AffineForOp>()) {
41 SmallVector<AffineForOp> nestedLoops;
42 getPerfectlyNestedLoops(nestedLoops, root);
43 analyzeForOp(nestedLoops.back(), memoryAnalysis);
53 forOp.getBody()->walk([&](Operation *op) {
57 ArrayRef<MemoryDependence> dependences = memoryAnalysis.
getDependences(op);
58 if (dependences.empty())
63 if (!hasDependence(memoryDep.dependenceType))
69 assert(succeeded(depInserted));
76 unsigned distance = *memoryDep.dependenceComponents.back().lb;
83 forOp.getBody()->walk([&](Operation *op) {
84 Block *thenBlock =
nullptr;
85 Block *elseBlock =
nullptr;
86 if (
auto ifOp = dyn_cast<scf::IfOp>(op)) {
87 thenBlock = ifOp.thenBlock();
88 elseBlock = ifOp.elseBlock();
89 }
else if (
auto ifOp = dyn_cast<AffineIfOp>(op)) {
90 thenBlock = ifOp.getThenBlock();
92 elseBlock = ifOp.getElseBlock();
94 return WalkResult::advance();
98 if (op->getNumResults() == 0)
99 return WalkResult::skip();
104 assert(succeeded(depInserted));
110 assert(succeeded(depInserted));
114 return WalkResult::advance();
119 auto *anchor = forOp.getBody()->getTerminator();
120 forOp.getBody()->walk([&](Operation *op) {
121 if (!isa<AffineStoreOp, memref::StoreOp>(op))
125 assert(succeeded(depInserted));
132 if (
unsigned nIterArgs = anchor->getNumOperands(); nIterArgs > 0) {
133 auto iterArgs = forOp.getRegionIterArgs();
134 for (
unsigned i = 0; i < nIterArgs; ++i) {
135 Operation *iterArgDefiner = anchor->getOperand(i).getDefiningOp();
140 for (Operation *iterArgUser : iterArgs[i].getUsers()) {
143 assert(succeeded(depInserted));
153 problems.insert(std::pair<Operation *, CyclicProblem>(forOp, problem));
158 auto problem = problems.find(forOp);
159 assert(problem != problems.end() &&
"expected problem to exist");
160 return problem->second;
This class models a cyclic scheduling problem.
void setDistance(Dependence dep, unsigned val)
void insertOperation(Operation *op)
Include op in this scheduling problem.
LogicalResult insertDependence(Dependence dep)
Include dep in the scheduling problem.
A wrapper class to uniformly handle def-use and auxiliary dependence edges.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
CyclicProblem & getProblem(affine::AffineForOp forOp)
CyclicSchedulingAnalysis(Operation *funcOp, AnalysisManager &am)
CyclicSchedulingAnalysis constructs a CyclicProblem for each AffineForOp by performing a memory depen...
void analyzeForOp(affine::AffineForOp forOp, MemoryDependenceAnalysis memoryAnalysis)
MemoryDependenceAnalysis traverses any AffineForOps in the FuncOp body and checks for affine memory a...
ArrayRef< MemoryDependence > getDependences(Operation *)
Returns the dependences, if any, that the given Operation depends on.
MemoryDependence captures a dependence from one memory operation to another.