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.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
Definition: DebugAnalysis.h:21
mlir::raw_indented_ostream & dbgs()
Definition: Utility.h:28