diff options
author | River Riddle <riddleriver@gmail.com> | 2022-01-20 17:32:31 -0800 |
---|---|---|
committer | River Riddle <riddleriver@gmail.com> | 2022-01-24 19:25:53 -0800 |
commit | a70aa7bb0d9a6066831b339e0a09a2c1bc74fe2b (patch) | |
tree | 7e807bcabf3cda9403351e442a3f74b3fae01756 /mlir/lib/Transforms/LoopInvariantCodeMotion.cpp | |
parent | 2e2c0738e80e9c2b7c1413ca4719d5be2df4c6b5 (diff) | |
download | llvm-a70aa7bb0d9a6066831b339e0a09a2c1bc74fe2b.zip llvm-a70aa7bb0d9a6066831b339e0a09a2c1bc74fe2b.tar.gz llvm-a70aa7bb0d9a6066831b339e0a09a2c1bc74fe2b.tar.bz2 |
[mlir:Transforms] Move out the remaining non-dialect independent transforms and utilities
This has been a major TODO for a very long time, and is necessary for establishing a proper
dialect-free dependency layering for the Transforms library. Code was moved to effectively
two main locations:
* Affine/
There was quite a bit of affine dialect related code in Transforms/ do to historical reasons
(of a time way into MLIR's past). The following headers were moved to:
Transforms/LoopFusionUtils.h -> Dialect/Affine/LoopFusionUtils.h
Transforms/LoopUtils.h -> Dialect/Affine/LoopUtils.h
Transforms/Utils.h -> Dialect/Affine/Utils.h
The following transforms were also moved:
AffineLoopFusion, AffinePipelineDataTransfer, LoopCoalescing
* SCF/
Only one SCF pass was in Transforms/ (likely accidentally placed here): ParallelLoopCollapsing
The SCF specific utilities in LoopUtils have been moved to SCF/Utils.h
* Misc:
mlir::moveLoopInvariantCode was also moved to LoopLikeInterface.h given
that it is a simple utility defined in terms of LoopLikeOpInterface.
Differential Revision: https://reviews.llvm.org/D117848
Diffstat (limited to 'mlir/lib/Transforms/LoopInvariantCodeMotion.cpp')
-rw-r--r-- | mlir/lib/Transforms/LoopInvariantCodeMotion.cpp | 79 |
1 files changed, 1 insertions, 78 deletions
diff --git a/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp b/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp index 3c8e14a..e4e3c16 100644 --- a/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp +++ b/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp @@ -11,13 +11,10 @@ //===----------------------------------------------------------------------===// #include "PassDetail.h" -#include "mlir/Transforms/Passes.h" - #include "mlir/IR/Builders.h" -#include "mlir/IR/BuiltinOps.h" #include "mlir/Interfaces/LoopLikeInterface.h" #include "mlir/Interfaces/SideEffectInterfaces.h" -#include "mlir/Transforms/LoopUtils.h" +#include "mlir/Transforms/Passes.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -34,80 +31,6 @@ struct LoopInvariantCodeMotion }; } // namespace -// Checks whether the given op can be hoisted by checking that -// - the op and any of its contained operations do not depend on SSA values -// defined inside of the loop (by means of calling definedOutside). -// - the op has no side-effects. If sideEffecting is Never, sideeffects of this -// op and its nested ops are ignored. -static bool canBeHoisted(Operation *op, - function_ref<bool(Value)> definedOutside) { - // Check that dependencies are defined outside of loop. - if (!llvm::all_of(op->getOperands(), definedOutside)) - return false; - // Check whether this op is side-effect free. If we already know that there - // can be no side-effects because the surrounding op has claimed so, we can - // (and have to) skip this step. - if (auto memInterface = dyn_cast<MemoryEffectOpInterface>(op)) { - if (!memInterface.hasNoEffect()) - return false; - // If the operation doesn't have side effects and it doesn't recursively - // have side effects, it can always be hoisted. - if (!op->hasTrait<OpTrait::HasRecursiveSideEffects>()) - return true; - - // Otherwise, if the operation doesn't provide the memory effect interface - // and it doesn't have recursive side effects we treat it conservatively as - // side-effecting. - } else if (!op->hasTrait<OpTrait::HasRecursiveSideEffects>()) { - return false; - } - - // Recurse into the regions for this op and check whether the contained ops - // can be hoisted. - for (auto ®ion : op->getRegions()) { - for (auto &block : region) { - for (auto &innerOp : block) - if (!canBeHoisted(&innerOp, definedOutside)) - return false; - } - } - return true; -} - -LogicalResult mlir::moveLoopInvariantCode(LoopLikeOpInterface looplike) { - auto &loopBody = looplike.getLoopBody(); - - // We use two collections here as we need to preserve the order for insertion - // and this is easiest. - SmallPtrSet<Operation *, 8> willBeMovedSet; - SmallVector<Operation *, 8> opsToMove; - - // Helper to check whether an operation is loop invariant wrt. SSA properties. - auto isDefinedOutsideOfBody = [&](Value value) { - auto *definingOp = value.getDefiningOp(); - return (definingOp && !!willBeMovedSet.count(definingOp)) || - looplike.isDefinedOutsideOfLoop(value); - }; - - // Do not use walk here, as we do not want to go into nested regions and hoist - // operations from there. These regions might have semantics unknown to this - // rewriting. If the nested regions are loops, they will have been processed. - for (auto &block : loopBody) { - for (auto &op : block.without_terminator()) { - if (canBeHoisted(&op, isDefinedOutsideOfBody)) { - opsToMove.push_back(&op); - willBeMovedSet.insert(&op); - } - } - } - - // For all instructions that we found to be invariant, move outside of the - // loop. - auto result = looplike.moveOutOfLoop(opsToMove); - LLVM_DEBUG(looplike.print(llvm::dbgs() << "\n\nModified loop:\n")); - return result; -} - void LoopInvariantCodeMotion::runOnOperation() { // Walk through all loops in a function in innermost-loop-first order. This // way, we first LICM from the inner loop, and place the ops in |