[PATCH] D74544: [MLIR] Add naive fusion of parallel loops.
Stephan Herhut via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 14 04:17:30 PST 2020
herhut requested changes to this revision.
herhut added a comment.
This revision now requires changes to proceed.
Cool, great start!
================
Comment at: mlir/include/mlir/Dialect/LoopOps/Passes.h:1
+#ifndef MLIR_DIALECT_LOOPOPS_PASSES_H_
+#define MLIR_DIALECT_LOOPOPS_PASSES_H_
----------------
This is lacking the LLVM header comment.
================
Comment at: mlir/lib/Dialect/LoopOps/Transforms/ParallelLoopFusion.cpp:39
+ const OperandRange &rhs) -> bool {
+ // TODO(pifon): Extend this to support aliases and equal constants.
+ return std::equal(lhs.begin(), lhs.end(), rhs.begin());
----------------
Avoid named TODO in llvm code base. I am an offender, as well, but I was told to avoid this in the future.
================
Comment at: mlir/lib/Dialect/LoopOps/Transforms/ParallelLoopFusion.cpp:48
+/// Analyzes dependencies in the most primitive way by checking that ploop1
+/// writes to the same buffer elements that ploop2 reads.
+static LogicalResult verifyDependencies(ParallelOp ploop1, ParallelOp ploop2,
----------------
You also need that `ploop2` does not write to buffers that `ploop1` reads. Both loops are fully independent if WRITES(ploop1) U READS(ploop2) is empty and READS(ploop1) U WRITES(ploop2) is empty. As we have sequential execution order within one iteration, we can ignore reads and writes between the two loops that are on the same index in the context of fusion.
================
Comment at: mlir/lib/Dialect/LoopOps/Transforms/ParallelLoopFusion.cpp:49
+/// writes to the same buffer elements that ploop2 reads.
+static LogicalResult verifyDependencies(ParallelOp ploop1, ParallelOp ploop2,
+ const BlockAndValueMapping &map) {
----------------
Can you add a comment what the `map` contains? This is a map from `ploop1` indices to `ploop2` indices I assume?
================
Comment at: mlir/lib/Dialect/LoopOps/Transforms/ParallelLoopFusion.cpp:65
+ // Check that the load indices of ploop2 coincide with store indices of
+ // ploop1 for the same memrefs.
+ auto storeIndices = write->second.front();
----------------
This is sufficient for memrefs that are defined outside of the loops. However, memrefs that are created within the loop, e.g. by a subview, will not be handled by this. As a starter, it would be ok to bail out in these cases.
================
Comment at: mlir/lib/Dialect/LoopOps/Transforms/ParallelLoopFusion.cpp:70
+ return WalkResult::interrupt();
+ for (int i = 0, e = storeIndices.size(); i < e; ++i) {
+ if (map.lookupOrDefault(storeIndices[i]) != loadIndices[i])
----------------
Does something like `llvm::all_of(llvm::zip(storeIndices, loadIndices), std::equal)` work? Just curious, no need to go there.
================
Comment at: mlir/lib/Dialect/LoopOps/Transforms/ParallelLoopFusion.cpp:110
+ // Iteratively fuse adjacent loops.
+ for (int i = 0, e = ploops.size(); i + 1 < e; ++i)
+ fuseIfLegal(ploops[i], ploops[i + 1], b);
----------------
What happens if there is a read or write inbetween the ploops? As a start, you could consider immediately adjacent loops or loops where we have no sideffecting ops inbetween.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D74544/new/
https://reviews.llvm.org/D74544
More information about the llvm-commits
mailing list