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 
16 #include "mlir/IR/PatternMatch.h"
17 #include "mlir/Pass/Pass.h"
18 #include "llvm/Support/Debug.h"
19 
20 #define DEBUG_TYPE "firrtl-layer-merge"
21 
22 namespace circt {
23 namespace firrtl {
24 #define GEN_PASS_DEF_LAYERMERGE
25 #include "circt/Dialect/FIRRTL/Passes.h.inc"
26 } // namespace firrtl
27 } // namespace circt
28 
29 using namespace circt;
30 using namespace firrtl;
31 
32 namespace {
33 /// A pass that merges layer blocks referencing the same layer definition.
34 struct LayerMerge : public circt::firrtl::impl::LayerMergeBase<LayerMerge> {
35  void runOnOperation() override;
36 };
37 } // namespace
38 
39 void LayerMerge::runOnOperation() {
40  LLVM_DEBUG(
41  llvm::dbgs() << "==----- Running LayerMerge "
42  "--------------------------------------------------===\n"
43  << "Module: '" << getOperation().getName() << "'\n";);
44 
45  // Track the last layer block that we saw which referenced a specific layer
46  // definition. Because this pass operates as a single walk of the IR, it is
47  // only ever possible that there is one prior layer block that references a
48  // given layer definition.
49  llvm::DenseMap<SymbolRefAttr, LayerBlockOp> priorLayerBlocks;
50 
51  // Recursively walk LayerBlockOps in the module. Whenever we see a layer
52  // block, check to see if there is a prior layer block that references the
53  // same declaration. If not, this layer block becomes the prior layer block
54  // and we continue. If there is a prior layer block, then splice the prior
55  // layer block's body into the beginning of this layer block and erase the
56  // prior layer block. This layer block then becomes the new prior layer
57  // block.
58  //
59  // The recursive walk will cause nested layer blocks to also be merged.
60  auto moduleOp = getOperation();
61  mlir::IRRewriter rewriter(moduleOp.getContext());
62  moduleOp.walk([&](LayerBlockOp layerBlock) {
63  auto layerName = layerBlock.getLayerName();
64  // If we haven't seen this layer before, then just insert it into
65  // priorLayerBlocks.
66  auto priorLayerBlockIt = priorLayerBlocks.find(layerName);
67  if (priorLayerBlockIt == priorLayerBlocks.end()) {
68  priorLayerBlocks[layerName] = layerBlock;
69  return WalkResult::advance();
70  }
71 
72  auto &priorLayerBlock = priorLayerBlockIt->getSecond();
73  rewriter.inlineBlockBefore(priorLayerBlock.getBody(), layerBlock.getBody(),
74  layerBlock.getBody()->begin());
75  priorLayerBlock->erase();
76  priorLayerBlocks[layerName] = layerBlock;
77  numMerged++;
78  return WalkResult::advance();
79  });
80 }
81 
82 std::unique_ptr<mlir::Pass> circt::firrtl::createLayerMergePass() {
83  return std::make_unique<LayerMerge>();
84 }
std::unique_ptr< mlir::Pass > createLayerMergePass()
Definition: LayerMerge.cpp:82
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