Skip to content

Commit

Permalink
Revert "[mlir] Refactor LICM into a utility"
Browse files Browse the repository at this point in the history
This reverts commit 3131f80.

This commit broke the Windows mlir bot:
https://lab.llvm.org/buildbot/#/builders/13/builds/19745
  • Loading branch information
sstamenova committed Apr 16, 2022
1 parent c6dc229 commit 353f0a8
Show file tree
Hide file tree
Showing 16 changed files with 167 additions and 268 deletions.
6 changes: 0 additions & 6 deletions mlir/include/mlir/IR/Region.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,12 +341,6 @@ class RegionRange
RegionRange(Arg &&arg)
: RegionRange(ArrayRef<std::unique_ptr<Region>>(std::forward<Arg>(arg))) {
}
template <typename Arg>
RegionRange(Arg &&arg,
typename std::enable_if_t<
std::is_constructible<ArrayRef<Region *>, Arg>::value &&
!std::is_convertible<Arg, Region *>::value> * = nullptr)
: RegionRange(ArrayRef<Region *>(std::forward<Arg>(arg))) {}
RegionRange(ArrayRef<std::unique_ptr<Region>> regions);
RegionRange(ArrayRef<Region *> regions);

Expand Down
13 changes: 13 additions & 0 deletions mlir/include/mlir/Interfaces/LoopLikeInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,20 @@

#include "mlir/IR/OpDefinition.h"

//===----------------------------------------------------------------------===//
// LoopLike Interfaces
//===----------------------------------------------------------------------===//

/// Include the generated interface declarations.
#include "mlir/Interfaces/LoopLikeInterface.h.inc"

//===----------------------------------------------------------------------===//
// LoopLike Utilities
//===----------------------------------------------------------------------===//

namespace mlir {
/// Move loop invariant code out of a `looplike` operation.
void moveLoopInvariantCode(LoopLikeOpInterface looplike);
} // namespace mlir

#endif // MLIR_INTERFACES_LOOPLIKEINTERFACE_H_
3 changes: 1 addition & 2 deletions mlir/include/mlir/Transforms/ControlFlowSinkUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class DominanceInfo;
class Operation;
class Region;
class RegionBranchOpInterface;
class RegionRange;

/// Given a list of regions, perform control flow sinking on them. For each
/// region, control-flow sinking moves operations that dominate the region but
Expand Down Expand Up @@ -62,7 +61,7 @@ class RegionRange;
///
/// Returns the number of operations sunk.
size_t
controlFlowSink(RegionRange regions, DominanceInfo &domInfo,
controlFlowSink(ArrayRef<Region *> regions, DominanceInfo &domInfo,
function_ref<bool(Operation *, Region *)> shouldMoveIntoRegion,
function_ref<void(Operation *, Region *)> moveIntoRegion);

Expand Down
75 changes: 0 additions & 75 deletions mlir/include/mlir/Transforms/LoopInvariantCodeMotionUtils.h

This file was deleted.

30 changes: 0 additions & 30 deletions mlir/include/mlir/Transforms/SideEffectUtils.h

This file was deleted.

1 change: 0 additions & 1 deletion mlir/lib/Dialect/Linalg/Transforms/Hoisting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Dominance.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "mlir/Transforms/LoopInvariantCodeMotionUtils.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
#include "mlir/Pass/PassManager.h"
#include "mlir/Support/LLVM.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "mlir/Transforms/LoopInvariantCodeMotionUtils.h"
#include "mlir/Transforms/Passes.h"

using namespace mlir;
Expand Down
15 changes: 14 additions & 1 deletion mlir/lib/Interfaces/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,17 @@ add_mlir_interface_library(SideEffectInterfaces)
add_mlir_interface_library(TilingInterface)
add_mlir_interface_library(VectorInterfaces)
add_mlir_interface_library(ViewLikeInterface)
add_mlir_interface_library(LoopLikeInterface)

add_mlir_library(MLIRLoopLikeInterface
LoopLikeInterface.cpp

ADDITIONAL_HEADER_DIRS
${MLIR_MAIN_INCLUDE_DIR}/mlir/Interfaces

DEPENDS
MLIRLoopLikeInterfaceIncGen

LINK_LIBS PUBLIC
MLIRIR
MLIRSideEffectInterfaces
)
100 changes: 100 additions & 0 deletions mlir/lib/Interfaces/LoopLikeInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,108 @@
//===----------------------------------------------------------------------===//

#include "mlir/Interfaces/LoopLikeInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
#include <queue>

using namespace mlir;

#define DEBUG_TYPE "loop-like"

//===----------------------------------------------------------------------===//
// LoopLike Interfaces
//===----------------------------------------------------------------------===//

/// Include the definitions of the loop-like interfaces.
#include "mlir/Interfaces/LoopLikeInterface.cpp.inc"

//===----------------------------------------------------------------------===//
// LoopLike Utilities
//===----------------------------------------------------------------------===//

/// Returns true if the given operation is side-effect free as are all of its
/// nested operations.
///
/// TODO: There is a duplicate function in ControlFlowSink. Move
/// `moveLoopInvariantCode` to TransformUtils and then factor out this function.
static bool isSideEffectFree(Operation *op) {
if (auto memInterface = dyn_cast<MemoryEffectOpInterface>(op)) {
// If the op has side-effects, it cannot be moved.
if (!memInterface.hasNoEffect())
return false;
// If the op does not have recursive side effects, then it can be moved.
if (!op->hasTrait<OpTrait::HasRecursiveSideEffects>())
return true;
} else if (!op->hasTrait<OpTrait::HasRecursiveSideEffects>()) {
// Otherwise, if the op does not implement the memory effect interface and
// it does not have recursive side effects, then it cannot be known that the
// op is moveable.
return false;
}

// Recurse into the regions and ensure that all nested ops can also be moved.
for (Region &region : op->getRegions())
for (Operation &op : region.getOps())
if (!isSideEffectFree(&op))
return false;
return true;
}

/// Checks whether the given op can be hoisted by checking that
/// - the op and none of its contained operations depend on values inside of the
/// loop (by means of calling definedOutside).
/// - the op has no side-effects.
static bool canBeHoisted(Operation *op,
function_ref<bool(Value)> definedOutside) {
if (!isSideEffectFree(op))
return false;

// Do not move terminators.
if (op->hasTrait<OpTrait::IsTerminator>())
return false;

// Walk the nested operations and check that all used values are either
// defined outside of the loop or in a nested region, but not at the level of
// the loop body.
auto walkFn = [&](Operation *child) {
for (Value operand : child->getOperands()) {
// Ignore values defined in a nested region.
if (op->isAncestor(operand.getParentRegion()->getParentOp()))
continue;
if (!definedOutside(operand))
return WalkResult::interrupt();
}
return WalkResult::advance();
};
return !op->walk(walkFn).wasInterrupted();
}

void mlir::moveLoopInvariantCode(LoopLikeOpInterface looplike) {
Region *loopBody = &looplike.getLoopBody();

std::queue<Operation *> worklist;
// Add top-level operations in the loop body to the worklist.
for (Operation &op : loopBody->getOps())
worklist.push(&op);

auto definedOutside = [&](Value value) {
return looplike.isDefinedOutsideOfLoop(value);
};

while (!worklist.empty()) {
Operation *op = worklist.front();
worklist.pop();
// Skip ops that have already been moved. Check if the op can be hoisted.
if (op->getParentRegion() != loopBody || !canBeHoisted(op, definedOutside))
continue;

looplike.moveOutOfLoop(op);

// Since the op has been moved, we need to check its users within the
// top-level of the loop body.
for (Operation *user : op->getUsers())
if (user->getParentRegion() == loopBody)
worklist.push(user);
}
}
26 changes: 25 additions & 1 deletion mlir/lib/Transforms/ControlFlowSink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Transforms/ControlFlowSinkUtils.h"
#include "mlir/Transforms/Passes.h"
#include "mlir/Transforms/SideEffectUtils.h"

using namespace mlir;

Expand All @@ -30,6 +29,31 @@ struct ControlFlowSink : public ControlFlowSinkBase<ControlFlowSink> {
};
} // end anonymous namespace

