MLIR  17.0.0git
InliningUtils.h
Go to the documentation of this file.
1 //===- InliningUtils.h - Inliner utilities ----------------------*- 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 header file defines interfaces for various inlining utility methods.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_TRANSFORMS_INLININGUTILS_H
14 #define MLIR_TRANSFORMS_INLININGUTILS_H
15 
17 #include "mlir/IR/Location.h"
18 #include "mlir/IR/Region.h"
19 #include <optional>
20 
21 namespace mlir {
22 
23 class Block;
24 class IRMapping;
25 class CallableOpInterface;
26 class CallOpInterface;
27 class OpBuilder;
28 class Operation;
29 class Region;
30 class TypeRange;
31 class Value;
32 class ValueRange;
33 
34 //===----------------------------------------------------------------------===//
35 // InlinerInterface
36 //===----------------------------------------------------------------------===//
37 
38 /// This is the interface that must be implemented by the dialects of operations
39 /// to be inlined. This interface should only handle the operations of the
40 /// given dialect.
42  : public DialectInterface::Base<DialectInlinerInterface> {
43 public:
44  DialectInlinerInterface(Dialect *dialect) : Base(dialect) {}
45 
46  //===--------------------------------------------------------------------===//
47  // Analysis Hooks
48  //===--------------------------------------------------------------------===//
49 
50  /// Returns true if the given operation 'callable', that implements the
51  /// 'CallableOpInterface', can be inlined into the position given call
52  /// operation 'call', that is registered to the current dialect and implements
53  /// the `CallOpInterface`. 'wouldBeCloned' is set to true if the region of the
54  /// given 'callable' is set to be cloned during the inlining process, or false
55  /// if the region is set to be moved in-place(i.e. no duplicates would be
56  /// created).
57  virtual bool isLegalToInline(Operation *call, Operation *callable,
58  bool wouldBeCloned) const {
59  return false;
60  }
61 
62  /// Returns true if the given region 'src' can be inlined into the region
63  /// 'dest' that is attached to an operation registered to the current dialect.
64  /// 'wouldBeCloned' is set to true if the given 'src' region is set to be
65  /// cloned during the inlining process, or false if the region is set to be
66  /// moved in-place(i.e. no duplicates would be created). 'valueMapping'
67  /// contains any remapped values from within the 'src' region. This can be
68  /// used to examine what values will replace entry arguments into the 'src'
69  /// region for example.
70  virtual bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
71  IRMapping &valueMapping) const {
72  return false;
73  }
74 
75  /// Returns true if the given operation 'op', that is registered to this
76  /// dialect, can be inlined into the given region, false otherwise.
77  /// 'wouldBeCloned' is set to true if the given 'op' is set to be cloned
78  /// during the inlining process, or false if the operation is set to be moved
79  /// in-place(i.e. no duplicates would be created). 'valueMapping' contains any
80  /// remapped values from within the 'src' region. This can be used to examine
81  /// what values may potentially replace the operands to 'op'.
82  virtual bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned,
83  IRMapping &valueMapping) const {
84  return false;
85  }
86 
87  /// This hook is invoked on an operation that contains regions. It should
88  /// return true if the analyzer should recurse within the regions of this
89  /// operation when computing legality and cost, false otherwise. The default
90  /// implementation returns true.
91  virtual bool shouldAnalyzeRecursively(Operation *op) const { return true; }
92 
93  //===--------------------------------------------------------------------===//
94  // Transformation Hooks
95  //===--------------------------------------------------------------------===//
96 
97  /// Handle the given inlined terminator by replacing it with a new operation
98  /// as necessary. This overload is called when the inlined region has more
99  /// than one block. The 'newDest' block represents the new final branching
100  /// destination of blocks within this region, i.e. operations that release
101  /// control to the parent operation will likely now branch to this block.
102  /// Its block arguments correspond to any values that need to be replaced by
103  /// terminators within the inlined region.
104  virtual void handleTerminator(Operation *op, Block *newDest) const {
105  llvm_unreachable("must implement handleTerminator in the case of multiple "
106  "inlined blocks");
107  }
108 
109  /// Handle the given inlined terminator by replacing it with a new operation
110  /// as necessary. This overload is called when the inlined region only
111  /// contains one block. 'valuesToReplace' contains the previously returned
112  /// values of the call site before inlining. These values must be replaced by
113  /// this callback if they had any users (for example for traditional function
114  /// calls, these are directly replaced with the operands of the `return`
115  /// operation). The given 'op' will be removed by the caller, after this
116  /// function has been called.
117  virtual void handleTerminator(Operation *op,
118  ArrayRef<Value> valuesToReplace) const {
119  llvm_unreachable(
120  "must implement handleTerminator in the case of one inlined block");
121  }
122 
123  /// Attempt to materialize a conversion for a type mismatch between a call
124  /// from this dialect, and a callable region. This method should generate an
125  /// operation that takes 'input' as the only operand, and produces a single
126  /// result of 'resultType'. If a conversion can not be generated, nullptr
127  /// should be returned. For example, this hook may be invoked in the following
128  /// scenarios:
129  /// func @foo(i32) -> i32 { ... }
130  ///
131  /// // Mismatched input operand
132  /// ... = foo.call @foo(%input : i16) -> i32
133  ///
134  /// // Mismatched result type.
135  /// ... = foo.call @foo(%input : i32) -> i16
136  ///
137  /// NOTE: This hook may be invoked before the 'isLegal' checks above.
139  Type resultType,
140  Location conversionLoc) const {
141  return nullptr;
142  }
143 
144  /// Process a set of blocks that have been inlined for a call. This callback
145  /// is invoked before inlined terminator operations have been processed.
147  Operation *call, iterator_range<Region::iterator> inlinedBlocks) const {}
148 };
149 
150 /// This interface provides the hooks into the inlining interface.
151 /// Note: this class automatically collects 'DialectInlinerInterface' objects
152 /// registered to each dialect within the given context.
154  : public DialectInterfaceCollection<DialectInlinerInterface> {
155 public:
156  using Base::Base;
157 
158  /// Process a set of blocks that have been inlined. This callback is invoked
159  /// *before* inlined terminator operations have been processed.
160  virtual void
162 
163  /// These hooks mirror the hooks for the DialectInlinerInterface, with default
164  /// implementations that call the hook on the handler for the dialect 'op' is
165  /// registered to.
166 
167  //===--------------------------------------------------------------------===//
168  // Analysis Hooks
169  //===--------------------------------------------------------------------===//
170 
171  virtual bool isLegalToInline(Operation *call, Operation *callable,
172  bool wouldBeCloned) const;
173  virtual bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
174  IRMapping &valueMapping) const;
175  virtual bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned,
176  IRMapping &valueMapping) const;
177  virtual bool shouldAnalyzeRecursively(Operation *op) const;
178 
179  //===--------------------------------------------------------------------===//
180  // Transformation Hooks
181  //===--------------------------------------------------------------------===//
182 
183  virtual void handleTerminator(Operation *op, Block *newDest) const;
184  virtual void handleTerminator(Operation *op,
185  ArrayRef<Value> valuesToRepl) const;
186  virtual void processInlinedCallBlocks(
187  Operation *call, iterator_range<Region::iterator> inlinedBlocks) const;
188 };
189 
190 //===----------------------------------------------------------------------===//
191 // Inline Methods.
192 //===----------------------------------------------------------------------===//
193 
194 /// This function inlines a region, 'src', into another. This function returns
195 /// failure if it is not possible to inline this function. If the function
196 /// returned failure, then no changes to the module have been made.
197 ///
198 /// The provided 'inlinePoint' must be within a region, and corresponds to the
199 /// location where the 'src' region should be inlined. 'mapping' contains any
200 /// remapped operands that are used within the region, and *must* include
201 /// remappings for the entry arguments to the region. 'resultsToReplace'
202 /// corresponds to any results that should be replaced by terminators within the
203 /// inlined region. 'regionResultTypes' specifies the expected return types of
204 /// the terminators in the region. 'inlineLoc' is an optional Location that, if
205 /// provided, will be used to update the inlined operations' location
206 /// information. 'shouldCloneInlinedRegion' corresponds to whether the source
207 /// region should be cloned into the 'inlinePoint' or spliced directly.
208 LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
209  Operation *inlinePoint, IRMapping &mapper,
210  ValueRange resultsToReplace,
211  TypeRange regionResultTypes,
212  std::optional<Location> inlineLoc = std::nullopt,
213  bool shouldCloneInlinedRegion = true);
214 LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
215  Block *inlineBlock, Block::iterator inlinePoint,
216  IRMapping &mapper, ValueRange resultsToReplace,
217  TypeRange regionResultTypes,
218  std::optional<Location> inlineLoc = std::nullopt,
219  bool shouldCloneInlinedRegion = true);
220 
221 /// This function is an overload of the above 'inlineRegion' that allows for
222 /// providing the set of operands ('inlinedOperands') that should be used
223 /// in-favor of the region arguments when inlining.
224 LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
225  Operation *inlinePoint, ValueRange inlinedOperands,
226  ValueRange resultsToReplace,
227  std::optional<Location> inlineLoc = std::nullopt,
228  bool shouldCloneInlinedRegion = true);
229 LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
230  Block *inlineBlock, Block::iterator inlinePoint,
231  ValueRange inlinedOperands,
232  ValueRange resultsToReplace,
233  std::optional<Location> inlineLoc = std::nullopt,
234  bool shouldCloneInlinedRegion = true);
235 
236 /// This function inlines a given region, 'src', of a callable operation,
237 /// 'callable', into the location defined by the given call operation. This
238 /// function returns failure if inlining is not possible, success otherwise. On
239 /// failure, no changes are made to the module. 'shouldCloneInlinedRegion'
240 /// corresponds to whether the source region should be cloned into the 'call' or
241 /// spliced directly.
242 LogicalResult inlineCall(InlinerInterface &interface, CallOpInterface call,
243  CallableOpInterface callable, Region *src,
244  bool shouldCloneInlinedRegion = true);
245 
246 } // namespace mlir
247 
248 #endif // MLIR_TRANSFORMS_INLININGUTILS_H
Block represents an ordered list of Operations.
Definition: Block.h:30
OpListType::iterator iterator
Definition: Block.h:129
This is the interface that must be implemented by the dialects of operations to be inlined.
Definition: InliningUtils.h:42
virtual bool isLegalToInline(Operation *call, Operation *callable, bool wouldBeCloned) const
Returns true if the given operation 'callable', that implements the 'CallableOpInterface',...
Definition: InliningUtils.h:57
virtual Operation * materializeCallConversion(OpBuilder &builder, Value input, Type resultType, Location conversionLoc) const
Attempt to materialize a conversion for a type mismatch between a call from this dialect,...
virtual bool shouldAnalyzeRecursively(Operation *op) const
This hook is invoked on an operation that contains regions.
Definition: InliningUtils.h:91
virtual bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned, IRMapping &valueMapping) const
Returns true if the given region 'src' can be inlined into the region 'dest' that is attached to an o...
Definition: InliningUtils.h:70
DialectInlinerInterface(Dialect *dialect)
Definition: InliningUtils.h:44
virtual void processInlinedCallBlocks(Operation *call, iterator_range< Region::iterator > inlinedBlocks) const
Process a set of blocks that have been inlined for a call.
virtual void handleTerminator(Operation *op, ArrayRef< Value > valuesToReplace) const
Handle the given inlined terminator by replacing it with a new operation as necessary.
virtual void handleTerminator(Operation *op, Block *newDest) const
Handle the given inlined terminator by replacing it with a new operation as necessary.
virtual bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned, IRMapping &valueMapping) const
Returns true if the given operation 'op', that is registered to this dialect, can be inlined into the...
Definition: InliningUtils.h:82
A collection of dialect interfaces within a context, for a given concrete interface type.
DialectInterfaceCollection< DialectInlinerInterface > Base
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:41
This is a utility class for mapping one set of IR entities to another.
Definition: IRMapping.h:26
This interface provides the hooks into the inlining interface.
virtual bool shouldAnalyzeRecursively(Operation *op) const
virtual void handleTerminator(Operation *op, Block *newDest) const
Handle the given inlined terminator by replacing it with a new operation as necessary.
virtual void processInlinedCallBlocks(Operation *call, iterator_range< Region::iterator > inlinedBlocks) const
virtual void processInlinedBlocks(iterator_range< Region::iterator > inlinedBlocks)
Process a set of blocks that have been inlined.
virtual bool isLegalToInline(Operation *call, Operation *callable, bool wouldBeCloned) const
These hooks mirror the hooks for the DialectInlinerInterface, with default implementations that call ...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
This class helps build Operations.
Definition: Builders.h:199
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:75
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:93
The base class used for all derived interface types.
Include the generated interface declarations.
LogicalResult inlineRegion(InlinerInterface &interface, Region *src, Operation *inlinePoint, IRMapping &mapper, ValueRange resultsToReplace, TypeRange regionResultTypes, std::optional< Location > inlineLoc=std::nullopt, bool shouldCloneInlinedRegion=true)
This function inlines a region, 'src', into another.
LogicalResult inlineCall(InlinerInterface &interface, CallOpInterface call, CallableOpInterface callable, Region *src, bool shouldCloneInlinedRegion=true)
This function inlines a given region, 'src', of a callable operation, 'callable', into the location d...