Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/include/mlir/Transforms/InliningUtils.h
Line
Count
Source (jump to first uncovered line)
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_INLINING_UTILS_H
14
#define MLIR_TRANSFORMS_INLINING_UTILS_H
15
16
#include "mlir/IR/DialectInterface.h"
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 FuncOp;
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.
41
class DialectInlinerInterface
42
    : public DialectInterface::Base<DialectInlinerInterface> {
43
public:
44
0
  DialectInlinerInterface(Dialect *dialect) : Base(dialect) {}
45
46
  //===--------------------------------------------------------------------===//
47
  // Analysis Hooks
48
  //===--------------------------------------------------------------------===//
49
50
  /// Returns true if the given region 'src' can be inlined into the region
51
  /// 'dest' that is attached to an operation registered to the current dialect.
52
  /// 'valueMapping' contains any remapped values from within the 'src' region.
53
  /// This can be used to examine what values will replace entry arguments into
54
  /// the 'src' region for example.
55
  virtual bool isLegalToInline(Region *dest, Region *src,
56
0
                               BlockAndValueMapping &valueMapping) const {
57
0
    return false;
58
0
  }
59
60
  /// Returns true if the given operation 'op', that is registered to this
61
  /// dialect, can be inlined into the given region, false otherwise.
62
  /// 'valueMapping' contains any remapped values from within the 'src' region.
63
  /// This can be used to examine what values may potentially replace the
64
  /// operands to 'op'.
65
  virtual bool isLegalToInline(Operation *op, Region *dest,
66
0
                               BlockAndValueMapping &valueMapping) const {
67
0
    return false;
68
0
  }
69
70
  /// This hook is invoked on an operation that contains regions. It should
71
  /// return true if the analyzer should recurse within the regions of this
72
  /// operation when computing legality and cost, false otherwise. The default
73
  /// implementation returns true.
74
0
  virtual bool shouldAnalyzeRecursively(Operation *op) const { return true; }
75
76
  //===--------------------------------------------------------------------===//
77
  // Transformation Hooks
78
  //===--------------------------------------------------------------------===//
79
80
  /// Handle the given inlined terminator by replacing it with a new operation
81
  /// as necessary. This overload is called when the inlined region has more
82
  /// than one block. The 'newDest' block represents the new final branching
83
  /// destination of blocks within this region, i.e. operations that release
84
  /// control to the parent operation will likely now branch to this block.
85
  /// Its block arguments correspond to any values that need to be replaced by
86
  /// terminators within the inlined region.
87
0
  virtual void handleTerminator(Operation *op, Block *newDest) const {
88
0
    llvm_unreachable("must implement handleTerminator in the case of multiple "
89
0
                     "inlined blocks");
90
0
  }
91
92
  /// Handle the given inlined terminator by replacing it with a new operation
93
  /// as necessary. This overload is called when the inlined region only
94
  /// contains one block. 'valuesToReplace' contains the previously returned
95
  /// values of the call site before inlining. These values must be replaced by
96
  /// this callback if they had any users (for example for traditional function
97
  /// calls, these are directly replaced with the operands of the `return`
98
  /// operation). The given 'op' will be removed by the caller, after this
99
  /// function has been called.
100
  virtual void handleTerminator(Operation *op,
101
0
                                ArrayRef<Value> valuesToReplace) const {
102
0
    llvm_unreachable(
103
0
        "must implement handleTerminator in the case of one inlined block");
104
0
  }
105
106
  /// Attempt to materialize a conversion for a type mismatch between a call
107
  /// from this dialect, and a callable region. This method should generate an
108
  /// operation that takes 'input' as the only operand, and produces a single
109
  /// result of 'resultType'. If a conversion can not be generated, nullptr
110
  /// should be returned. For example, this hook may be invoked in the following
111
  /// scenarios:
112
  ///   func @foo(i32) -> i32 { ... }
113
  ///
114
  ///   // Mismatched input operand
115
  ///   ... = foo.call @foo(%input : i16) -> i32
116
  ///
117
  ///   // Mismatched result type.
118
  ///   ... = foo.call @foo(%input : i32) -> i16
119
  ///
120
  /// NOTE: This hook may be invoked before the 'isLegal' checks above.
121
  virtual Operation *materializeCallConversion(OpBuilder &builder, Value input,
122
                                               Type resultType,
123
0
                                               Location conversionLoc) const {
124
0
    return nullptr;
125
0
  }
126
};
127
128
/// This interface provides the hooks into the inlining interface.
129
/// Note: this class automatically collects 'DialectInlinerInterface' objects
130
/// registered to each dialect within the given context.
131
class InlinerInterface
132
    : public DialectInterfaceCollection<DialectInlinerInterface> {
133
public:
134
  using Base::Base;
135
136
  /// Process a set of blocks that have been inlined. This callback is invoked
137
  /// *before* inlined terminator operations have been processed.
138
  virtual void
139
0
  processInlinedBlocks(iterator_range<Region::iterator> inlinedBlocks) {}
140
141
  /// These hooks mirror the hooks for the DialectInlinerInterface, with default
142
  /// implementations that call the hook on the handler for the dialect 'op' is
143
  /// registered to.
144
145
  //===--------------------------------------------------------------------===//
146
  // Analysis Hooks
147
  //===--------------------------------------------------------------------===//
148
149
  virtual bool isLegalToInline(Region *dest, Region *src,
150
                               BlockAndValueMapping &valueMapping) const;
151
  virtual bool isLegalToInline(Operation *op, Region *dest,
152
                               BlockAndValueMapping &valueMapping) const;
153
  virtual bool shouldAnalyzeRecursively(Operation *op) const;
154
155
  //===--------------------------------------------------------------------===//
156
  // Transformation Hooks
157
  //===--------------------------------------------------------------------===//
158
159
  virtual void handleTerminator(Operation *op, Block *newDest) const;
160
  virtual void handleTerminator(Operation *op,
161
                                ArrayRef<Value> valuesToRepl) const;
162
};
163
164
//===----------------------------------------------------------------------===//
165
// Inline Methods.
166
//===----------------------------------------------------------------------===//
167
168
/// This function inlines a region, 'src', into another. This function returns
169
/// failure if it is not possible to inline this function. If the function
170
/// returned failure, then no changes to the module have been made.
171
///
172
/// The provided 'inlinePoint' must be within a region, and corresponds to the
173
/// location where the 'src' region should be inlined. 'mapping' contains any
174
/// remapped operands that are used within the region, and *must* include
175
/// remappings for the entry arguments to the region. 'resultsToReplace'
176
/// corresponds to any results that should be replaced by terminators within the
177
/// inlined region. 'regionResultTypes' specifies the expected return types of
178
/// the terminators in the region. 'inlineLoc' is an optional Location that, if
179
/// provided, will be used to update the inlined operations' location
180
/// information. 'shouldCloneInlinedRegion' corresponds to whether the source
181
/// region should be cloned into the 'inlinePoint' or spliced directly.
182
LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
183
                           Operation *inlinePoint, BlockAndValueMapping &mapper,
