CIRCT  19.0.0git
LayerMerge.cpp
Go to the documentation of this file.
1 //===- LayerMerge.cpp - Merge layer blocks together -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass merges layer blocks in a module which reference the same layer
10 // definition.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "PassDetails.h"
15 #include "mlir/IR/PatternMatch.h"
16 #include "llvm/Support/Debug.h"
17 
18 #define DEBUG_TYPE "firrtl-layer-merge"
19 
20 using namespace circt;
21 using namespace firrtl;
22 
23 namespace {
24 /// A pass that merges layer blocks referencing the same layer definition.
25 struct LayerMerge : public LayerMergeBase<LayerMerge> {
26  void runOnOperation() override;
27 };
28 } // namespace
29 
30 void LayerMerge::runOnOperation() {
31  LLVM_DEBUG(
32  llvm::dbgs() << "==----- Running LayerMerge "
33  "--------------------------------------------------===\n"
34  << "Module: '" << getOperation().getName() << "'\n";);
35 
36  // Track the last layer block that we saw which referenced a specific layer
37  // definition. Because this pass operates as a single walk of the IR, it is
38  // only ever possible that there is one prior layer block that references a
39  // given layer definition.
40  llvm::DenseMap<SymbolRefAttr, LayerBlockOp> priorLayerBlocks;
41 
42  // Recursively walk LayerBlockOps in the module. Whenever we see a layer
43  // block, check to see if there is a prior layer block that references the
44  // same declaration. If not, this layer block becomes the prior layer block
45  // and we continue. If there is a prior layer block, then splice the prior
46  // layer block's body into the beginning of this layer block and erase the
47  // prior layer block. This layer block then becomes the new prior layer
48  // block.
49  //
50  // The recursive walk will cause nested layer blocks to also be merged.
51  auto moduleOp = getOperation();
52  mlir::IRRewriter rewriter(moduleOp.getContext());
53  moduleOp.walk([&](LayerBlockOp layerBlock) {
54  auto layerName = layerBlock.getLayerName();
55  // If we haven't seen this layer before, then just insert it into
56  // priorLayerBlocks.
57  auto priorLayerBlockIt = priorLayerBlocks.find(layerName);
58  if (priorLayerBlockIt == priorLayerBlocks.end()) {
59  priorLayerBlocks[layerName] = layerBlock;
60  return WalkResult::advance();
61  }
62 
63  auto &priorLayerBlock = priorLayerBlockIt->getSecond();
64  rewriter.inlineBlockBefore(priorLayerBlock.getBody(), layerBlock.getBody(),
65  layerBlock.getBody()->begin());
66  priorLayerBlock->erase();
67  priorLayerBlocks[layerName] = layerBlock;
68  numMerged++;
69  return WalkResult::advance();
70  });
71 }
72 
73 std::unique_ptr<mlir::Pass> circt::firrtl::createLayerMergePass() {
74  return std::make_unique<LayerMerge>();
75 }
std::unique_ptr< mlir::Pass > createLayerMergePass()
Definition: LayerMerge.cpp:73
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21