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