184
                           ValueRange resultsToReplace,
185
                           TypeRange regionResultTypes,
186
                           Optional<Location> inlineLoc = llvm::None,
187
                           bool shouldCloneInlinedRegion = true);
188
189
/// This function is an overload of the above 'inlineRegion' that allows for
190
/// providing the set of operands ('inlinedOperands') that should be used
191
/// in-favor of the region arguments when inlining.
192
LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
193
                           Operation *inlinePoint,
194
                           ValueRange inlinedOperands,
195
                           ValueRange resultsToReplace,
196
                           Optional<Location> inlineLoc = llvm::None,
197
                           bool shouldCloneInlinedRegion = true);
198
199
/// This function inlines a given region, 'src', of a callable operation,
200
/// 'callable', into the location defined by the given call operation. This
201
/// function returns failure if inlining is not possible, success otherwise. On
202
/// failure, no changes are made to the module. 'shouldCloneInlinedRegion'
203
/// corresponds to whether the source region should be cloned into the 'call' or
204
/// spliced directly.
205
LogicalResult inlineCall(InlinerInterface &interface, CallOpInterface call,
206
                         CallableOpInterface callable, Region *src,
207
                         bool shouldCloneInlinedRegion = true);
208
209
} // end namespace mlir
210
211
#endif // MLIR_TRANSFORMS_INLINING_UTILS_H