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"
34 Operation *op, AnalysisManager &am) {
35 auto funcOp = cast<func::FuncOp>(op);
41 for (
auto root : funcOp.getOps<AffineForOp>()) {
42 SmallVector<AffineForOp> nestedLoops;
43 getPerfectlyNestedLoops(nestedLoops, root);
44 analyzeForOp(nestedLoops.back(), memoryAnalysis);
54 forOp.getBody()->walk([&](Operation *op) {
58 ArrayRef<MemoryDependence> dependences = memoryAnalysis.
getDependences(op);
59 if (dependences.empty())
64 if (!hasDependence(memoryDep.dependenceType))
70 assert(succeeded(depInserted));
77 unsigned distance = *memoryDep.dependenceComponents.back().lb;
84 forOp.getBody()->walk([&](Operation *op) {
85 Block *thenBlock =
nullptr;
86 Block *elseBlock =
nullptr;
87 if (
auto ifOp = dyn_cast<scf::IfOp>(op)) {
88 thenBlock = ifOp.thenBlock();
89 elseBlock = ifOp.elseBlock();
90 }
else if (
auto ifOp = dyn_cast<AffineIfOp>(op)) {
91 thenBlock = ifOp.getThenBlock();
93 elseBlock = ifOp.getElseBlock();
95 return WalkResult::advance();
99 if (op->getNumResults() == 0)
100 return WalkResult::skip();
105 assert(succeeded(depInserted));
111 assert(succeeded(depInserted));
115 return WalkResult::advance();
120 auto *anchor = forOp.getBody()->getTerminator();
121 forOp.getBody()->walk([&](Operation *op) {
122 if (!isa<AffineStoreOp, memref::StoreOp>(op))
126 assert(succeeded(depInserted));
133 if (
unsigned nIterArgs = anchor->getNumOperands(); nIterArgs > 0) {
134 auto iterArgs = forOp.getRegionIterArgs();
135 for (
unsigned i = 0; i < nIterArgs; ++i) {
136 Operation *iterArgDefiner = anchor->getOperand(i).getDefiningOp();
141 for (Operation *iterArgUser : iterArgs[i].getUsers()) {
144 assert(succeeded(depInserted));
154 problems.insert(std::pair<Operation *, CyclicProblem>(forOp, problem));
159 auto problem = problems.find(forOp);
160 assert(problem != problems.end() &&
"expected problem to exist");
161 return problem->second;
assert(baseType &&"element must be base type")
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.
CyclicSchedulingAnalysis(Operation *funcOp, mlir::AnalysisManager &am)
CyclicSchedulingAnalysis constructs a CyclicProblem for each AffineForOp by performing a memory depen...
void analyzeForOp(mlir::affine::AffineForOp forOp, MemoryDependenceAnalysis memoryAnalysis)
scheduling::CyclicProblem & getProblem(mlir::affine::AffineForOp forOp)
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.