/// Returns true if the given operation is side-effect free as are all of its
/// nested operations.
static bool isSideEffectFree(Operation *op) {
if (auto memInterface = dyn_cast<MemoryEffectOpInterface>(op)) {
// If the op has side-effects, it cannot be moved.
if (!memInterface.hasNoEffect())
return false;
// If the op does not have recursive side effects, then it can be moved.
if (!op->hasTrait<OpTrait::HasRecursiveSideEffects>())
return true;
} else if (!op->hasTrait<OpTrait::HasRecursiveSideEffects>()) {
// Otherwise, if the op does not implement the memory effect interface and
// it does not have recursive side effects, then it cannot be known that the
// op is moveable.
return false;
}

// Recurse into the regions and ensure that all nested ops can also be moved.
for (Region &region : op->getRegions())
for (Operation &op : region.getOps())
if (!isSideEffectFree(&op))
return false;
return true;
}

void ControlFlowSink::runOnOperation() {
auto &domInfo = getAnalysis<DominanceInfo>();
getOperation()->walk([&](RegionBranchOpInterface branch) {
Expand Down
15 changes: 11 additions & 4 deletions mlir/lib/Transforms/LoopInvariantCodeMotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
//===----------------------------------------------------------------------===//

#include "PassDetail.h"
#include "mlir/IR/Builders.h"
#include "mlir/Interfaces/LoopLikeInterface.h"
#include "mlir/Transforms/LoopInvariantCodeMotionUtils.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Transforms/Passes.h"
#include "mlir/Transforms/SideEffectUtils.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"

#define DEBUG_TYPE "licm"

using namespace mlir;

Expand All @@ -30,8 +35,10 @@ 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
// the outer loop, which in turn can be further LICM'ed.
getOperation()->walk(
[&](LoopLikeOpInterface loopLike) { moveLoopInvariantCode(loopLike); });
getOperation()->walk([&](LoopLikeOpInterface loopLike) {
LLVM_DEBUG(loopLike.print(llvm::dbgs() << "\nOriginal loop:\n"));
moveLoopInvariantCode(loopLike);
});
}

std::unique_ptr<Pass> mlir::createLoopInvariantCodeMotionPass() {
Expand Down
3 changes: 0 additions & 3 deletions mlir/lib/Transforms/Utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@ add_mlir_library(MLIRTransformUtils
FoldUtils.cpp
GreedyPatternRewriteDriver.cpp
InliningUtils.cpp
LoopInvariantCodeMotionUtils.cpp
RegionUtils.cpp
SideEffectUtils.cpp

ADDITIONAL_HEADER_DIRS
${MLIR_MAIN_INCLUDE_DIR}/mlir/Transforms

LINK_LIBS PUBLIC
MLIRAnalysis
MLIRLoopLikeInterface
MLIRRewrite
)
Loading

0 comments on commit 353f0a8

Please sign in to comment.