MLIR  18.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/IRMapping.h"
17 #include "mlir/IR/Operation.h"
19 #include "llvm/ADT/MapVector.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <optional>
23 
24 #define DEBUG_TYPE "inlining"
25 
26 using namespace mlir;
27 
28 /// Remap locations from the inlined blocks with CallSiteLoc locations with the
29 /// provided caller location.
30 static void
32  Location callerLoc) {
33  DenseMap<Location, Location> mappedLocations;
34  auto remapOpLoc = [&](Operation *op) {
35  auto it = mappedLocations.find(op->getLoc());
36  if (it == mappedLocations.end()) {
37  auto newLoc = CallSiteLoc::get(op->getLoc(), callerLoc);
38  it = mappedLocations.try_emplace(op->getLoc(), newLoc).first;
39  }
40  op->setLoc(it->second);
41  };
42  for (auto &block : inlinedBlocks)
43  block.walk(remapOpLoc);
44 }
45 
47  IRMapping &mapper) {
48  auto remapOperands = [&](Operation *op) {
49  for (auto &operand : op->getOpOperands())
50  if (auto mappedOp = mapper.lookupOrNull(operand.get()))
51  operand.set(mappedOp);
52  };
53  for (auto &block : inlinedBlocks)
54  block.walk(remapOperands);
55 }
56 
57 //===----------------------------------------------------------------------===//
58 // InlinerInterface
59 //===----------------------------------------------------------------------===//
60 
62  bool wouldBeCloned) const {
63  if (auto *handler = getInterfaceFor(call))
64  return handler->isLegalToInline(call, callable, wouldBeCloned);
65  return false;
66 }
67 
69  bool wouldBeCloned,
70  IRMapping &valueMapping) const {
71  if (auto *handler = getInterfaceFor(dest->getParentOp()))
72  return handler->isLegalToInline(dest, src, wouldBeCloned, valueMapping);
73  return false;
74 }
75 
77  bool wouldBeCloned,
78  IRMapping &valueMapping) const {
79  if (auto *handler = getInterfaceFor(op))
80  return handler->isLegalToInline(op, dest, wouldBeCloned, valueMapping);
81  return false;
82 }
83 
85  auto *handler = getInterfaceFor(op);
86  return handler ? handler->shouldAnalyzeRecursively(op) : true;
87 }
88 
89 /// Handle the given inlined terminator by replacing it with a new operation
90 /// as necessary.
92  auto *handler = getInterfaceFor(op);
93  assert(handler && "expected valid dialect handler");
94  handler->handleTerminator(op, newDest);
95 }
96 
97 /// Handle the given inlined terminator by replacing it with a new operation
98 /// as necessary.
100  ArrayRef<Value> valuesToRepl) const {
101  auto *handler = getInterfaceFor(op);
102  assert(handler && "expected valid dialect handler");
103  handler->handleTerminator(op, valuesToRepl);
104 }
105 
107  Operation *callable, Value argument,
108  DictionaryAttr argumentAttrs) const {
109  auto *handler = getInterfaceFor(callable);
110  assert(handler && "expected valid dialect handler");
111  return handler->handleArgument(builder, call, callable, argument,
112  argumentAttrs);
113 }
114 
116  Operation *callable, Value result,
117  DictionaryAttr resultAttrs) const {
118  auto *handler = getInterfaceFor(callable);
119  assert(handler && "expected valid dialect handler");
120  return handler->handleResult(builder, call, callable, result, resultAttrs);
121 }
122 
124  Operation *call, iterator_range<Region::iterator> inlinedBlocks) const {
125  auto *handler = getInterfaceFor(call);
126  assert(handler && "expected valid dialect handler");
127  handler->processInlinedCallBlocks(call, inlinedBlocks);
128 }
129 
130 /// Utility to check that all of the operations within 'src' can be inlined.
131 static bool isLegalToInline(InlinerInterface &interface, Region *src,
132  Region *insertRegion, bool shouldCloneInlinedRegion,
133  IRMapping &valueMapping) {
134  for (auto &block : *src) {
135  for (auto &op : block) {
136  // Check this operation.
137  if (!interface.isLegalToInline(&op, insertRegion,
138  shouldCloneInlinedRegion, valueMapping)) {
139  LLVM_DEBUG({
140  llvm::dbgs() << "* Illegal to inline because of op: ";
141  op.dump();
142  });
143  return false;
144  }
145  // Check any nested regions.
146  if (interface.shouldAnalyzeRecursively(&op) &&
147  llvm::any_of(op.getRegions(), [&](Region &region) {
148  return !isLegalToInline(interface, &region, insertRegion,
149  shouldCloneInlinedRegion, valueMapping);
150  }))
151  return false;
152  }
153  }
154  return true;
155 }
156 
157 //===----------------------------------------------------------------------===//
158 // Inline Methods
159 //===----------------------------------------------------------------------===//
160 
161 static void handleArgumentImpl(InlinerInterface &interface, OpBuilder &builder,
162  CallOpInterface call,
163  CallableOpInterface callable,
164  IRMapping &mapper) {
165  // Unpack the argument attributes if there are any.
167  callable.getCallableRegion()->getNumArguments(),
168  builder.getDictionaryAttr({}));
169  if (ArrayAttr arrayAttr = callable.getArgAttrsAttr()) {
170  assert(arrayAttr.size() == argAttrs.size());
171  for (auto [idx, attr] : llvm::enumerate(arrayAttr))
172  argAttrs[idx] = cast<DictionaryAttr>(attr);
173  }
174 
175  // Run the argument attribute handler for the given argument and attribute.
176  for (auto [blockArg, argAttr] :
177  llvm::zip(callable.getCallableRegion()->getArguments(), argAttrs)) {
178  Value newArgument = interface.handleArgument(
179  builder, call, callable, mapper.lookup(blockArg), argAttr);
180  assert(newArgument.getType() == mapper.lookup(blockArg).getType() &&
181  "expected the argument type to not change");
182 
183  // Update the mapping to point the new argument returned by the handler.
184  mapper.map(blockArg, newArgument);
185  }
186 }
187 
188 static void handleResultImpl(InlinerInterface &interface, OpBuilder &builder,
189  CallOpInterface call, CallableOpInterface callable,
190  ValueRange results) {
191  // Unpack the result attributes if there are any.
192  SmallVector<DictionaryAttr> resAttrs(results.size(),
193  builder.getDictionaryAttr({}));
194  if (ArrayAttr arrayAttr = callable.getResAttrsAttr()) {
195  assert(arrayAttr.size() == resAttrs.size());
196  for (auto [idx, attr] : llvm::enumerate(arrayAttr))
197  resAttrs[idx] = cast<DictionaryAttr>(attr);
198  }
199 
200  // Run the result attribute handler for the given result and attribute.
201  SmallVector<DictionaryAttr> resultAttributes;
202  for (auto [result, resAttr] : llvm::zip(results, resAttrs)) {
203  // Store the original result users before running the handler.
204  DenseSet<Operation *> resultUsers;
205  for (Operation *user : result.getUsers())
206  resultUsers.insert(user);
207 
208  Value newResult =
209  interface.handleResult(builder, call, callable, result, resAttr);
210  assert(newResult.getType() == result.getType() &&
211  "expected the result type to not change");
212 
213  // Replace the result uses except for the ones introduce by the handler.
214  result.replaceUsesWithIf(newResult, [&](OpOperand &operand) {
215  return resultUsers.count(operand.getOwner());
216  });
217  }
218 }
219 
220 static LogicalResult
221 inlineRegionImpl(InlinerInterface &interface, Region *src, Block *inlineBlock,
222  Block::iterator inlinePoint, IRMapping &mapper,
223  ValueRange resultsToReplace, TypeRange regionResultTypes,
224  std::optional<Location> inlineLoc,
225  bool shouldCloneInlinedRegion, CallOpInterface call = {}) {
226  assert(resultsToReplace.size() == regionResultTypes.size());
227  // We expect the region to have at least one block.
228  if (src->empty())
229  return failure();
230 
231  // Check that all of the region arguments have been mapped.
232  auto *srcEntryBlock = &src->front();
233  if (llvm::any_of(srcEntryBlock->getArguments(),
234  [&](BlockArgument arg) { return !mapper.contains(arg); }))
235  return failure();
236 
237  // Check that the operations within the source region are valid to inline.
238  Region *insertRegion = inlineBlock->getParent();
239  if (!interface.isLegalToInline(insertRegion, src, shouldCloneInlinedRegion,
240  mapper) ||
241  !isLegalToInline(interface, src, insertRegion, shouldCloneInlinedRegion,
242  mapper))
243  return failure();
244 
245  // Run the argument attribute handler before inlining the callable region.
246  OpBuilder builder(inlineBlock, inlinePoint);
247  auto callable = dyn_cast<CallableOpInterface>(src->getParentOp());
248  if (call && callable)
249  handleArgumentImpl(interface, builder, call, callable, mapper);
250 
251  // Check to see if the region is being cloned, or moved inline. In either
252  // case, move the new blocks after the 'insertBlock' to improve IR
253  // readability.
254  Block *postInsertBlock = inlineBlock->splitBlock(inlinePoint);
255  if (shouldCloneInlinedRegion)
256  src->cloneInto(insertRegion, postInsertBlock->getIterator(), mapper);
257  else
258  insertRegion->getBlocks().splice(postInsertBlock->getIterator(),
259  src->getBlocks(), src->begin(),
260  src->end());
261 
262  // Get the range of newly inserted blocks.
263  auto newBlocks = llvm::make_range(std::next(inlineBlock->getIterator()),
264  postInsertBlock->getIterator());
265  Block *firstNewBlock = &*newBlocks.begin();
266 
267  // Remap the locations of the inlined operations if a valid source location
268  // was provided.
269  if (inlineLoc && !llvm::isa<UnknownLoc>(*inlineLoc))
270  remapInlinedLocations(newBlocks, *inlineLoc);
271 
272  // If the blocks were moved in-place, make sure to remap any necessary
273  // operands.
274  if (!shouldCloneInlinedRegion)
275  remapInlinedOperands(newBlocks, mapper);
276 
277  // Process the newly inlined blocks.
278  if (call)
279  interface.processInlinedCallBlocks(call, newBlocks);
280  interface.processInlinedBlocks(newBlocks);
281 
282  // Handle the case where only a single block was inlined.
283  if (std::next(newBlocks.begin()) == newBlocks.end()) {
284  // Run the result attribute handler on the terminator operands.
285  Operation *firstBlockTerminator = firstNewBlock->getTerminator();
286  builder.setInsertionPoint(firstBlockTerminator);
287  if (call && callable)
288  handleResultImpl(interface, builder, call, callable,
289  firstBlockTerminator->getOperands());
290 
291  // Have the interface handle the terminator of this block.
292  interface.handleTerminator(firstBlockTerminator,
293  llvm::to_vector<6>(resultsToReplace));
294  firstBlockTerminator->erase();
295 
296  // Merge the post insert block into the cloned entry block.
297  firstNewBlock->getOperations().splice(firstNewBlock->end(),
298  postInsertBlock->getOperations());
299  postInsertBlock->erase();
300  } else {
301  // Otherwise, there were multiple blocks inlined. Add arguments to the post
302  // insertion block to represent the results to replace.
303  for (const auto &resultToRepl : llvm::enumerate(resultsToReplace)) {
304  resultToRepl.value().replaceAllUsesWith(
305  postInsertBlock->addArgument(regionResultTypes[resultToRepl.index()],
306  resultToRepl.value().getLoc()));
307  }
308 
309  // Run the result attribute handler on the post insertion block arguments.
310  builder.setInsertionPointToStart(postInsertBlock);
311  if (call && callable)
312  handleResultImpl(interface, builder, call, callable,
313  postInsertBlock->getArguments());
314 
315  /// Handle the terminators for each of the new blocks.
316  for (auto &newBlock : newBlocks)
317  interface.handleTerminator(newBlock.getTerminator(), postInsertBlock);
318  }
319 
320  // Splice the instructions of the inlined entry block into the insert block.
321  inlineBlock->getOperations().splice(inlineBlock->end(),
322  firstNewBlock->getOperations());
323  firstNewBlock->erase();
324  return success();
325 }
326 
327 static LogicalResult
328 inlineRegionImpl(InlinerInterface &interface, Region *src, Block *inlineBlock,
329  Block::iterator inlinePoint, ValueRange inlinedOperands,
330  ValueRange resultsToReplace, std::optional<Location> inlineLoc,
331  bool shouldCloneInlinedRegion, CallOpInterface call = {}) {
332  // We expect the region to have at least one block.
333  if (src->empty())
334  return failure();
335 
336  auto *entryBlock = &src->front();
337  if (inlinedOperands.size() != entryBlock->getNumArguments())
338  return failure();
339 
340  // Map the provided call operands to the arguments of the region.
341  IRMapping mapper;
342  for (unsigned i = 0, e = inlinedOperands.size(); i != e; ++i) {
343  // Verify that the types of the provided values match the function argument
344  // types.
345  BlockArgument regionArg = entryBlock->getArgument(i);
346  if (inlinedOperands[i].getType() != regionArg.getType())
347  return failure();
348  mapper.map(regionArg, inlinedOperands[i]);
349  }
350 
351  // Call into the main region inliner function.
352  return inlineRegionImpl(interface, src, inlineBlock, inlinePoint, mapper,
353  resultsToReplace, resultsToReplace.getTypes(),
354  inlineLoc, shouldCloneInlinedRegion, call);
355 }
356 
358  Operation *inlinePoint, IRMapping &mapper,
359  ValueRange resultsToReplace,
360  TypeRange regionResultTypes,
361  std::optional<Location> inlineLoc,
362  bool shouldCloneInlinedRegion) {
363  return inlineRegion(interface, src, inlinePoint->getBlock(),
364  ++inlinePoint->getIterator(), mapper, resultsToReplace,
365  regionResultTypes, inlineLoc, shouldCloneInlinedRegion);
366 }
368  Block *inlineBlock,
369  Block::iterator inlinePoint, IRMapping &mapper,
370  ValueRange resultsToReplace,
371  TypeRange regionResultTypes,
372  std::optional<Location> inlineLoc,
373  bool shouldCloneInlinedRegion) {
374  return inlineRegionImpl(interface, src, inlineBlock, inlinePoint, mapper,
375  resultsToReplace, regionResultTypes, inlineLoc,
376  shouldCloneInlinedRegion);
377 }
378 
380  Operation *inlinePoint,
381  ValueRange inlinedOperands,
382  ValueRange resultsToReplace,
383  std::optional<Location> inlineLoc,
384  bool shouldCloneInlinedRegion) {
385  return inlineRegion(interface, src, inlinePoint->getBlock(),
386  ++inlinePoint->getIterator(), inlinedOperands,
387  resultsToReplace, inlineLoc, shouldCloneInlinedRegion);
388 }
390  Block *inlineBlock,
391  Block::iterator inlinePoint,
392  ValueRange inlinedOperands,
393  ValueRange resultsToReplace,
394  std::optional<Location> inlineLoc,
395  bool shouldCloneInlinedRegion) {
396  return inlineRegionImpl(interface, src, inlineBlock, inlinePoint,
397  inlinedOperands, resultsToReplace, inlineLoc,
398  shouldCloneInlinedRegion);
399 }
400 
401 /// Utility function used to generate a cast operation from the given interface,
402 /// or return nullptr if a cast could not be generated.
405  OpBuilder &castBuilder, Value arg, Type type,
406  Location conversionLoc) {
407  if (!interface)
408  return nullptr;
409 
410  // Check to see if the interface for the call can materialize a conversion.
411  Operation *castOp = interface->materializeCallConversion(castBuilder, arg,
412  type, conversionLoc);
413  if (!castOp)
414  return nullptr;
415  castOps.push_back(castOp);
416 
417  // Ensure that the generated cast is correct.
418  assert(castOp->getNumOperands() == 1 && castOp->getOperand(0) == arg &&
419  castOp->getNumResults() == 1 && *castOp->result_type_begin() == type);
420  return castOp->getResult(0);
421 }
422 
423 /// This function inlines a given region, 'src', of a callable operation,
424 /// 'callable', into the location defined by the given call operation. This
425 /// function returns failure if inlining is not possible, success otherwise. On
426 /// failure, no changes are made to the module. 'shouldCloneInlinedRegion'
427 /// corresponds to whether the source region should be cloned into the 'call' or
428 /// spliced directly.
430  CallOpInterface call,
431  CallableOpInterface callable, Region *src,
432  bool shouldCloneInlinedRegion) {
433  // We expect the region to have at least one block.
434  if (src->empty())
435  return failure();
436  auto *entryBlock = &src->front();
437  ArrayRef<Type> callableResultTypes = callable.getResultTypes();
438 
439  // Make sure that the number of arguments and results matchup between the call
440  // and the region.
441  SmallVector<Value, 8> callOperands(call.getArgOperands());
442  SmallVector<Value, 8> callResults(call->getResults());
443  if (callOperands.size() != entryBlock->getNumArguments() ||
444  callResults.size() != callableResultTypes.size())
445  return failure();
446 
447  // A set of cast operations generated to matchup the signature of the region
448  // with the signature of the call.
450  castOps.reserve(callOperands.size() + callResults.size());
451 
452  // Functor used to cleanup generated state on failure.
453  auto cleanupState = [&] {
454  for (auto *op : castOps) {
455  op->getResult(0).replaceAllUsesWith(op->getOperand(0));
456  op->erase();
457  }
458  return failure();
459  };
460 
461  // Builder used for any conversion operations that need to be materialized.
462  OpBuilder castBuilder(call);
463  Location castLoc = call.getLoc();
464  const auto *callInterface = interface.getInterfaceFor(call->getDialect());
465 
466  // Map the provided call operands to the arguments of the region.
467  IRMapping mapper;
468  for (unsigned i = 0, e = callOperands.size(); i != e; ++i) {
469  BlockArgument regionArg = entryBlock->getArgument(i);
470  Value operand = callOperands[i];
471 
472  // If the call operand doesn't match the expected region argument, try to
473  // generate a cast.
474  Type regionArgType = regionArg.getType();
475  if (operand.getType() != regionArgType) {
476  if (!(operand = materializeConversion(callInterface, castOps, castBuilder,
477  operand, regionArgType, castLoc)))
478  return cleanupState();
479  }
480  mapper.map(regionArg, operand);
481  }
482 
483  // Ensure that the resultant values of the call match the callable.
484  castBuilder.setInsertionPointAfter(call);
485  for (unsigned i = 0, e = callResults.size(); i != e; ++i) {
486  Value callResult = callResults[i];
487  if (callResult.getType() == callableResultTypes[i])
488  continue;
489 
490  // Generate a conversion that will produce the original type, so that the IR
491  // is still valid after the original call gets replaced.
492  Value castResult =
493  materializeConversion(callInterface, castOps, castBuilder, callResult,
494  callResult.getType(), castLoc);
495  if (!castResult)
496  return cleanupState();
497  callResult.replaceAllUsesWith(castResult);
498  castResult.getDefiningOp()->replaceUsesOfWith(castResult, callResult);
499  }
500 
501  // Check that it is legal to inline the callable into the call.
502  if (!interface.isLegalToInline(call, callable, shouldCloneInlinedRegion))
503  return cleanupState();
504 
505  // Attempt to inline the call.
506  if (failed(inlineRegionImpl(interface, src, call->getBlock(),
507  ++call->getIterator(), mapper, callResults,
508  callableResultTypes, call.getLoc(),
509  shouldCloneInlinedRegion, call)))
510  return cleanupState();
511  return success();
512 }
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 LogicalResult inlineRegionImpl(InlinerInterface &interface, 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 locations from the inlined blocks with CallSiteLoc locations with the provided caller location.
static void handleArgumentImpl(InlinerInterface &interface, OpBuilder &builder, CallOpInterface call, CallableOpInterface callable, IRMapping &mapper)
This class represents an argument of a Block.
Definition: Value.h:310
Block represents an ordered list of Operations.
Definition: Block.h:30
OpListType::iterator iterator
Definition: Block.h:133
void erase()
Unlink this Block from its parent region and delete it.
Definition: Block.cpp:60
Block * splitBlock(iterator splitBefore)
Split the block into two blocks before the specified operation or iterator.
Definition: Block.cpp:302
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Definition: Block.cpp:26
Operation * getTerminator()
Get the terminator operation of this block.
Definition: Block.cpp:238
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition: Block.cpp:147
OpListType & getOperations()
Definition: Block.h:130
BlockArgListType getArguments()
Definition: Block.h:80
iterator end()
Definition: Block.h:137
iterator begin()
Definition: Block.h:136
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
Definition: Builders.cpp:120
This is the interface that must be implemented by the dialects of operations to be inlined.
Definition: InliningUtils.h:43
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
Get the interface for a given object, or null if one is not registered.
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 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:206
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Definition: Builders.h:397
This class represents an operand of an operation.
Definition: Value.h:261
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
void setLoc(Location loc)
Set the source location the operation was defined or derived from.
Definition: Operation.h:226
void replaceUsesOfWith(Value from, Value to)
Replace any uses of 'from' with 'to' within this operation.
Definition: Operation.cpp:226
Value getOperand(unsigned idx)
Definition: Operation.h:345
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition: Operation.h:402
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
unsigned getNumOperands()
Definition: Operation.h:341
Block * getBlock()
Returns the operation block that contains this operation.
Definition: Operation.h:213
result_type_iterator result_type_begin()
Definition: Operation.h:421
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition: Operation.h:655
MutableArrayRef< OpOperand > getOpOperands()
Definition: Operation.h:378
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition: Operation.h:373
user_range getUsers()
Returns a range of all users.
Definition: Operation.h:852
void erase()
Remove this operation from its parent block and delete it.
Definition: Operation.cpp:538
unsigned getNumResults()
Return the number of results held by this operation.
Definition: Operation.h:399
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
Operation * getParentOp()
Return the parent operation this region is attached to.
Definition: Region.h:200
bool empty()
Definition: Region.h:60
void cloneInto(Region *dest, IRMapping &mapper)
Clone the internal blocks from this region into dest.
Definition: Region.cpp:70
iterator end()
Definition: Region.h:56
iterator begin()
Definition: Region.h:55
BlockListType & getBlocks()
Definition: Region.h:45
Block & front()
Definition: Region.h:65
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:36
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:372
type_range getTypes() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:93
Type getType() const
Return the type of this value.
Definition: Value.h:122
void replaceAllUsesWith(Value newValue) const
Replace all uses of 'this' value with the new value, updating anything in the IR that uses 'this' to ...
Definition: Value.h:166
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition: Value.cpp:20
Operation * getOwner() const
Return the owner of this operand.
Definition: UseDefLists.h:38
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:285
This header declares functions that assist transformations in the MemRef dialect.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
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.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
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...
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26