MLIR 22.0.0git
InliningUtils.cpp
Go to the documentation of this file.
1//===- InliningUtils.cpp ---- Misc utilities for inlining -----------------===//
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 file implements miscellaneous inlining utilities.
10//
11//===----------------------------------------------------------------------===//
12
14
15#include "mlir/IR/Builders.h"
16#include "mlir/IR/BuiltinOps.h"
17#include "mlir/IR/IRMapping.h"
18#include "mlir/IR/Operation.h"
20#include "llvm/Support/Debug.h"
21#include "llvm/Support/DebugLog.h"
22#include "llvm/Support/raw_ostream.h"
23#include <optional>
24
25#define DEBUG_TYPE "inlining"
26
27using namespace mlir;
28
29/// Combine `callee` location with `caller` location to create a stack that
30/// represents the call chain.
31/// If `callee` location is a `CallSiteLoc`, indicating an existing stack of
32/// locations, the `caller` location is appended to the end of it, extending
33/// the chain.
34/// Otherwise, a single `CallSiteLoc` is created, representing a direct call
35/// from `caller` to `callee`.
37 Location lastCallee = callee;
38 SmallVector<CallSiteLoc> calleeInliningStack;
39 while (auto nextCallSite = dyn_cast<CallSiteLoc>(lastCallee)) {
40 calleeInliningStack.push_back(nextCallSite);
41 lastCallee = nextCallSite.getCaller();
42 }
43
44 CallSiteLoc firstCallSite = CallSiteLoc::get(lastCallee, caller);
45 for (CallSiteLoc currentCallSite : reverse(calleeInliningStack))
46 firstCallSite =
47 CallSiteLoc::get(currentCallSite.getCallee(), firstCallSite);
48
49 return firstCallSite;
50}
51
52/// Remap all locations reachable from the inlined blocks with CallSiteLoc
53/// locations with the provided caller location.
54static void
56 Location callerLoc) {
58 auto remapLoc = [&](Location loc) {
59 auto [it, inserted] = mappedLocations.try_emplace(loc);
60 // Only query the attribute uniquer once per callsite attribute.
61 if (inserted) {
62 LocationAttr newLoc = stackLocations(loc, callerLoc);
63 it->getSecond() = newLoc;
64 }
65 return it->second;
66 };
67
68 AttrTypeReplacer attrReplacer;
69 attrReplacer.addReplacement(
70 [&](LocationAttr loc) -> std::pair<LocationAttr, WalkResult> {
71 return {remapLoc(loc), WalkResult::skip()};
72 });
73
74 for (Block &block : inlinedBlocks) {
75 for (BlockArgument &arg : block.getArguments())
76 if (LocationAttr newLoc = remapLoc(arg.getLoc()))
77 arg.setLoc(newLoc);
78
79 for (Operation &op : block)
80 attrReplacer.recursivelyReplaceElementsIn(&op, /*replaceAttrs=*/false,
81 /*replaceLocs=*/true);
82 }
83}
84
86 IRMapping &mapper) {
87 auto remapOperands = [&](Operation *op) {
88 for (auto &operand : op->getOpOperands())
89 if (auto mappedOp = mapper.lookupOrNull(operand.get()))
90 operand.set(mappedOp);
91 };
92 for (auto &block : inlinedBlocks)
93 block.walk(remapOperands);
94}
95
96//===----------------------------------------------------------------------===//
97// InlinerInterface
98//===----------------------------------------------------------------------===//
99
101 bool wouldBeCloned) const {
102 if (auto *handler = getInterfaceFor(call))
103 return handler->isLegalToInline(call, callable, wouldBeCloned);
104 return false;
105}
106
108 bool wouldBeCloned,
109 IRMapping &valueMapping) const {
110 if (auto *handler = getInterfaceFor(dest->getParentOp()))
111 return handler->isLegalToInline(dest, src, wouldBeCloned, valueMapping);
112 return false;
113}
114
116 bool wouldBeCloned,
117 IRMapping &valueMapping) const {
118 if (auto *handler = getInterfaceFor(op))
119 return handler->isLegalToInline(op, dest, wouldBeCloned, valueMapping);
120 return false;
121}
122
124 auto *handler = getInterfaceFor(op);
125 return handler ? handler->shouldAnalyzeRecursively(op) : true;
126}
127
128/// Handle the given inlined terminator by replacing it with a new operation
129/// as necessary.
131 auto *handler = getInterfaceFor(op);
132 assert(handler && "expected valid dialect handler");
133 handler->handleTerminator(op, newDest);
134}
135
136/// Handle the given inlined terminator by replacing it with a new operation
137/// as necessary.
139 ValueRange valuesToRepl) const {
140 auto *handler = getInterfaceFor(op);
141 assert(handler && "expected valid dialect handler");
142 handler->handleTerminator(op, valuesToRepl);
143}
144
145/// Returns true if the inliner can assume a fast path of not creating a
146/// new block, if there is only one block.
148 iterator_range<Region::iterator> inlinedBlocks) const {
149 if (inlinedBlocks.empty()) {
150 return true;
151 }
152 auto *handler = getInterfaceFor(inlinedBlocks.begin()->getParentOp());
153 assert(handler && "expected valid dialect handler");
154 return handler->allowSingleBlockOptimization(inlinedBlocks);
155}
156
158 Operation *callable, Value argument,
159 DictionaryAttr argumentAttrs) const {
160 auto *handler = getInterfaceFor(callable);
161 assert(handler && "expected valid dialect handler");
162 return handler->handleArgument(builder, call, callable, argument,
163 argumentAttrs);
164}
165
167 Operation *callable, Value result,
168 DictionaryAttr resultAttrs) const {
169 auto *handler = getInterfaceFor(callable);
170 assert(handler && "expected valid dialect handler");
171 return handler->handleResult(builder, call, callable, result, resultAttrs);
172}
173
175 Operation *call, iterator_range<Region::iterator> inlinedBlocks) const {
176 auto *handler = getInterfaceFor(call);
177 assert(handler && "expected valid dialect handler");
178 handler->processInlinedCallBlocks(call, inlinedBlocks);
179}
180
181/// Utility to check that all of the operations within 'src' can be inlined.
182static bool isLegalToInline(InlinerInterface &interface, Region *src,
183 Region *insertRegion, bool shouldCloneInlinedRegion,
184 IRMapping &valueMapping) {
185 for (auto &block : *src) {
186 for (auto &op : block) {
187 // UnrealizedConversionCastOp is inlineable but cannot implement the
188 // inliner interface due to layering constraints.
189 if (isa<UnrealizedConversionCastOp>(op))
190 continue;
191
192 // Check this operation.
193 if (!interface.isLegalToInline(&op, insertRegion,
194 shouldCloneInlinedRegion, valueMapping)) {
195 LDBG() << "* Illegal to inline because of op: "
196 << OpWithFlags(&op, OpPrintingFlags().skipRegions());
197 return false;
198 }
199 // Check any nested regions.
200 if (interface.shouldAnalyzeRecursively(&op) &&
201 llvm::any_of(op.getRegions(), [&](Region &region) {
202 return !isLegalToInline(interface, &region, insertRegion,
203 shouldCloneInlinedRegion, valueMapping);
204 }))
205 return false;
206 }
207 }
208 return true;
209}
210
211//===----------------------------------------------------------------------===//
212// Inline Methods
213//===----------------------------------------------------------------------===//
214
215static void handleArgumentImpl(InlinerInterface &interface, OpBuilder &builder,
216 CallOpInterface call,
217 CallableOpInterface callable,
218 IRMapping &mapper) {
219 // Unpack the argument attributes if there are any.
221 callable.getCallableRegion()->getNumArguments(),
222 builder.getDictionaryAttr({}));
223 if (ArrayAttr arrayAttr = callable.getArgAttrsAttr()) {
224 assert(arrayAttr.size() == argAttrs.size());
225 for (auto [idx, attr] : llvm::enumerate(arrayAttr))
226 argAttrs[idx] = cast<DictionaryAttr>(attr);
227 }
228
229 // Run the argument attribute handler for the given argument and attribute.
230 for (auto [blockArg, argAttr] :
231 llvm::zip(callable.getCallableRegion()->getArguments(), argAttrs)) {
232 Value newArgument = interface.handleArgument(
233 builder, call, callable, mapper.lookup(blockArg), argAttr);
234 assert(newArgument.getType() == mapper.lookup(blockArg).getType() &&
235 "expected the argument type to not change");
236
237 // Update the mapping to point the new argument returned by the handler.
238 mapper.map(blockArg, newArgument);
239 }
240}
241
242static void handleResultImpl(InlinerInterface &interface, OpBuilder &builder,
243 CallOpInterface call, CallableOpInterface callable,
244 ValueRange results) {
245 // Unpack the result attributes if there are any.
246 SmallVector<DictionaryAttr> resAttrs(results.size(),
247 builder.getDictionaryAttr({}));
248 if (ArrayAttr arrayAttr = callable.getResAttrsAttr()) {
249 assert(arrayAttr.size() == resAttrs.size());
250 for (auto [idx, attr] : llvm::enumerate(arrayAttr))
251 resAttrs[idx] = cast<DictionaryAttr>(attr);
252 }
253
254 // Run the result attribute handler for the given result and attribute.
255 for (auto [result, resAttr] : llvm::zip(results, resAttrs)) {
256 // Store the original result users before running the handler.
257 DenseSet<Operation *> resultUsers(llvm::from_range, result.getUsers());
258
259 Value newResult =
260 interface.handleResult(builder, call, callable, result, resAttr);
261 assert(newResult.getType() == result.getType() &&
262 "expected the result type to not change");
263
264 // Replace the result uses except for the ones introduce by the handler.
265 result.replaceUsesWithIf(newResult, [&](OpOperand &operand) {
266 return resultUsers.count(operand.getOwner());
267 });
268 }
269}
270
271static LogicalResult inlineRegionImpl(
272 InlinerInterface &interface,
274 Region *src, Block *inlineBlock, Block::iterator inlinePoint,
275 IRMapping &mapper, ValueRange resultsToReplace, TypeRange regionResultTypes,
276 std::optional<Location> inlineLoc, bool shouldCloneInlinedRegion,
277 CallOpInterface call = {}) {
278 assert(resultsToReplace.size() == regionResultTypes.size());
279 // We expect the region to have at least one block.
280 if (src->empty())
281 return failure();
282
283 // Check that all of the region arguments have been mapped.
284 auto *srcEntryBlock = &src->front();
285 if (llvm::any_of(srcEntryBlock->getArguments(),
286 [&](BlockArgument arg) { return !mapper.contains(arg); }))
287 return failure();
288
289 // Check that the operations within the source region are valid to inline.
290 Region *insertRegion = inlineBlock->getParent();
291 if (!interface.isLegalToInline(insertRegion, src, shouldCloneInlinedRegion,
292 mapper) ||
293 !isLegalToInline(interface, src, insertRegion, shouldCloneInlinedRegion,
294 mapper))
295 return failure();
296
297 // Run the argument attribute handler before inlining the callable region.
298 OpBuilder builder(inlineBlock, inlinePoint);
299 auto callable = dyn_cast<CallableOpInterface>(src->getParentOp());
300 if (call && callable)
301 handleArgumentImpl(interface, builder, call, callable, mapper);
302
303 // Clone the callee's source into the caller.
304 Block *postInsertBlock = inlineBlock->splitBlock(inlinePoint);
305 cloneCallback(builder, src, inlineBlock, postInsertBlock, mapper,
306 shouldCloneInlinedRegion);
307
308 // Get the range of newly inserted blocks.
309 auto newBlocks = llvm::make_range(std::next(inlineBlock->getIterator()),
310 postInsertBlock->getIterator());
311 Block *firstNewBlock = &*newBlocks.begin();
312
313 // Remap the locations of the inlined operations if a valid source location
314 // was provided.
315 if (inlineLoc && !llvm::isa<UnknownLoc>(*inlineLoc))
316 remapInlinedLocations(newBlocks, *inlineLoc);
317
318 // If the blocks were moved in-place, make sure to remap any necessary
319 // operands.
320 if (!shouldCloneInlinedRegion)
321 remapInlinedOperands(newBlocks, mapper);
322
323 // Process the newly inlined blocks.
324 if (call)
325 interface.processInlinedCallBlocks(call, newBlocks);
326 interface.processInlinedBlocks(newBlocks);
327
328 bool singleBlockFastPath = interface.allowSingleBlockOptimization(newBlocks);
329
330 // Handle the case where only a single block was inlined.
331 if (singleBlockFastPath && llvm::hasSingleElement(newBlocks)) {
332 // Run the result attribute handler on the terminator operands.
333 Operation *firstBlockTerminator = firstNewBlock->getTerminator();
334 builder.setInsertionPoint(firstBlockTerminator);
335 if (call && callable)
336 handleResultImpl(interface, builder, call, callable,
337 firstBlockTerminator->getOperands());
338
339 // Have the interface handle the terminator of this block.
340 interface.handleTerminator(firstBlockTerminator, resultsToReplace);
341 firstBlockTerminator->erase();
342
343 // Merge the post insert block into the cloned entry block.
344 firstNewBlock->getOperations().splice(firstNewBlock->end(),
345 postInsertBlock->getOperations());
346 postInsertBlock->erase();
347 } else {
348 // Otherwise, there were multiple blocks inlined. Add arguments to the post
349 // insertion block to represent the results to replace.
350 for (const auto &resultToRepl : llvm::enumerate(resultsToReplace)) {
351 resultToRepl.value().replaceAllUsesWith(
352 postInsertBlock->addArgument(regionResultTypes[resultToRepl.index()],
353 resultToRepl.value().getLoc()));
354 }
355
356 // Run the result attribute handler on the post insertion block arguments.
357 builder.setInsertionPointToStart(postInsertBlock);
358 if (call && callable)
359 handleResultImpl(interface, builder, call, callable,
360 postInsertBlock->getArguments());
361
362 /// Handle the terminators for each of the new blocks.
363 for (auto &newBlock : newBlocks)
364 interface.handleTerminator(newBlock.getTerminator(), postInsertBlock);
365 }
366
367 // Splice the instructions of the inlined entry block into the insert block.
368 inlineBlock->getOperations().splice(inlineBlock->end(),
369 firstNewBlock->getOperations());
370 firstNewBlock->erase();
371 return success();
372}
373
374static LogicalResult inlineRegionImpl(
375 InlinerInterface &interface,
377 Region *src, Block *inlineBlock, Block::iterator inlinePoint,
378 ValueRange inlinedOperands, ValueRange resultsToReplace,
379 std::optional<Location> inlineLoc, bool shouldCloneInlinedRegion,
380 CallOpInterface call = {}) {
381 // We expect the region to have at least one block.
382 if (src->empty())
383 return failure();
384
385 auto *entryBlock = &src->front();
386 if (inlinedOperands.size() != entryBlock->getNumArguments())
387 return failure();
388
389 // Map the provided call operands to the arguments of the region.
390 IRMapping mapper;
391 for (unsigned i = 0, e = inlinedOperands.size(); i != e; ++i) {
392 // Verify that the types of the provided values match the function argument
393 // types.
394 BlockArgument regionArg = entryBlock->getArgument(i);
395 if (inlinedOperands[i].getType() != regionArg.getType())
396 return failure();
397 mapper.map(regionArg, inlinedOperands[i]);
398 }
399
400 // Call into the main region inliner function.
401 return inlineRegionImpl(interface, cloneCallback, src, inlineBlock,
402 inlinePoint, mapper, resultsToReplace,
403 resultsToReplace.getTypes(), inlineLoc,
404 shouldCloneInlinedRegion, call);
405}
406
407LogicalResult mlir::inlineRegion(
408 InlinerInterface &interface,
410 Region *src, Operation *inlinePoint, IRMapping &mapper,
411 ValueRange resultsToReplace, TypeRange regionResultTypes,
412 std::optional<Location> inlineLoc, bool shouldCloneInlinedRegion) {
413 return inlineRegion(interface, cloneCallback, src, inlinePoint->getBlock(),
414 ++inlinePoint->getIterator(), mapper, resultsToReplace,
415 regionResultTypes, inlineLoc, shouldCloneInlinedRegion);
416}
417
418LogicalResult mlir::inlineRegion(
419 InlinerInterface &interface,
421 Region *src, Block *inlineBlock, Block::iterator inlinePoint,
422 IRMapping &mapper, ValueRange resultsToReplace, TypeRange regionResultTypes,
423 std::optional<Location> inlineLoc, bool shouldCloneInlinedRegion) {
424 return inlineRegionImpl(
425 interface, cloneCallback, src, inlineBlock, inlinePoint, mapper,
426 resultsToReplace, regionResultTypes, inlineLoc, shouldCloneInlinedRegion);
427}
428
429LogicalResult mlir::inlineRegion(
430 InlinerInterface &interface,
432 Region *src, Operation *inlinePoint, ValueRange inlinedOperands,
433 ValueRange resultsToReplace, std::optional<Location> inlineLoc,
434 bool shouldCloneInlinedRegion) {
435 return inlineRegion(interface, cloneCallback, src, inlinePoint->getBlock(),
436 ++inlinePoint->getIterator(), inlinedOperands,
437 resultsToReplace, inlineLoc, shouldCloneInlinedRegion);
438}
439
440LogicalResult mlir::inlineRegion(
441 InlinerInterface &interface,
443 Region *src, Block *inlineBlock, Block::iterator inlinePoint,
444 ValueRange inlinedOperands, ValueRange resultsToReplace,
445 std::optional<Location> inlineLoc, bool shouldCloneInlinedRegion) {
446 return inlineRegionImpl(interface, cloneCallback, src, inlineBlock,
447 inlinePoint, inlinedOperands, resultsToReplace,
448 inlineLoc, shouldCloneInlinedRegion);
449}
450
451/// Utility function used to generate a cast operation from the given interface,
452/// or return nullptr if a cast could not be generated.
455 OpBuilder &castBuilder, Value arg, Type type,
456 Location conversionLoc) {
457 if (!interface)
458 return nullptr;
459
460 // Check to see if the interface for the call can materialize a conversion.
461 Operation *castOp = interface->materializeCallConversion(castBuilder, arg,
462 type, conversionLoc);
463 if (!castOp)
464 return nullptr;
465 castOps.push_back(castOp);
466
467 // Ensure that the generated cast is correct.
468 assert(castOp->getNumOperands() == 1 && castOp->getOperand(0) == arg &&
469 castOp->getNumResults() == 1 && *castOp->result_type_begin() == type);
470 return castOp->getResult(0);
471}
472
473/// This function inlines a given region, 'src', of a callable operation,
474/// 'callable', into the location defined by the given call operation. This
475/// function returns failure if inlining is not possible, success otherwise. On
476/// failure, no changes are made to the module. 'shouldCloneInlinedRegion'
477/// corresponds to whether the source region should be cloned into the 'call' or
478/// spliced directly.
479LogicalResult mlir::inlineCall(
480 InlinerInterface &interface,
482 CallOpInterface call, CallableOpInterface callable, Region *src,
483 bool shouldCloneInlinedRegion) {
484 // We expect the region to have at least one block.
485 if (src->empty())
486 return failure();
487 auto *entryBlock = &src->front();
488 ArrayRef<Type> callableResultTypes = callable.getResultTypes();
489
490 // Make sure that the number of arguments and results matchup between the call
491 // and the region.
492 SmallVector<Value, 8> callOperands(call.getArgOperands());
493 SmallVector<Value, 8> callResults(call->getResults());
494 if (callOperands.size() != entryBlock->getNumArguments() ||
495 callResults.size() != callableResultTypes.size())
496 return failure();
497
498 // A set of cast operations generated to matchup the signature of the region
499 // with the signature of the call.
501 castOps.reserve(callOperands.size() + callResults.size());
502
503 // Functor used to cleanup generated state on failure.
504 auto cleanupState = [&] {
505 for (auto *op : castOps) {
506 op->getResult(0).replaceAllUsesWith(op->getOperand(0));
507 op->erase();
508 }
509 return failure();
510 };
511
512 // Builder used for any conversion operations that need to be materialized.
513 OpBuilder castBuilder(call);
514 Location castLoc = call.getLoc();
515 const auto *callInterface = interface.getInterfaceFor(call->getDialect());
516
517 // Map the provided call operands to the arguments of the region.
518 IRMapping mapper;
519 for (unsigned i = 0, e = callOperands.size(); i != e; ++i) {
520 BlockArgument regionArg = entryBlock->getArgument(i);
521 Value operand = callOperands[i];
522
523 // If the call operand doesn't match the expected region argument, try to
524 // generate a cast.
525 Type regionArgType = regionArg.getType();
526 if (operand.getType() != regionArgType) {
527 if (!(operand = materializeConversion(callInterface, castOps, castBuilder,
528 operand, regionArgType, castLoc)))
529 return cleanupState();
530 }
531 mapper.map(regionArg, operand);
532 }
533
534 // Ensure that the resultant values of the call match the callable.
535 castBuilder.setInsertionPointAfter(call);
536 for (unsigned i = 0, e = callResults.size(); i != e; ++i) {
537 Value callResult = callResults[i];
538 if (callResult.getType() == callableResultTypes[i])
539 continue;
540
541 // Generate a conversion that will produce the original type, so that the IR
542 // is still valid after the original call gets replaced.
543 Value castResult =
544 materializeConversion(callInterface, castOps, castBuilder, callResult,
545 callResult.getType(), castLoc);
546 if (!castResult)
547 return cleanupState();
548 callResult.replaceAllUsesWith(castResult);
549 castResult.getDefiningOp()->replaceUsesOfWith(castResult, callResult);
550 }
551
552 // Check that it is legal to inline the callable into the call.
553 if (!interface.isLegalToInline(call, callable, shouldCloneInlinedRegion))
554 return cleanupState();
555
556 // Attempt to inline the call.
557 if (failed(inlineRegionImpl(interface, cloneCallback, src, call->getBlock(),
558 ++call->getIterator(), mapper, callResults,
559 callableResultTypes, call.getLoc(),
560 shouldCloneInlinedRegion, call)))
561 return cleanupState();
562 return success();
563}
return success()
static void remapInlinedOperands(iterator_range< Region::iterator > inlinedBlocks, IRMapping &mapper)
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.
static void handleResultImpl(InlinerInterface &interface, OpBuilder &builder, CallOpInterface call, CallableOpInterface callable, ValueRange results)
static LocationAttr stackLocations(Location callee, Location caller)
Combine callee location with caller location to create a stack that represents the call chain.
static LogicalResult inlineRegionImpl(InlinerInterface &interface, function_ref< InlinerInterface::CloneCallbackSigTy > cloneCallback, Region *src, Block *inlineBlock, Block::iterator inlinePoint, IRMapping &mapper, ValueRange resultsToReplace, TypeRange regionResultTypes, std::optional< Location > inlineLoc, bool shouldCloneInlinedRegion, CallOpInterface call={})
static Value materializeConversion(const DialectInlinerInterface *interface, SmallVectorImpl< Operation * > &castOps, OpBuilder &castBuilder, Value arg, Type type, Location conversionLoc)
Utility function used to generate a cast operation from the given interface, or return nullptr if a c...
static void remapInlinedLocations(iterator_range< Region::iterator > inlinedBlocks, Location callerLoc)
Remap all locations reachable from the inlined blocks with CallSiteLoc locations with the provided ca...
static void handleArgumentImpl(InlinerInterface &interface, OpBuilder &builder, CallOpInterface call, CallableOpInterface callable, IRMapping &mapper)
ArrayAttr()
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
This is an attribute/type replacer that is naively cached.
This class represents an argument of a Block.
Definition Value.h:309
Block represents an ordered list of Operations.
Definition Block.h:33
OpListType::iterator iterator
Definition Block.h:140
void erase()
Unlink this Block from its parent region and delete it.
Definition Block.cpp:66
Block * splitBlock(iterator splitBefore)
Split the block into two blocks before the specified operation or iterator.
Definition Block.cpp:318
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Definition Block.cpp:27
OpListType & getOperations()
Definition Block.h:137
Operation * getTerminator()
Get the terminator operation of this block.
Definition Block.cpp:244
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition Block.cpp:153
BlockArgListType getArguments()
Definition Block.h:87
iterator end()
Definition Block.h:144
iterator begin()
Definition Block.h:143
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
Definition Builders.cpp:104
This is the interface that must be implemented by the dialects of operations to be inlined.
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,...
const DialectInlinerInterface * getInterfaceFor(Object *obj) const
This is a utility class for mapping one set of IR entities to another.
Definition IRMapping.h:26
auto lookup(T from) const
Lookup a mapped value within the map.
Definition IRMapping.h:72
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
Definition IRMapping.h:30
auto lookupOrNull(T from) const
Lookup a mapped value within the map.
Definition IRMapping.h:58
This interface provides the hooks into the inlining interface.
virtual Value handleResult(OpBuilder &builder, Operation *call, Operation *callable, Value result, DictionaryAttr resultAttrs) const
virtual Value handleArgument(OpBuilder &builder, Operation *call, Operation *callable, Value argument, DictionaryAttr argumentAttrs) const
virtual bool shouldAnalyzeRecursively(Operation *op) const
virtual bool allowSingleBlockOptimization(iterator_range< Region::iterator > inlinedBlocks) const
Returns true if the inliner can assume a fast path of not creating a new block, if there is only one ...
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 ...
Location objects represent source locations information in MLIR.
Definition Location.h:32
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
This class helps build Operations.
Definition Builders.h:207
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Definition Builders.h:412
This class represents an operand of an operation.
Definition Value.h:257
Set of flags used to control the behavior of the various IR print methods (e.g.
A wrapper class that allows for printing an operation with a set of flags, useful to act as a "stream...
Definition Operation.h:1111
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
void replaceUsesOfWith(Value from, Value to)
Replace any uses of 'from' with 'to' within this operation.
Value getOperand(unsigned idx)
Definition Operation.h:350
Block * getBlock()
Returns the operation block that contains this operation.
Definition Operation.h:213
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:407
unsigned getNumOperands()
Definition Operation.h:346
result_type_iterator result_type_begin()
Definition Operation.h:426
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition Operation.h:378
void erase()
Remove this operation from its parent block and delete it.
unsigned getNumResults()
Return the number of results held by this operation.
Definition Operation.h:404
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
Block & front()
Definition Region.h:65
bool empty()
Definition Region.h:60
Operation * getParentOp()
Return the parent operation this region is attached to.
Definition Region.h:200
This class provides an abstraction over the various different ranges of value types.
Definition TypeRange.h:37
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:387
type_range getTypes() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Type getType() const
Return the type of this value.
Definition Value.h:105
void replaceAllUsesWith(Value newValue)
Replace all uses of 'this' value with the new value, updating anything in the IR that uses 'this' to ...
Definition Value.h:149
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition Value.cpp:18
static WalkResult skip()
Definition WalkResult.h:48
void recursivelyReplaceElementsIn(Operation *op, bool replaceAttrs=true, bool replaceLocs=false, bool replaceTypes=false)
Replace the elements within the given operation, and all nested operations.
void addReplacement(ReplaceFn< Attribute > fn)
AttrTypeReplacerBase.
Operation * getOwner() const
Return the owner of this operand.
Definition UseDefLists.h:38
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Definition Utils.cpp:304
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
Definition LLVM.h:128
LogicalResult inlineCall(InlinerInterface &interface, function_ref< InlinerInterface::CloneCallbackSigTy > cloneCallback, 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...
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:126
LogicalResult inlineRegion(InlinerInterface &interface, function_ref< InlinerInterface::CloneCallbackSigTy > cloneCallback, 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.
llvm::function_ref< Fn > function_ref
Definition LLVM.h:152