18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/raw_ostream.h"
23 #define GEN_PASS_DEF_AFFINELOOPINVARIANTCODEMOTION
24 #include "mlir/Dialect/Affine/Passes.h.inc"
28 #define DEBUG_TYPE "affine-licm"
43 struct LoopInvariantCodeMotion
44 :
public affine::impl::AffineLoopInvariantCodeMotionBase<
45 LoopInvariantCodeMotion> {
46 void runOnOperation()
override;
47 void runOnAffineForOp(AffineForOp forOp);
53 SmallPtrSetImpl<Operation *> &opsWithUsers,
54 SmallPtrSetImpl<Operation *> &opsToHoist);
56 SmallPtrSetImpl<Operation *> &opsWithUsers,
57 SmallPtrSetImpl<Operation *> &opsToHoist);
61 SmallPtrSetImpl<Operation *> &opsWithUsers,
62 SmallPtrSetImpl<Operation *> &opsToHoist);
66 SmallPtrSetImpl<Operation *> &opsWithUsers,
67 SmallPtrSetImpl<Operation *> &opsToHoist) {
68 Value iv = loop.getInductionVar();
70 if (
auto ifOp = dyn_cast<AffineIfOp>(op)) {
73 }
else if (
auto forOp = dyn_cast<AffineForOp>(op)) {
77 }
else if (
auto parOp = dyn_cast<AffineParallelOp>(op)) {
82 !isa<AffineReadOpInterface, AffineWriteOpInterface>(&op)) {
86 }
else if (isa<AffineReadOpInterface, AffineWriteOpInterface>(op)) {
88 opsWithUsers.insert(&op);
90 auto read = dyn_cast<AffineReadOpInterface>(op);
92 read ? read.getMemRef() : cast<AffineWriteOpInterface>(op).getMemRef();
93 for (
auto *user : memref.
getUsers()) {
100 if (hasEffect<MemoryEffects::Write>(user, memref) ||
101 (hasEffect<MemoryEffects::Read>(user, memref) &&
102 isa<AffineWriteOpInterface>(op))) {
106 if (llvm::is_contained(userIVs, loop))
113 ValueRange iterArgs = loop.getRegionIterArgs();
122 if (llvm::is_contained(iterArgs, op.
getOperand(i)))
129 if (opsWithUsers.count(operandSrc) && opsToHoist.count(operandSrc) == 0)
135 opsToHoist.insert(&op);
142 SmallPtrSetImpl<Operation *> &opsWithUsers,
143 SmallPtrSetImpl<Operation *> &opsToHoist) {
145 for (
auto &b : blockList) {
158 SmallPtrSetImpl<Operation *> &opsWithUsers,
159 SmallPtrSetImpl<Operation *> &opsToHoist) {
161 opsWithUsers, opsToHoist))
165 opsWithUsers, opsToHoist))
171 void LoopInvariantCodeMotion::runOnAffineForOp(AffineForOp forOp) {
184 opsWithUsers.insert(&op);
185 if (!isa<AffineYieldOp>(op)) {
187 opsToMove.push_back(&op);
194 for (
auto *op : opsToMove) {
195 op->moveBefore(forOp);
199 void LoopInvariantCodeMotion::runOnOperation() {
203 getOperation().walk([&](AffineForOp op) { runOnAffineForOp(op); });
206 std::unique_ptr<OperationPass<func::FuncOp>>
208 return std::make_unique<LoopInvariantCodeMotion>();
static bool isOpLoopInvariant(Operation &op, AffineForOp loop, SmallPtrSetImpl< Operation * > &opsWithUsers, SmallPtrSetImpl< Operation * > &opsToHoist)
Returns true if op is invariant on loop.
static bool areAllOpsInTheBlockListInvariant(Region &blockList, AffineForOp loop, SmallPtrSetImpl< Operation * > &opsWithUsers, SmallPtrSetImpl< Operation * > &opsToHoist)
static bool checkInvarianceOfNestedIfOps(AffineIfOp ifOp, AffineForOp loop, SmallPtrSetImpl< Operation * > &opsWithUsers, SmallPtrSetImpl< Operation * > &opsToHoist)
This class helps build Operations.
Operation is the basic unit of execution within MLIR.
Value getOperand(unsigned idx)
unsigned getNumOperands()
This class contains a list of basic blocks and a link to the parent operation it is attached to.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
user_range getUsers() const
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
std::unique_ptr< OperationPass< func::FuncOp > > createAffineLoopInvariantCodeMotionPass()
Creates a loop invariant code motion pass that hoists loop invariant operations out of affine loops.
void getAffineForIVs(Operation &op, SmallVectorImpl< AffineForOp > *loops)
Populates 'loops' with IVs of the affine.for ops surrounding 'op' ordered from the outermost 'affine....
Include the generated interface declarations.
bool isMemoryEffectFree(Operation *op)
Returns true if the given operation is free of memory effects.