MLIR  20.0.0git
OneToNTypeConversion.cpp
Go to the documentation of this file.
1 //===-- OneToNTypeConversion.cpp - Utils for 1:N type conversion-*- C++ -*-===//
2 //
3 // Licensed 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 
10 
13 #include "llvm/ADT/SmallSet.h"
14 
15 #include <unordered_map>
16 
17 using namespace llvm;
18 using namespace mlir;
19 
20 std::optional<SmallVector<Value>>
21 OneToNTypeConverter::materializeTargetConversion(OpBuilder &builder,
22  Location loc,
23  TypeRange resultTypes,
24  Value input) const {
25  for (const OneToNMaterializationCallbackFn &fn :
26  llvm::reverse(oneToNTargetMaterializations)) {
27  if (std::optional<SmallVector<Value>> result =
28  fn(builder, resultTypes, input, loc))
29  return *result;
30  }
31  return std::nullopt;
32 }
33 
34 TypeRange OneToNTypeMapping::getConvertedTypes(unsigned originalTypeNo) const {
35  TypeRange convertedTypes = getConvertedTypes();
36  if (auto mapping = getInputMapping(originalTypeNo))
37  return convertedTypes.slice(mapping->inputNo, mapping->size);
38  return {};
39 }
40 
42 OneToNTypeMapping::getConvertedValues(ValueRange convertedValues,
43  unsigned originalValueNo) const {
44  if (auto mapping = getInputMapping(originalValueNo))
45  return convertedValues.slice(mapping->inputNo, mapping->size);
46  return {};
47 }
48 
49 void OneToNTypeMapping::convertLocation(
50  Value originalValue, unsigned originalValueNo,
51  llvm::SmallVectorImpl<Location> &result) const {
52  if (auto mapping = getInputMapping(originalValueNo))
53  result.append(mapping->size, originalValue.getLoc());
54 }
55 
56 void OneToNTypeMapping::convertLocations(
57  ValueRange originalValues, llvm::SmallVectorImpl<Location> &result) const {
58  assert(originalValues.size() == getOriginalTypes().size());
59  for (auto [i, value] : llvm::enumerate(originalValues))
60  convertLocation(value, i, result);
61 }
62 
63 static bool isIdentityConversion(Type originalType, TypeRange convertedTypes) {
64  return convertedTypes.size() == 1 && convertedTypes[0] == originalType;
65 }
66 
67 bool OneToNTypeMapping::hasNonIdentityConversion() const {
68  // XXX: I think that the original types and the converted types are the same
69  // iff there was no non-identity type conversion. If that is true, the
70  // patterns could actually test whether there is anything useful to do
71  // without having access to the signature conversion.
72  for (auto [i, originalType] : llvm::enumerate(originalTypes)) {
73  TypeRange types = getConvertedTypes(i);
74  if (!isIdentityConversion(originalType, types)) {
75  assert(TypeRange(originalTypes) != getConvertedTypes());
76  return true;
77  }
78  }
79  assert(TypeRange(originalTypes) == getConvertedTypes());
80  return false;
81 }
82 
83 namespace {
84 enum class CastKind {
85  // Casts block arguments in the target type back to the source type. (If
86  // necessary, this cast becomes an argument materialization.)
87  Argument,
88 
89  // Casts other values in the target type back to the source type. (If
90  // necessary, this cast becomes a source materialization.)
91  Source,
92 
93  // Casts values in the source type to the target type. (If necessary, this
94  // cast becomes a target materialization.)
95  Target
96 };
97 } // namespace
98 
99 /// Mapping of enum values to string values.
100 StringRef getCastKindName(CastKind kind) {
101  static const std::unordered_map<CastKind, StringRef> castKindNames = {
102  {CastKind::Argument, "argument"},
103  {CastKind::Source, "source"},
104  {CastKind::Target, "target"}};
105  return castKindNames.at(kind);
106 }
107 
108 /// Attribute name that is used to annotate inserted unrealized casts with their
109 /// kind (source, argument, or target).
110 static const char *const castKindAttrName =
111  "__one-to-n-type-conversion_cast-kind__";
112 
113 /// Builds an `UnrealizedConversionCastOp` from the given inputs to the given
114 /// result types. Returns the result values of the cast.
115 static ValueRange buildUnrealizedCast(OpBuilder &builder, TypeRange resultTypes,
116  ValueRange inputs, CastKind kind) {
117  // Special case: 1-to-N conversion with N = 0. No need to build an
118  // UnrealizedConversionCastOp because the op will always be dead.
119  if (resultTypes.empty())
120  return ValueRange();
121 
122  // Create cast.
123  Location loc = builder.getUnknownLoc();
124  if (!inputs.empty())
125  loc = inputs.front().getLoc();
126  auto castOp =
127  builder.create<UnrealizedConversionCastOp>(loc, resultTypes, inputs);
128 
129  // Store cast kind as attribute.
130  auto kindAttr = StringAttr::get(builder.getContext(), getCastKindName(kind));
131  castOp->setAttr(castKindAttrName, kindAttr);
132 
133  return castOp->getResults();
134 }
135 
136 /// Builds one `UnrealizedConversionCastOp` for each of the given original
137 /// values using the respective target types given in the provided conversion
138 /// mapping and returns the results of these casts. If the conversion mapping of
139 /// a value maps a type to itself (i.e., is an identity conversion), then no
140 /// cast is inserted and the original value is returned instead.
141 /// Note that these unrealized casts are different from target materializations
142 /// in that they are *always* inserted, even if they immediately fold away, such
143 /// that patterns always see valid intermediate IR, whereas materializations are
144 /// only used in the places where the unrealized casts *don't* fold away.
145 static SmallVector<Value>
147  OneToNTypeMapping &conversion,
148  RewriterBase &rewriter, CastKind kind) {
149 
150  // Convert each operand one by one.
151  SmallVector<Value> convertedValues;
152  convertedValues.reserve(conversion.getConvertedTypes().size());
153  for (auto [idx, originalValue] : llvm::enumerate(originalValues)) {
154  TypeRange convertedTypes = conversion.getConvertedTypes(idx);
155 
156  // Identity conversion: keep operand as is.
157  if (isIdentityConversion(originalValue.getType(), convertedTypes)) {
158  convertedValues.push_back(originalValue);
159  continue;
160  }
161 
162  // Non-identity conversion: materialize target types.
163  ValueRange castResult =
164  buildUnrealizedCast(rewriter, convertedTypes, originalValue, kind);
165  convertedValues.append(castResult.begin(), castResult.end());
166  }
167 
168  return convertedValues;
169 }
170 
171 /// Builds one `UnrealizedConversionCastOp` for each sequence of the given
172 /// original values to one value of the type they originated from, i.e., a
173 /// "reverse" conversion from N converted values back to one value of the
174 /// original type, using the given (forward) type conversion. If a given value
175 /// was mapped to a value of the same type (i.e., the conversion in the mapping
176 /// is an identity conversion), then the "converted" value is returned without
177 /// cast.
178 /// Note that these unrealized casts are different from source materializations
179 /// in that they are *always* inserted, even if they immediately fold away, such
180 /// that patterns always see valid intermediate IR, whereas materializations are
181 /// only used in the places where the unrealized casts *don't* fold away.
182 static SmallVector<Value>
184  const OneToNTypeMapping &typeConversion,
185  RewriterBase &rewriter) {
186  assert(typeConversion.getConvertedTypes() == convertedValues.getTypes());
187 
188  // Create unrealized cast op for each converted result of the op.
189  SmallVector<Value> recastValues;
190  TypeRange originalTypes = typeConversion.getOriginalTypes();
191  recastValues.reserve(originalTypes.size());
192  auto convertedValueIt = convertedValues.begin();
193  for (auto [idx, originalType] : llvm::enumerate(originalTypes)) {
194  TypeRange convertedTypes = typeConversion.getConvertedTypes(idx);
195  size_t numConvertedValues = convertedTypes.size();
196  if (isIdentityConversion(originalType, convertedTypes)) {
197  // Identity conversion: take result as is.
198  recastValues.push_back(*convertedValueIt);
199  } else {
200  // Non-identity conversion: cast back to source type.
201  ValueRange recastValue = buildUnrealizedCast(
202  rewriter, originalType,
203  ValueRange{convertedValueIt, convertedValueIt + numConvertedValues},
204  CastKind::Source);
205  assert(recastValue.size() == 1);
206  recastValues.push_back(recastValue.front());
207  }
208  convertedValueIt += numConvertedValues;
209  }
210 
211  return recastValues;
212 }
213 
214 void OneToNPatternRewriter::replaceOp(Operation *op, ValueRange newValues,
215  const OneToNTypeMapping &resultMapping) {
216  // Create a cast back to the original types and replace the results of the
217  // original op with those.
218  assert(newValues.size() == resultMapping.getConvertedTypes().size());
219  assert(op->getResultTypes() == resultMapping.getOriginalTypes());
222  SmallVector<Value> castResults =
223  buildUnrealizedBackwardsCasts(newValues, resultMapping, *this);
224  replaceOp(op, castResults);
225 }
226 
227 Block *OneToNPatternRewriter::applySignatureConversion(
228  Block *block, OneToNTypeMapping &argumentConversion) {
230 
231  // Split the block at the beginning to get a new block to use for the
232  // updated signature.
234  argumentConversion.convertLocations(block->getArguments(), locs);
235  Block *newBlock =
236  createBlock(block, argumentConversion.getConvertedTypes(), locs);
237  replaceAllUsesWith(block, newBlock);
238 
239  // Create necessary casts in new block.
240  SmallVector<Value> castResults;
241  for (auto [i, arg] : llvm::enumerate(block->getArguments())) {
242  TypeRange convertedTypes = argumentConversion.getConvertedTypes(i);
243  ValueRange newArgs =
244  argumentConversion.getConvertedValues(newBlock->getArguments(), i);
245  if (isIdentityConversion(arg.getType(), convertedTypes)) {
246  // Identity conversion: take argument as is.
247  assert(newArgs.size() == 1);
248  castResults.push_back(newArgs.front());
249  } else {
250  // Non-identity conversion: cast the converted arguments to the original
251  // type.
253  setInsertionPointToStart(newBlock);
254  ValueRange castResult = buildUnrealizedCast(*this, arg.getType(), newArgs,
256  assert(castResult.size() == 1);
257  castResults.push_back(castResult.front());
258  }
259  }
260 
261  // Merge old block into new block such that we only have the latter with the
262  // new signature.
263  mergeBlocks(block, newBlock, castResults);
264 
265  return newBlock;
266 }
267 
268 LogicalResult
269 OneToNConversionPattern::matchAndRewrite(Operation *op,
270  PatternRewriter &rewriter) const {
271  auto *typeConverter = getTypeConverter<OneToNTypeConverter>();
272 
273  // Construct conversion mapping for results.
274  Operation::result_type_range originalResultTypes = op->getResultTypes();
275  OneToNTypeMapping resultMapping(originalResultTypes);
276  if (failed(typeConverter->computeTypeMapping(originalResultTypes,
277  resultMapping)))
278  return failure();
279 
280  // Construct conversion mapping for operands.
281  Operation::operand_type_range originalOperandTypes = op->getOperandTypes();
282  OneToNTypeMapping operandMapping(originalOperandTypes);
283  if (failed(typeConverter->computeTypeMapping(originalOperandTypes,
284  operandMapping)))
285  return failure();
286 
287  // Cast operands to target types.
289  op->getOperands(), operandMapping, rewriter, CastKind::Target);
290 
291  // Create a `OneToNPatternRewriter` for the pattern, which provides additional
292  // functionality.
293  // TODO(ingomueller): I guess it would be better to use only one rewriter
294  // throughout the whole pass, but that would require to
295  // drive the pattern application ourselves, which is a lot
296  // of additional boilerplate code. This seems to work fine,
297  // so I leave it like this for the time being.
298  OneToNPatternRewriter oneToNPatternRewriter(rewriter.getContext(),
299  rewriter.getListener());
300  oneToNPatternRewriter.restoreInsertionPoint(rewriter.saveInsertionPoint());
301 
302  // Apply actual pattern.
303  if (failed(matchAndRewrite(op, oneToNPatternRewriter, operandMapping,
304  resultMapping, convertedOperands)))
305  return failure();
306 
307  return success();
308 }
309 
310 namespace mlir {
311 
312 // This function applies the provided patterns using
313 // `applyPatternsAndFoldGreedily` and then replaces all newly inserted
314 // `UnrealizedConversionCastOps` that haven't folded away. ("Backward" casts
315 // from target to source types inserted by a `OneToNConversionPattern` normally
316 // fold away with the "forward" casts from source to target types inserted by
317 // the next pattern.) To understand which casts are "newly inserted", all casts
318 // inserted by this pass are annotated with a string attribute that also
319 // documents which kind of the cast (source, argument, or target).
320 LogicalResult
322  const FrozenRewritePatternSet &patterns) {
323 #ifndef NDEBUG
324  // Remember existing unrealized casts. This data structure is only used in
325  // asserts; building it only for that purpose may be an overkill.
326  SmallSet<UnrealizedConversionCastOp, 4> existingCasts;
327  op->walk([&](UnrealizedConversionCastOp castOp) {
328  assert(!castOp->hasAttr(castKindAttrName));
329  existingCasts.insert(castOp);
330  });
331 #endif // NDEBUG
332 
333  // Apply provided conversion patterns.
334  if (failed(applyPatternsAndFoldGreedily(op, patterns))) {
335  emitError(op->getLoc()) << "failed to apply conversion patterns";
336  return failure();
337  }
338 
339  // Find all unrealized casts inserted by the pass that haven't folded away.
341  op->walk([&](UnrealizedConversionCastOp castOp) {
342  if (castOp->hasAttr(castKindAttrName)) {
343  assert(!existingCasts.contains(castOp));
344  worklist.push_back(castOp);
345  }
346  });
347 
348  // Replace new casts with user materializations.
349  IRRewriter rewriter(op->getContext());
350  for (UnrealizedConversionCastOp castOp : worklist) {
351  TypeRange resultTypes = castOp->getResultTypes();
352  ValueRange operands = castOp->getOperands();
353  StringRef castKind =
354  castOp->getAttrOfType<StringAttr>(castKindAttrName).getValue();
355  rewriter.setInsertionPoint(castOp);
356 
357 #ifndef NDEBUG
358  // Determine whether operands or results are already legal to test some
359  // assumptions for the different kind of materializations. These properties
360  // are only used it asserts and it may be overkill to compute them.
361  bool areOperandTypesLegal = llvm::all_of(
362  operands.getTypes(), [&](Type t) { return typeConverter.isLegal(t); });
363  bool areResultsTypesLegal = llvm::all_of(
364  resultTypes, [&](Type t) { return typeConverter.isLegal(t); });
365 #endif // NDEBUG
366 
367  // Add materialization and remember materialized results.
368  SmallVector<Value> materializedResults;
369  if (castKind == getCastKindName(CastKind::Target)) {
370  // Target materialization.
371  assert(!areOperandTypesLegal && areResultsTypesLegal &&
372  operands.size() == 1 && "found unexpected target cast");
373  std::optional<SmallVector<Value>> maybeResults =
374  typeConverter.materializeTargetConversion(
375  rewriter, castOp->getLoc(), resultTypes, operands.front());
376  if (!maybeResults) {
377  emitError(castOp->getLoc())
378  << "failed to create target materialization";
379  return failure();
380  }
381  materializedResults = maybeResults.value();
382  } else {
383  // Source and argument materializations.
384  assert(areOperandTypesLegal && !areResultsTypesLegal &&
385  resultTypes.size() == 1 && "found unexpected cast");
386  std::optional<Value> maybeResult;
387  if (castKind == getCastKindName(CastKind::Source)) {
388  // Source materialization.
389  maybeResult = typeConverter.materializeSourceConversion(
390  rewriter, castOp->getLoc(), resultTypes.front(),
391  castOp.getOperands());
392  } else {
393  // Argument materialization.
394  assert(castKind == getCastKindName(CastKind::Argument) &&
395  "unexpected value of cast kind attribute");
396  assert(llvm::all_of(operands, llvm::IsaPred<BlockArgument>));
397  maybeResult = typeConverter.materializeArgumentConversion(
398  rewriter, castOp->getLoc(), resultTypes.front(),
399  castOp.getOperands());
400  }
401  if (!maybeResult.has_value() || !maybeResult.value()) {
402  emitError(castOp->getLoc())
403  << "failed to create " << castKind << " materialization";
404  return failure();
405  }
406  materializedResults = {maybeResult.value()};
407  }
408 
409  // Replace the cast with the result of the materialization.
410  rewriter.replaceOp(castOp, materializedResults);
411  }
412 
413  return success();
414 }
415 
416 namespace {
417 class FunctionOpInterfaceSignatureConversion : public OneToNConversionPattern {
418 public:
419  FunctionOpInterfaceSignatureConversion(StringRef functionLikeOpName,
420  MLIRContext *ctx,
421  TypeConverter &converter)
422  : OneToNConversionPattern(converter, functionLikeOpName, /*benefit=*/1,
423  ctx) {}
424 
425  LogicalResult matchAndRewrite(Operation *op, OneToNPatternRewriter &rewriter,
426  const OneToNTypeMapping &operandMapping,
427  const OneToNTypeMapping &resultMapping,
428  ValueRange convertedOperands) const override {
429  auto funcOp = cast<FunctionOpInterface>(op);
430  auto *typeConverter = getTypeConverter<OneToNTypeConverter>();
431 
432  // Construct mapping for function arguments.
433  OneToNTypeMapping argumentMapping(funcOp.getArgumentTypes());
434  if (failed(typeConverter->computeTypeMapping(funcOp.getArgumentTypes(),
435  argumentMapping)))
436  return failure();
437 
438  // Construct mapping for function results.
439  OneToNTypeMapping funcResultMapping(funcOp.getResultTypes());
440  if (failed(typeConverter->computeTypeMapping(funcOp.getResultTypes(),
441  funcResultMapping)))
442  return failure();
443 
444  // Nothing to do if the op doesn't have any non-identity conversions for its
445  // operands or results.
446  if (!argumentMapping.hasNonIdentityConversion() &&
447  !funcResultMapping.hasNonIdentityConversion())
448  return failure();
449 
450  // Update the function signature in-place.
451  auto newType = FunctionType::get(rewriter.getContext(),
452  argumentMapping.getConvertedTypes(),
453  funcResultMapping.getConvertedTypes());
454  rewriter.modifyOpInPlace(op, [&] { funcOp.setType(newType); });
455 
456  // Update block signatures.
457  if (!funcOp.isExternal()) {
458  Region *region = &funcOp.getFunctionBody();
459  Block *block = &region->front();
460  rewriter.applySignatureConversion(block, argumentMapping);
461  }
462 
463  return success();
464  }
465 };
466 } // namespace
467 
469  StringRef functionLikeOpName, TypeConverter &converter,
470  RewritePatternSet &patterns) {
471  patterns.add<FunctionOpInterfaceSignatureConversion>(
472  functionLikeOpName, patterns.getContext(), converter);
473 }
474 } // namespace mlir
static void setInsertionPointAfter(OpBuilder &b, Value value)
static void setInsertionPointToStart(OpBuilder &builder, Value val)
static MlirBlock createBlock(const py::sequence &pyArgTypes, const std::optional< py::sequence > &pyArgLocs)
Create a block, using the current location context if no locations are specified.
Definition: IRCore.cpp:211
static ValueRange buildUnrealizedCast(OpBuilder &builder, TypeRange resultTypes, ValueRange inputs, CastKind kind)
Builds an UnrealizedConversionCastOp from the given inputs to the given result types.
static SmallVector< Value > buildUnrealizedForwardCasts(ValueRange originalValues, OneToNTypeMapping &conversion, RewriterBase &rewriter, CastKind kind)
Builds one UnrealizedConversionCastOp for each of the given original values using the respective targ...
StringRef getCastKindName(CastKind kind)
Mapping of enum values to string values.
static bool isIdentityConversion(Type originalType, TypeRange convertedTypes)
static SmallVector< Value > buildUnrealizedBackwardsCasts(ValueRange convertedValues, const OneToNTypeMapping &typeConversion, RewriterBase &rewriter)
Builds one UnrealizedConversionCastOp for each sequence of the given original values to one value of ...
static const char *const castKindAttrName
Attribute name that is used to annotate inserted unrealized casts with their kind (source,...
Block represents an ordered list of Operations.
Definition: Block.h:31
BlockArgListType getArguments()
Definition: Block.h:85
MLIRContext * getContext() const
Definition: Builders.h:55
Location getUnknownLoc()
Definition: Builders.cpp:27
This class represents a frozen set of patterns that can be processed by a pattern applicator.
This class coordinates rewriting a piece of IR outside of a pattern rewrite, providing a way to keep ...
Definition: PatternMatch.h:766
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
Base class for patterns with 1:N type conversions.
Specialization of PatternRewriter that OneToNConversionPatterns use.
Block * applySignatureConversion(Block *block, OneToNTypeMapping &argumentConversion)
Applies the given argument conversion to the given block.
Extends TypeConverter with 1:N target materializations.
std::optional< SmallVector< Value > > materializeTargetConversion(OpBuilder &builder, Location loc, TypeRange resultTypes, Value input) const
Applies one of the user-provided 1:N target materializations.
std::function< std::optional< SmallVector< Value > >(OpBuilder &, TypeRange, Value, Location)> OneToNMaterializationCallbackFn
Callback that expresses user-provided materialization logic from the given value to N values of the g...
Stores a 1:N mapping of types and provides several useful accessors.
TypeRange getConvertedTypes(unsigned originalTypeNo) const
Returns the list of types that corresponds to the original type at the given index.
void convertLocations(ValueRange originalValues, llvm::SmallVectorImpl< Location > &result) const
Fills the given result vector with as many copies of the lociation of each original value as the numb...
TypeRange getOriginalTypes() const
Returns the list of original types.
ValueRange getConvertedValues(ValueRange convertedValues, unsigned originalValueNo) const
Returns the slice of converted values that corresponds the original value at the given index.
RAII guard to reset the insertion point of the builder when destroyed.
Definition: Builders.h:351
This class helps build Operations.
Definition: Builders.h:210
InsertPoint saveInsertionPoint() const
Return a saved insertion point.
Definition: Builders.h:388
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition: Builders.h:401
void restoreInsertionPoint(InsertPoint ip)
Restore the insert point to a previously saved point.
Definition: Builders.h:393
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Definition: Builders.h:323
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:468
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Definition: Operation.h:793
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:216
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
operand_type_range getOperandTypes()
Definition: Operation.h:392
result_type_range getResultTypes()
Definition: Operation.h:423
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition: Operation.h:373
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Definition: PatternMatch.h:785
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
MLIRContext * getContext() const
Definition: PatternMatch.h:823
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
Definition: PatternMatch.h:847
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
Definition: PatternMatch.h:400
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
Definition: PatternMatch.h:630
Type conversion class.
bool isLegal(Type type) const
Return true if the given type is legal for this type converter, i.e.
Value materializeSourceConversion(OpBuilder &builder, Location loc, Type resultType, ValueRange inputs) const
Value materializeArgumentConversion(OpBuilder &builder, Location loc, Type resultType, ValueRange inputs) const
Materialize a conversion from a set of types into one result type by generating a cast sequence of so...
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:381
type_range getTypes() const
This class implements iteration on the types of a given range of values.
Definition: TypeRange.h:131
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
Location getLoc() const
Return the location of this value.
Definition: Value.cpp:26
Include the generated interface declarations.
Definition: CallGraph.h:229
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:285
llvm::PointerUnion< NamedAttribute *, NamedProperty *, NamedTypeConstraint * > Argument
Definition: Argument.h:64
Include the generated interface declarations.
LogicalResult applyPartialOneToNConversion(Operation *op, OneToNTypeConverter &typeConverter, const FrozenRewritePatternSet &patterns)
Applies the given set of patterns recursively on the given op and adds user materializations where ne...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
void populateOneToNFunctionOpInterfaceTypeConversionPattern(StringRef functionLikeOpName, TypeConverter &converter, RewritePatternSet &patterns)
Add a pattern to the given pattern list to convert the signature of a FunctionOpInterface op with the...
LogicalResult applyPatternsAndFoldGreedily(Region &region, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig(), bool *changed=nullptr)
Rewrite ops in the given region, which must be isolated from above, by repeatedly applying the highes...
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...