CIRCT 20.0.0git
Loading...
Searching...
No Matches
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
19namespace circt {
20namespace firrtl {
21#define GEN_PASS_DEF_LOWERMATCHES
22#include "circt/Dialect/FIRRTL/Passes.h.inc"
23} // namespace firrtl
24} // namespace circt
25
26using namespace circt;
27using namespace firrtl;
28
29namespace {
30class LowerMatchesPass
31 : public circt::firrtl::impl::LowerMatchesBase<LowerMatchesPass> {
32 void runOnOperation() override;
33};
34} // end anonymous namespace
35
36static 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
84void 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
95std::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.