Skip to content

Commit b8b9838

Browse files
committed
[mlir] Move InlinerInterface from Transforms to Interfaces.
1 parent 1d900e2 commit b8b9838

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+409
-320
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
//===- InlinerInterface.h - Inliner interface -------------------*- 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_INTERFACES_INLINERINTERFACE_H
14+
#define MLIR_INTERFACES_INLINERINTERFACE_H
15+
16+
#include "mlir/IR/BuiltinAttributes.h"
17+
#include "mlir/IR/DialectInterface.h"
18+
#include "mlir/IR/Location.h"
19+
#include "mlir/IR/Region.h"
20+
#include "mlir/IR/ValueRange.h"
21+
22+
namespace mlir {
23+
24+
class IRMapping;
25+
class OpBuilder;
26+
27+
//===----------------------------------------------------------------------===//
28+
// InlinerInterface
29+
//===----------------------------------------------------------------------===//
30+
31+
/// This is the interface that must be implemented by the dialects of operations
32+
/// to be inlined. This interface should only handle the operations of the
33+
/// given dialect.
34+
class DialectInlinerInterface
35+
: public DialectInterface::Base<DialectInlinerInterface> {
36+
public:
37+
DialectInlinerInterface(Dialect *dialect) : Base(dialect) {}
38+
39+
//===--------------------------------------------------------------------===//
40+
// Analysis Hooks
41+
//===--------------------------------------------------------------------===//
42+
43+
/// Returns true if the given operation 'callable', that implements the
44+
/// 'CallableOpInterface', can be inlined into the position given call
45+
/// operation 'call', that is registered to the current dialect and implements
46+
/// the `CallOpInterface`. 'wouldBeCloned' is set to true if the region of the
47+
/// given 'callable' is set to be cloned during the inlining process, or false
48+
/// if the region is set to be moved in-place(i.e. no duplicates would be
49+
/// created).
50+
virtual bool isLegalToInline(Operation *call, Operation *callable,
51+
bool wouldBeCloned) const {
52+
return false;
53+
}
54+
55+
/// Returns true if the given region 'src' can be inlined into the region
56+
/// 'dest' that is attached to an operation registered to the current dialect.
57+
/// 'wouldBeCloned' is set to true if the given 'src' region is set to be
58+
/// cloned during the inlining process, or false if the region is set to be
59+
/// moved in-place(i.e. no duplicates would be created). 'valueMapping'
60+
/// contains any remapped values from within the 'src' region. This can be
61+
/// used to examine what values will replace entry arguments into the 'src'
62+
/// region for example.
63+
virtual bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
64+
IRMapping &valueMapping) const {
65+
return false;
66+
}
67+
68+
/// Returns true if the given operation 'op', that is registered to this
69+
/// dialect, can be inlined into the given region, false otherwise.
70+
/// 'wouldBeCloned' is set to true if the given 'op' is set to be cloned
71+
/// during the inlining process, or false if the operation is set to be moved
72+
/// in-place(i.e. no duplicates would be created). 'valueMapping' contains any
73+
/// remapped values from within the 'src' region. This can be used to examine
74+
/// what values may potentially replace the operands to 'op'.
75+
virtual bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned,
76+
IRMapping &valueMapping) const {
77+
return false;
78+
}
79+
80+
/// This hook is invoked on an operation that contains regions. It should
81+
/// return true if the analyzer should recurse within the regions of this
82+
/// operation when computing legality and cost, false otherwise. The default
83+
/// implementation returns true.
84+
virtual bool shouldAnalyzeRecursively(Operation *op) const { return true; }
85+
86+
//===--------------------------------------------------------------------===//
87+
// Transformation Hooks
88+
//===--------------------------------------------------------------------===//
89+
90+
/// Handle the given inlined terminator by replacing it with a new operation
91+
/// as necessary. This overload is called when the inlined region has more
92+
/// than one block. The 'newDest' block represents the new final branching
93+
/// destination of blocks within this region, i.e. operations that release
94+
/// control to the parent operation will likely now branch to this block.
95+
/// Its block arguments correspond to any values that need to be replaced by
96+
/// terminators within the inlined region.
97+
virtual void handleTerminator(Operation *op, Block *newDest) const {
98+
llvm_unreachable("must implement handleTerminator in the case of multiple "
99+
"inlined blocks");
100+
}
101+
102+
/// Handle the given inlined terminator by replacing it with a new operation
103+
/// as necessary. This overload is called when the inlined region only
104+
/// contains one block. 'valuesToReplace' contains the previously returned
105+
/// values of the call site before inlining. These values must be replaced by
106+
/// this callback if they had any users (for example for traditional function
107+
/// calls, these are directly replaced with the operands of the `return`
108+
/// operation). The given 'op' will be removed by the caller, after this
109+
/// function has been called.
110+
virtual void handleTerminator(Operation *op,
111+
ValueRange valuesToReplace) const {
112+
llvm_unreachable(
113+
"must implement handleTerminator in the case of one inlined block");
114+
}
115+
116+
/// Attempt to materialize a conversion for a type mismatch between a call
117+
/// from this dialect, and a callable region. This method should generate an
118+
/// operation that takes 'input' as the only operand, and produces a single
119+
/// result of 'resultType'. If a conversion can not be generated, nullptr
120+
/// should be returned. For example, this hook may be invoked in the following
121+
/// scenarios:
122+
/// func @foo(i32) -> i32 { ... }
123+
///
124+
/// // Mismatched input operand
125+
/// ... = foo.call @foo(%input : i16) -> i32
126+
///
127+
/// // Mismatched result type.
128+
/// ... = foo.call @foo(%input : i32) -> i16
129+
///
130+
/// NOTE: This hook may be invoked before the 'isLegal' checks above.
131+
virtual Operation *materializeCallConversion(OpBuilder &builder, Value input,
132+
Type resultType,
133+
Location conversionLoc) const {
134+
return nullptr;
135+
}
136+
137+
/// Hook to transform the call arguments before using them to replace the
138+
/// callee arguments. Returns a value of the same type or the `argument`
139+
/// itself if nothing changed. The `argumentAttrs` dictionary is non-null even
140+
/// if no attribute is present. The hook is called after converting the
141+
/// callsite argument types using the materializeCallConversion callback, and
142+
/// right before inlining the callee region. Any operations created using the
143+
/// provided `builder` are inserted right before the inlined callee region. An
144+
/// example use case is the insertion of copies for by value arguments.
145+
virtual Value handleArgument(OpBuilder &builder, Operation *call,
146+
Operation *callable, Value argument,
147+
DictionaryAttr argumentAttrs) const {
148+
return argument;
149+
}
150+
151+
/// Hook to transform the callee results before using them to replace the call
152+
/// results. Returns a value of the same type or the `result` itself if
153+
/// nothing changed. The `resultAttrs` dictionary is non-null even if no
154+
/// attribute is present. The hook is called right before handling
155+
/// terminators, and obtains the callee result before converting its type
156+
/// using the `materializeCallConversion` callback. Any operations created
157+
/// using the provided `builder` are inserted right after the inlined callee
158+
/// region. An example use case is the insertion of copies for by value
159+
/// results. NOTE: This hook is invoked after inlining the `callable` region.
160+
virtual Value handleResult(OpBuilder &builder, Operation *call,
161+
Operation *callable, Value result,
162+
DictionaryAttr resultAttrs) const {
163+
return result;
164+
}
165+
166+
/// Process a set of blocks that have been inlined for a call. This callback
167+
/// is invoked before inlined terminator operations have been processed.
168+
virtual void processInlinedCallBlocks(
169+
Operation *call, iterator_range<Region::iterator> inlinedBlocks) const {}
170+
};
171+
172+
/// This interface provides the hooks into the inlining interface.
173+
/// Note: this class automatically collects 'DialectInlinerInterface' objects
174+
/// registered to each dialect within the given context.
175+
class InlinerInterface
176+
: public DialectInterfaceCollection<DialectInlinerInterface> {
177+
public:
178+
using Base::Base;
179+
180+
/// Process a set of blocks that have been inlined. This callback is invoked
181+
/// *before* inlined terminator operations have been processed.
182+
virtual void
183+
processInlinedBlocks(iterator_range<Region::iterator> inlinedBlocks) {}
184+
185+
/// These hooks mirror the hooks for the DialectInlinerInterface, with default
186+
/// implementations that call the hook on the handler for the dialect 'op' is
187+
/// registered to.
188+
189+
//===--------------------------------------------------------------------===//
190+
// Analysis Hooks
191+
//===--------------------------------------------------------------------===//
192+
193+
virtual bool isLegalToInline(Operation *call, Operation *callable,
194+
bool wouldBeCloned) const;
195+
virtual bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
196+
IRMapping &valueMapping) const;
197+
virtual bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned,
198+
IRMapping &valueMapping) const;
199+
virtual bool shouldAnalyzeRecursively(Operation *op) const;
200+
201+
//===--------------------------------------------------------------------===//
202+
// Transformation Hooks
203+
//===--------------------------------------------------------------------===//
204+
205+
virtual void handleTerminator(Operation *op, Block *newDest) const;
206+
virtual void handleTerminator(Operation *op, ValueRange valuesToRepl) const;
207+
208+
virtual Value handleArgument(OpBuilder &builder, Operation *call,
209+
Operation *callable, Value argument,
210+
DictionaryAttr argumentAttrs) const;
211+
virtual Value handleResult(OpBuilder &builder, Operation *call,
212+
Operation *callable, Value result,
213+
DictionaryAttr resultAttrs) const;
214+
215+
virtual void processInlinedCallBlocks(
216+
Operation *call, iterator_range<Region::iterator> inlinedBlocks) const;
217+
};
218+
219+
} // namespace mlir
220+
221+
#endif // MLIR_INTERFACES_INLINERINTERFACE_H

0 commit comments

Comments
 (0)