MLIR  20.0.0git
InlinerExtension.cpp
Go to the documentation of this file.
1 //===- InlinerExtension.cpp - Func Inliner Extension ----------------------===//
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 
14 
15 using namespace mlir;
16 using namespace mlir::func;
17 
18 //===----------------------------------------------------------------------===//
19 // FuncDialect Interfaces
20 //===----------------------------------------------------------------------===//
21 namespace {
22 /// This class defines the interface for handling inlining with func operations.
23 struct FuncInlinerInterface : public DialectInlinerInterface {
25 
26  //===--------------------------------------------------------------------===//
27  // Analysis Hooks
28  //===--------------------------------------------------------------------===//
29 
30  /// Call operations can be inlined unless specified otherwise by attributes
31  /// on either the call or the callbale.
32  bool isLegalToInline(Operation *call, Operation *callable,
33  bool wouldBeCloned) const final {
34  auto callOp = dyn_cast<func::CallOp>(call);
35  auto funcOp = dyn_cast<func::FuncOp>(callable);
36  return !(callOp && callOp.getNoInline()) &&
37  !(funcOp && funcOp.getNoInline());
38  }
39 
40  /// All operations can be inlined.
41  bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
42  return true;
43  }
44 
45  /// All function bodies can be inlined.
46  bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final {
47  return true;
48  }
49 
50  //===--------------------------------------------------------------------===//
51  // Transformation Hooks
52  //===--------------------------------------------------------------------===//
53 
54  /// Handle the given inlined terminator by replacing it with a new operation
55  /// as necessary.
56  void handleTerminator(Operation *op, Block *newDest) const final {
57  // Only return needs to be handled here.
58  auto returnOp = dyn_cast<ReturnOp>(op);
59  if (!returnOp)
60  return;
61 
62  // Replace the return with a branch to the dest.
63  OpBuilder builder(op);
64  builder.create<cf::BranchOp>(op->getLoc(), newDest, returnOp.getOperands());
65  op->erase();
66  }
67 
68  /// Handle the given inlined terminator by replacing it with a new operation
69  /// as necessary.
70  void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
71  // Only return needs to be handled here.
72  auto returnOp = cast<ReturnOp>(op);
73 
74  // Replace the values directly with the return operands.
75  assert(returnOp.getNumOperands() == valuesToRepl.size());
76  for (const auto &it : llvm::enumerate(returnOp.getOperands()))
77  valuesToRepl[it.index()].replaceAllUsesWith(it.value());
78  }
79 };
80 } // namespace
81 
82 //===----------------------------------------------------------------------===//
83 // Registration
84 //===----------------------------------------------------------------------===//
85 
87  registry.addExtension(+[](MLIRContext *ctx, func::FuncDialect *dialect) {
88  dialect->addInterfaces<FuncInlinerInterface>();
89 
90  // The inliner extension relies on the ControlFlow dialect.
91  ctx->getOrLoadDialect<cf::ControlFlowDialect>();
92  });
93 }
static bool isLegalToInline(InlinerInterface &interface, Region *src, Region *insertRegion, bool shouldCloneInlinedRegion, IRMapping &valueMapping)
Utility to check that all of the operations within 'src' can be inlined.
Block represents an ordered list of Operations.
Definition: Block.h:33
This is the interface that must be implemented by the dialects of operations to be inlined.
Definition: InliningUtils.h:44
DialectInlinerInterface(Dialect *dialect)
Definition: InliningUtils.h:46
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
This is a utility class for mapping one set of IR entities to another.
Definition: IRMapping.h:26
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
Definition: MLIRContext.h:97
This class helps build Operations.
Definition: Builders.h:216
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:381
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:344
void registerInlinerExtension(DialectRegistry &registry)
Register the extension used to support inlining the func dialect.
Include the generated interface declarations.