[PATCH] D79134: [mlir] Add support for merging identical blocks during canonicalization

Mehdi AMINI via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon May 4 12:22:38 PDT 2020


mehdi_amini accepted this revision.
mehdi_amini added a comment.
This revision is now accepted and ready to land.

The whole handling of `mismatchedOperands` caused me some mental effort to follow, I think it'd be nice to have a high-level description of this parts (which is more than "identical block" strictly speaking).



================
Comment at: mlir/include/mlir/IR/Operation.h:560
+  bool isUsedOutsideOfBlock(Block *block) {
+    return llvm::all_of(getOpResults(), [block](OpResult result) {
+      return result.isUsedOutsideOfBlock(block);
----------------
I'm surprised this isn't an "any_of" here, it can be surprising with the name of the method, and the difference with the same method on the Value class.


================
Comment at: mlir/include/mlir/IR/OperationSupport.h:856
+  static bool isEquivalentTo(Operation *lhs, Operation *rhs,
+                             unsigned flags = 0);
 };
----------------
What about LLVM_MARK_AS_BITMASK_ENUM and use the Enum instead of unsigned?


================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:379
+/// This class contains the information for comparing the equivalencies of two
+/// blocks.
+struct BlockEquivalenceData {
----------------
can you add a description of what is considered "equivalent"?


================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:392
+  /// A map of result producing operations to their relative orders within this
+  /// block.
+  DenseMap<Operation *, unsigned> opOrderIndex;
----------------
Can you expand here?
In particular the order here is counting the results of an operation: an operation order in a block is the number of defined value in the block before this operation (including the block arguments)


================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:481
+    for (int operand : llvm::seq<int>(0, lhsIt->getNumOperands())) {
+      auto lhsOperand = lhsOperands[operand], rhsOperand = rhsOperands[operand];
+      if (lhsOperand == rhsOperand)
----------------
`auto`->`Value`?


================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:485
+
+      // Let the operands differ if they are defined in a different block. These
+      // will become new arguments if the blocks get merged.
----------------
The comment seems misleading to me (or misplaced, I would write this before the line `if (!lhsIsInBlock) {`




================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:508
+  if (lhsIt != lhsE || rhsIt != rhsE)
+    return failure();
+
----------------
Could check this ahead using the block ordering of the terminator?


================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:519
+/// their operands updated.
+static bool unableToUpdatePredOperands(Block *block) {
+  for (auto it = block->pred_begin(), e = block->pred_end(); it != e; ++it) {
----------------
Nit: in general predicate a more readable when they are written with positive logic instead of negative ("able" instead of "unable")


================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:539
+    // TODO: We could try and sub-partition this cluster if only some blocks
+    // cause the mismatch.
+    if (unableToUpdatePredOperands(leaderBlock) ||
----------------
You could get this by checking this property in `addToCluster` and return a failure when there are operandsToMerge so that you don't cluster blocks in the first place


================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:578
+    }
+    // Update the predecessors for each of the blocks.
+    auto updatePredecessors = [&](Block *block, unsigned it) {
----------------
I didn't quite get what this meant until I read the code, what about something around the line of: `// Update each block's predecessors terminator with the new arguments` 


================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:579
+    // Update the predecessors for each of the blocks.
+    auto updatePredecessors = [&](Block *block, unsigned it) {
+      for (auto i = block->pred_begin(), e = block->pred_end(); i != e; ++i) {
----------------
Do you have some name more explicit than `it`?


================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:580
+    auto updatePredecessors = [&](Block *block, unsigned it) {
+      for (auto i = block->pred_begin(), e = block->pred_end(); i != e; ++i) {
+        auto branch = cast<BranchOpInterface>((*i)->getTerminator());
----------------
Can you use something else than `i` for the iterator? I'm already not thrilled by `i` for integer index, but here it seems misleading as it is an iterator that it derefenced.


================
Comment at: mlir/lib/Transforms/Utils/RegionUtils.cpp:623
+      // Don't allow merging if this block has any regions.
+      // TODO: Ådd support for regions if necessary.
+      bool hasNonEmptyRegion = llvm::any_of(*block, [](Operation &op) {
----------------
Å->A


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79134/new/

https://reviews.llvm.org/D79134





More information about the llvm-commits mailing list