CIRCT  20.0.0git
FunctionEliminationPass.cpp
Go to the documentation of this file.
1 //===- FunctionEliminationPass.cpp - Implement Function Elimination Pass --===//
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 // Implement pass to check that all functions got inlined and delete them.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "circt/Dialect/HW/HWOps.h"
16 #include "mlir/Dialect/Func/IR/FuncOps.h"
17 #include "mlir/IR/SymbolTable.h"
18 #include "mlir/IR/Visitors.h"
19 #include "mlir/Interfaces/CallInterfaces.h"
20 #include "mlir/Pass/Pass.h"
21 #include "mlir/Transforms/InliningUtils.h"
22 #include "llvm/Support/LogicalResult.h"
23 
24 namespace circt {
25 namespace llhd {
26 #define GEN_PASS_DEF_FUNCTIONELIMINATION
27 #include "circt/Dialect/LLHD/Transforms/Passes.h.inc"
28 } // namespace llhd
29 } // namespace circt
30 
31 using namespace mlir;
32 using namespace circt;
33 
34 namespace {
35 
36 struct FunctionInliner : public InlinerInterface {
37  FunctionInliner(MLIRContext *context) : InlinerInterface(context) {}
38 
39  bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
40  IRMapping &valueMapping) const override {
41  return dest->getParentOfType<llhd::ProcessOp>() &&
42  isa<func::FuncOp>(src->getParentOp());
43  }
44  bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned,
45  IRMapping &valueMapping) const override {
46  return true;
47  }
48 };
49 
50 struct FunctionEliminationPass
51  : public circt::llhd::impl::FunctionEliminationBase<
52  FunctionEliminationPass> {
53  void runOnOperation() override;
54  LogicalResult runOnModule(hw::HWModuleOp module);
55 };
56 
57 void FunctionEliminationPass::runOnOperation() {
58  for (auto module : getOperation().getOps<hw::HWModuleOp>())
59  if (failed(runOnModule(module)))
60  return signalPassFailure();
61 
62  getOperation().walk([&](mlir::func::FuncOp op) {
63  if (op.symbolKnownUseEmpty(getOperation()))
64  op.erase();
65  });
66 }
67 
68 LogicalResult FunctionEliminationPass::runOnModule(hw::HWModuleOp module) {
69  FunctionInliner inliner(&getContext());
70  SymbolTableCollection table;
71 
72  SmallVector<CallOpInterface> calls;
73  module.walk([&](func::CallOp op) { calls.push_back(op); });
74 
75  for (auto call : calls) {
76  auto symbol = call.getCallableForCallee().dyn_cast<SymbolRefAttr>();
77  if (!symbol)
78  return call.emitError(
79  "functions not referred to by symbol are not supported");
80 
81  auto func = cast<CallableOpInterface>(
82  table.lookupNearestSymbolFrom(module, symbol.getLeafReference()));
83 
84  if (succeeded(
85  mlir::inlineCall(inliner, call, func, func.getCallableRegion()))) {
86  call->erase();
87  continue;
88  }
89 
90  return call.emitError(
91  "Not all functions are inlined, there is at least "
92  "one function call left within a llhd.process or hw.module.");
93  }
94 
95  return success();
96 }
97 } // namespace
98 
99 std::unique_ptr<OperationPass<ModuleOp>>
101  return std::make_unique<FunctionEliminationPass>();
102 }
std::unique_ptr< OperationPass< ModuleOp > > createFunctionEliminationPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21