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