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