CIRCT  19.0.0git
RemoveGroups.cpp
Go to the documentation of this file.
1 //===- RemoveGroups.cpp - Remove Groups Pass --------------------*- 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 // Contains the definitions of the Remove Groups pass.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "PassDetails.h"
17 #include "circt/Support/LLVM.h"
18 #include "mlir/IR/BuiltinTypes.h"
19 #include "mlir/IR/OperationSupport.h"
20 
21 using namespace circt;
22 using namespace calyx;
23 using namespace mlir;
24 
25 /// Makes several modifications to the operations of a GroupOp:
26 /// 1. Assign the 'done' signal of the component with the done_op of the top
27 /// level control group.
28 /// 2. Append the 'go' signal of the component to guard of each assignment.
29 /// 3. Replace all uses of GroupGoOp with the respective guard, and delete the
30 /// GroupGoOp.
31 /// 4. Remove the GroupDoneOp.
32 static void modifyGroupOperations(ComponentOp component) {
33  auto control = component.getControlOp();
34  // Get the only EnableOp in the control.
35  auto topLevel = *control.getRegion().getOps<EnableOp>().begin();
36  auto topLevelName = topLevel.getGroupName();
37 
38  auto wires = component.getWiresOp();
39  Value componentGoPort = component.getGoPort();
40  wires.walk([&](GroupOp group) {
41  auto &groupRegion = group->getRegion(0);
42  OpBuilder builder(groupRegion);
43  // Walk the assignments and append component's 'go' signal to each guard.
44  updateGroupAssignmentGuards(builder, group, componentGoPort);
45 
46  auto groupDone = group.getDoneOp();
47  if (topLevelName == group.getSymName()) {
48  // Replace `calyx.group_done %0, %1 ? : i1`
49  // with `calyx.assign %done, %0, %1 ? : i1`
50  auto assignOp =
51  builder.create<AssignOp>(group->getLoc(), component.getDonePort(),
52  groupDone.getSrc(), groupDone.getGuard());
53  groupDone->replaceAllUsesWith(assignOp);
54  } else {
55  // Replace calyx.group_go's uses with its guard, e.g.
56  // %A.go = calyx.group_go %true, %3 ? : i1
57  // %0 = comb.and %1, %A.go : i1
58  // ->
59  // %0 = comb.and %1, %3 : i1
60  auto groupGo = group.getGoOp();
61  auto groupGoGuard = groupGo.getGuard();
62  groupGo.replaceAllUsesWith(groupGoGuard);
63  groupGo->erase();
64  }
65  // In either case, remove the group's done value.
66  groupDone->erase();
67  });
68 }
69 
70 /// Inlines each group in the WiresOp.
71 void inlineGroups(ComponentOp component) {
72  auto &wiresRegion = component.getWiresOp().getRegion();
73  auto &wireBlocks = wiresRegion.getBlocks();
74  auto lastBlock = wiresRegion.end();
75 
76  // Inline the body of each group as a Block into the WiresOp.
77  wiresRegion.walk([&](GroupOp group) {
78  wireBlocks.splice(lastBlock, group.getRegion().getBlocks());
79  group->erase();
80  });
81 
82  // Merge the operations of each Block into the first block of the WiresOp.
83  auto firstBlock = wireBlocks.begin();
84  for (auto it = firstBlock, e = lastBlock; it != e; ++it) {
85  if (it == firstBlock)
86  continue;
87  firstBlock->getOperations().splice(firstBlock->end(), it->getOperations());
88  }
89 
90  // Erase the (now) empty blocks.
91  while (&wiresRegion.front() != &wiresRegion.back())
92  wiresRegion.back().erase();
93 }
94 
95 namespace {
96 
97 struct RemoveGroupsPass : public RemoveGroupsBase<RemoveGroupsPass> {
98  void runOnOperation() override;
99 };
100 
101 } // end anonymous namespace
102 
103 void RemoveGroupsPass::runOnOperation() {
104  ComponentOp component = getOperation();
105 
106  // Early exit if there is no control to compile.
107  if (component.getControlOp().getOps().empty())
108  return;
109 
110  // Make the necessary modifications to each group's operations.
111  modifyGroupOperations(component);
112 
113  // Inline the body of each group.
114  inlineGroups(component);
115 
116  // Remove the last EnableOp from the control.
117  auto control = component.getControlOp();
118  control.walk([&](EnableOp enable) { enable->erase(); });
119 }
120 
121 std::unique_ptr<mlir::Pass> circt::calyx::createRemoveGroupsPass() {
122  return std::make_unique<RemoveGroupsPass>();
123 }
Builder builder
static void modifyGroupOperations(ComponentOp component)
Makes several modifications to the operations of a GroupOp:
void inlineGroups(ComponentOp component)
Inlines each group in the WiresOp.
static void updateGroupAssignmentGuards(OpBuilder &builder, GroupOp &group, Op &op)
Updates the guard of each assignment within a group with op.
Definition: CalyxHelpers.h:67
std::unique_ptr< mlir::Pass > createRemoveGroupsPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21