/// Unrolls this for operation completely if the trip count is known to be
/// constant. Returns failure otherwise.
LogicalResult loopUnrollFull(AffineForOp forOp);
+
/// Unrolls this for operation by the specified unroll factor. Returns failure
/// if the loop cannot be unrolled either due to restrictions or due to invalid
/// unroll factors.
LogicalResult loopUnrollByFactor(AffineForOp forOp, uint64_t unrollFactor);
+
/// Unrolls this loop by the specified unroll factor or its trip count,
/// whichever is lower.
LogicalResult loopUnrollUpToFactor(AffineForOp forOp, uint64_t unrollFactor);
+/// Get perfectly nested sequence of loops starting at root of loop nest
+/// (the first op being another AffineFor, and the second op - a terminator).
+/// A loop is perfectly nested iff: the first op in the loop's body is another
+/// AffineForOp, and the second op is a terminator).
+void getPerfectlyNestedLoops(SmallVectorImpl<AffineForOp> &nestedLoops,
+ AffineForOp root);
+
/// Unrolls and jams this loop by the specified factor. Returns success if the
/// loop is successfully unroll-jammed.
LogicalResult loopUnrollJamByFactor(AffineForOp forOp,
// pushing loop carried dependence to a greater depth in the loop nest.
static void sinkSequentialLoops(MemRefDependenceGraph::Node *node) {
assert(node->op->isa<AffineForOp>());
- // Get perfectly nested sequence of loops starting at root of loop nest
- // (the first op being another AffineFor, and the second op - a terminator).
- // TODO(andydavis,bondhugula) Share this with similar code in loop tiling.
SmallVector<AffineForOp, 4> loops;
AffineForOp curr = node->op->cast<AffineForOp>();
- loops.push_back(curr);
- auto *currBody = curr.getBody();
- while (currBody->begin() == std::prev(currBody->end(), 2) &&
- (curr = curr.getBody()->front().dyn_cast<AffineForOp>())) {
- loops.push_back(curr);
- currBody = curr.getBody();
- }
+ getPerfectlyNestedLoops(loops, curr);
if (loops.size() < 2)
return;
// (inclusive).
auto getMaximalPerfectLoopNest = [&](AffineForOp root) {
SmallVector<AffineForOp, 6> band;
- AffineForOp currInst = root;
- do {
- band.push_back(currInst);
- } while (currInst.getBody()->getOperations().size() == 2 &&
- (currInst = currInst.getBody()->front().dyn_cast<AffineForOp>()));
+ getPerfectlyNestedLoops(band, root);
bands->push_back(band);
};
return success();
}
+/// Get perfectly nested sequence of loops starting at root of loop nest
+/// (the first op being another AffineFor, and the second op - a terminator).
+/// A loop is perfectly nested iff: the first op in the loop's body is another
+/// AffineForOp, and the second op is a terminator).
+void mlir::getPerfectlyNestedLoops(SmallVectorImpl<AffineForOp> &nestedLoops,
+ AffineForOp root) {
+ AffineForOp curr = root;
+ nestedLoops.push_back(curr);
+ auto *currBody = curr.getBody();
+ while (currBody->begin() == std::prev(currBody->end(), 2) &&
+ (curr = curr.getBody()->front().dyn_cast<AffineForOp>())) {
+ nestedLoops.push_back(curr);
+ currBody = curr.getBody();
+ }
+}
+
/// Unrolls this loop completely.
LogicalResult mlir::loopUnrollFull(AffineForOp forOp) {
Optional<uint64_t> mayBeConstantTripCount = getConstantTripCount(forOp);