CIRCT  20.0.0git
LowerMatches.cpp
Go to the documentation of this file.
1 //===- LowerMatches.cpp - Lower match statements to whens -------*- C++ -*-===//
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 file defines the LowerMatchesPass, which lowers match statements to when
10 // statements
11 //
12 //===----------------------------------------------------------------------===//
13 
17 #include "mlir/IR/ImplicitLocOpBuilder.h"
18 #include "mlir/Pass/Pass.h"
19 
20 namespace circt {
21 namespace firrtl {
22 #define GEN_PASS_DEF_LOWERMATCHES
23 #include "circt/Dialect/FIRRTL/Passes.h.inc"
24 } // namespace firrtl
25 } // namespace circt
26 
27 using namespace circt;
28 using namespace firrtl;
29 
30 namespace {
31 class LowerMatchesPass
32  : public circt::firrtl::impl::LowerMatchesBase<LowerMatchesPass> {
33  void runOnOperation() override;
34 };
35 } // end anonymous namespace
36 
37 static void lowerMatch(MatchOp match) {
38 
39  // If this is an empty enumeration statement, just delete the match.
40  auto numCases = match->getNumRegions();
41  if (!numCases) {
42  match->erase();
43  return;
44  }
45 
46  ImplicitLocOpBuilder b(match.getLoc(), match);
47  auto input = match.getInput();
48  for (size_t i = 0; i < numCases - 1; ++i) {
49  // Create a WhenOp which tests the enum's tag.
50  auto condition = b.create<IsTagOp>(input, match.getFieldIndexAttr(i));
51  auto when = b.create<WhenOp>(condition, /*withElse=*/true);
52 
53  // Move the case block to the WhenOp.
54  auto *thenBlock = &when.getThenBlock();
55  auto *caseBlock = &match.getRegion(i).front();
56  caseBlock->moveBefore(thenBlock);
57  thenBlock->erase();
58 
59  // Replace the block argument with a subtag op.
60  b.setInsertionPointToStart(caseBlock);
61  auto data = b.create<SubtagOp>(input, match.getFieldIndexAttr(i));
62  caseBlock->getArgument(0).replaceAllUsesWith(data);
63  caseBlock->eraseArgument(0);
64 
65  // Change insertion to the else block.
66  b.setInsertionPointToStart(&when.getElseBlock());
67  }
68 
69  // At this point, the insertion point is either in the final else-block, or
70  // if there was only 1 variant, right before the match operation.
71 
72  // Replace the block argument with a subtag op.
73  auto data = b.create<SubtagOp>(input, match.getFieldIndexAttr(numCases - 1));
74 
75  // Get the final block from the match statement, and splice it into the
76  // current insertion point.
77  auto *caseBlock = &match->getRegions().back().front();
78  caseBlock->getArgument(0).replaceAllUsesWith(data);
79  auto *defaultBlock = b.getInsertionBlock();
80  defaultBlock->getOperations().splice(b.getInsertionPoint(),
81  caseBlock->getOperations());
82  match->erase();
83 }
84 
85 void LowerMatchesPass::runOnOperation() {
86  bool changed = false;
87  getOperation()->walk([&changed](MatchOp op) {
88  changed = true;
89  lowerMatch(op);
90  });
91  if (!changed)
92  return markAllAnalysesPreserved();
93  markAnalysesPreserved<InstanceGraph>();
94 }
95 
96 std::unique_ptr<mlir::Pass> circt::firrtl::createLowerMatchesPass() {
97  return std::make_unique<LowerMatchesPass>();
98 }
static void lowerMatch(MatchOp match)
std::unique_ptr< mlir::Pass > createLowerMatchesPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21