MLIR  17.0.0git
Async.cpp
Go to the documentation of this file.
1 //===- Async.cpp - MLIR Async Operations ----------------------------------===//
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 
10 
13 #include "mlir/IR/IRMapping.h"
14 #include "llvm/ADT/MapVector.h"
15 #include "llvm/ADT/TypeSwitch.h"
16 
17 using namespace mlir;
18 using namespace mlir::async;
19 
20 #include "mlir/Dialect/Async/IR/AsyncOpsDialect.cpp.inc"
21 
22 constexpr StringRef AsyncDialect::kAllowedToBlockAttrName;
23 
24 void AsyncDialect::initialize() {
25  addOperations<
26 #define GET_OP_LIST
27 #include "mlir/Dialect/Async/IR/AsyncOps.cpp.inc"
28  >();
29  addTypes<
30 #define GET_TYPEDEF_LIST
31 #include "mlir/Dialect/Async/IR/AsyncOpsTypes.cpp.inc"
32  >();
33 }
34 
35 //===----------------------------------------------------------------------===//
36 // YieldOp
37 //===----------------------------------------------------------------------===//
38 
40  // Get the underlying value types from async values returned from the
41  // parent `async.execute` operation.
42  auto executeOp = (*this)->getParentOfType<ExecuteOp>();
43  auto types =
44  llvm::map_range(executeOp.getBodyResults(), [](const OpResult &result) {
45  return result.getType().cast<ValueType>().getValueType();
46  });
47 
48  if (getOperandTypes() != types)
49  return emitOpError("operand types do not match the types returned from "
50  "the parent ExecuteOp");
51 
52  return success();
53 }
54 
56 YieldOp::getMutableSuccessorOperands(std::optional<unsigned> index) {
57  return getOperandsMutable();
58 }
59 
60 //===----------------------------------------------------------------------===//
61 /// ExecuteOp
62 //===----------------------------------------------------------------------===//
63 
64 constexpr char kOperandSegmentSizesAttr[] = "operand_segment_sizes";
65 
67 ExecuteOp::getSuccessorEntryOperands(std::optional<unsigned> index) {
68  assert(index && *index == 0 && "invalid region index");
69  return getBodyOperands();
70 }
71 
72 bool ExecuteOp::areTypesCompatible(Type lhs, Type rhs) {
73  const auto getValueOrTokenType = [](Type type) {
74  if (auto value = type.dyn_cast<ValueType>())
75  return value.getValueType();
76  return type;
77  };
78  return getValueOrTokenType(lhs) == getValueOrTokenType(rhs);
79 }
80 
81 void ExecuteOp::getSuccessorRegions(std::optional<unsigned> index,
84  // The `body` region branch back to the parent operation.
85  if (index) {
86  assert(*index == 0 && "invalid region index");
87  regions.push_back(RegionSuccessor(getBodyResults()));
88  return;
89  }
90 
91  // Otherwise the successor is the body region.
92  regions.push_back(
93  RegionSuccessor(&getBodyRegion(), getBodyRegion().getArguments()));
94 }
95 
96 void ExecuteOp::build(OpBuilder &builder, OperationState &result,
97  TypeRange resultTypes, ValueRange dependencies,
98  ValueRange operands, BodyBuilderFn bodyBuilder) {
99 
100  result.addOperands(dependencies);
101  result.addOperands(operands);
102 
103  // Add derived `operand_segment_sizes` attribute based on parsed operands.
104  int32_t numDependencies = dependencies.size();
105  int32_t numOperands = operands.size();
106  auto operandSegmentSizes =
107  builder.getDenseI32ArrayAttr({numDependencies, numOperands});
108  result.addAttribute(kOperandSegmentSizesAttr, operandSegmentSizes);
109 
110  // First result is always a token, and then `resultTypes` wrapped into
111  // `async.value`.
112  result.addTypes({TokenType::get(result.getContext())});
113  for (Type type : resultTypes)
114  result.addTypes(ValueType::get(type));
115 
116  // Add a body region with block arguments as unwrapped async value operands.
117  Region *bodyRegion = result.addRegion();
118  bodyRegion->push_back(new Block);
119  Block &bodyBlock = bodyRegion->front();
120  for (Value operand : operands) {
121  auto valueType = operand.getType().dyn_cast<ValueType>();
122  bodyBlock.addArgument(valueType ? valueType.getValueType()
123  : operand.getType(),
124  operand.getLoc());
125  }
126 
127  // Create the default terminator if the builder is not provided and if the
128  // expected result is empty. Otherwise, leave this to the caller
129  // because we don't know which values to return from the execute op.
130  if (resultTypes.empty() && !bodyBuilder) {
131  OpBuilder::InsertionGuard guard(builder);
132  builder.setInsertionPointToStart(&bodyBlock);
133  builder.create<async::YieldOp>(result.location, ValueRange());
134  } else if (bodyBuilder) {
135  OpBuilder::InsertionGuard guard(builder);
136  builder.setInsertionPointToStart(&bodyBlock);
137  bodyBuilder(builder, result.location, bodyBlock.getArguments());
138  }
139 }
140 
142  // [%tokens,...]
143  if (!getDependencies().empty())
144  p << " [" << getDependencies() << "]";
145 
146  // (%value as %unwrapped: !async.value<!arg.type>, ...)
147  if (!getBodyOperands().empty()) {
148  p << " (";
149  Block *entry = getBodyRegion().empty() ? nullptr : &getBodyRegion().front();
150  llvm::interleaveComma(
151  getBodyOperands(), p, [&, n = 0](Value operand) mutable {
152  Value argument = entry ? entry->getArgument(n++) : Value();
153  p << operand << " as " << argument << ": " << operand.getType();
154  });
155  p << ")";
156  }
157 
158  // -> (!async.value<!return.type>, ...)
159  p.printOptionalArrowTypeList(llvm::drop_begin(getResultTypes()));
160  p.printOptionalAttrDictWithKeyword((*this)->getAttrs(),
161  {kOperandSegmentSizesAttr});
162  p << ' ';
163  p.printRegion(getBodyRegion(), /*printEntryBlockArgs=*/false);
164 }
165 
166 ParseResult ExecuteOp::parse(OpAsmParser &parser, OperationState &result) {
167  MLIRContext *ctx = result.getContext();
168 
169  // Sizes of parsed variadic operands, will be updated below after parsing.
170  int32_t numDependencies = 0;
171 
172  auto tokenTy = TokenType::get(ctx);
173 
174  // Parse dependency tokens.
175  if (succeeded(parser.parseOptionalLSquare())) {
177  if (parser.parseOperandList(tokenArgs) ||
178  parser.resolveOperands(tokenArgs, tokenTy, result.operands) ||
179  parser.parseRSquare())
180  return failure();
181 
182  numDependencies = tokenArgs.size();
183  }
184 
185  // Parse async value operands (%value as %unwrapped : !async.value<!type>).
188  SmallVector<Type, 4> valueTypes;
189 
190  // Parse a single instance of `%value as %unwrapped : !async.value<!type>`.
191  auto parseAsyncValueArg = [&]() -> ParseResult {
192  if (parser.parseOperand(valueArgs.emplace_back()) ||
193  parser.parseKeyword("as") ||
194  parser.parseArgument(unwrappedArgs.emplace_back()) ||
195  parser.parseColonType(valueTypes.emplace_back()))
196  return failure();
197 
198  auto valueTy = valueTypes.back().dyn_cast<ValueType>();
199  unwrappedArgs.back().type = valueTy ? valueTy.getValueType() : Type();
200  return success();
201  };
202 
203  auto argsLoc = parser.getCurrentLocation();
205  parseAsyncValueArg) ||
206  parser.resolveOperands(valueArgs, valueTypes, argsLoc, result.operands))
207  return failure();
208 
209  int32_t numOperands = valueArgs.size();
210 
211  // Add derived `operand_segment_sizes` attribute based on parsed operands.
212  auto operandSegmentSizes =
213  parser.getBuilder().getDenseI32ArrayAttr({numDependencies, numOperands});
214  result.addAttribute(kOperandSegmentSizesAttr, operandSegmentSizes);
215 
216  // Parse the types of results returned from the async execute op.
217  SmallVector<Type, 4> resultTypes;
218  NamedAttrList attrs;
219  if (parser.parseOptionalArrowTypeList(resultTypes) ||
220  // Async execute first result is always a completion token.
221  parser.addTypeToList(tokenTy, result.types) ||
222  parser.addTypesToList(resultTypes, result.types) ||
223  // Parse operation attributes.
224  parser.parseOptionalAttrDictWithKeyword(attrs))
225  return failure();
226 
227  result.addAttributes(attrs);
228 
229  // Parse asynchronous region.
230  Region *body = result.addRegion();
231  return parser.parseRegion(*body, /*arguments=*/unwrappedArgs);
232 }
233 
234 LogicalResult ExecuteOp::verifyRegions() {
235  // Unwrap async.execute value operands types.
236  auto unwrappedTypes = llvm::map_range(getBodyOperands(), [](Value operand) {
237  return operand.getType().cast<ValueType>().getValueType();
238  });
239 
240  // Verify that unwrapped argument types matches the body region arguments.
241  if (getBodyRegion().getArgumentTypes() != unwrappedTypes)
242  return emitOpError("async body region argument types do not match the "
243  "execute operation arguments types");
244 
245  return success();
246 }
247 
248 //===----------------------------------------------------------------------===//
249 /// CreateGroupOp
250 //===----------------------------------------------------------------------===//
251 
252 LogicalResult CreateGroupOp::canonicalize(CreateGroupOp op,
253  PatternRewriter &rewriter) {
254  // Find all `await_all` users of the group.
255  llvm::SmallVector<AwaitAllOp> awaitAllUsers;
256 
257  auto isAwaitAll = [&](Operation *op) -> bool {
258  if (AwaitAllOp awaitAll = dyn_cast<AwaitAllOp>(op)) {
259  awaitAllUsers.push_back(awaitAll);
260  return true;
261  }
262  return false;
263  };
264 
265  // Check if all users of the group are `await_all` operations.
266  if (!llvm::all_of(op->getUsers(), isAwaitAll))
267  return failure();
268 
269  // If group is only awaited without adding anything to it, we can safely erase
270  // the create operation and all users.
271  for (AwaitAllOp awaitAll : awaitAllUsers)
272  rewriter.eraseOp(awaitAll);
273  rewriter.eraseOp(op);
274 
275  return success();
276 }
277 
278 //===----------------------------------------------------------------------===//
279 /// AwaitOp
280 //===----------------------------------------------------------------------===//
281 
282 void AwaitOp::build(OpBuilder &builder, OperationState &result, Value operand,
283  ArrayRef<NamedAttribute> attrs) {
284  result.addOperands({operand});
285  result.attributes.append(attrs.begin(), attrs.end());
286 
287  // Add unwrapped async.value type to the returned values types.
288  if (auto valueType = operand.getType().dyn_cast<ValueType>())
289  result.addTypes(valueType.getValueType());
290 }
291 
292 static ParseResult parseAwaitResultType(OpAsmParser &parser, Type &operandType,
293  Type &resultType) {
294  if (parser.parseType(operandType))
295  return failure();
296 
297  // Add unwrapped async.value type to the returned values types.
298  if (auto valueType = operandType.dyn_cast<ValueType>())
299  resultType = valueType.getValueType();
300 
301  return success();
302 }
303 
305  Type operandType, Type resultType) {
306  p << operandType;
307 }
308 
310  Type argType = getOperand().getType();
311 
312  // Awaiting on a token does not have any results.
313  if (argType.isa<TokenType>() && !getResultTypes().empty())
314  return emitOpError("awaiting on a token must have empty result");
315 
316  // Awaiting on a value unwraps the async value type.
317  if (auto value = argType.dyn_cast<ValueType>()) {
318  if (*getResultType() != value.getValueType())
319  return emitOpError() << "result type " << *getResultType()
320  << " does not match async value type "
321  << value.getValueType();
322  }
323 
324  return success();
325 }
326 
327 //===----------------------------------------------------------------------===//
328 // FuncOp
329 //===----------------------------------------------------------------------===//
330 
331 void FuncOp::build(OpBuilder &builder, OperationState &state, StringRef name,
332  FunctionType type, ArrayRef<NamedAttribute> attrs,
333  ArrayRef<DictionaryAttr> argAttrs) {
335  builder.getStringAttr(name));
336  state.addAttribute(getFunctionTypeAttrName(state.name), TypeAttr::get(type));
337 
338  state.attributes.append(attrs.begin(), attrs.end());
339  state.addRegion();
340 
341  if (argAttrs.empty())
342  return;
343  assert(type.getNumInputs() == argAttrs.size());
345  builder, state, argAttrs, /*resultAttrs=*/std::nullopt,
346  getArgAttrsAttrName(state.name), getResAttrsAttrName(state.name));
347 }
348 
349 ParseResult FuncOp::parse(OpAsmParser &parser, OperationState &result) {
350  auto buildFuncType =
351  [](Builder &builder, ArrayRef<Type> argTypes, ArrayRef<Type> results,
353  std::string &) { return builder.getFunctionType(argTypes, results); };
354 
356  parser, result, /*allowVariadic=*/false,
357  getFunctionTypeAttrName(result.name), buildFuncType,
358  getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
359 }
360 
361 void FuncOp::print(OpAsmPrinter &p) {
363  p, *this, /*isVariadic=*/false, getFunctionTypeAttrName(),
364  getArgAttrsAttrName(), getResAttrsAttrName());
365 }
366 
367 /// Check that the result type of async.func is not void and must be
368 /// some async token or async values.
370  auto resultTypes = getResultTypes();
371  if (resultTypes.empty())
372  return emitOpError()
373  << "result is expected to be at least of size 1, but got "
374  << resultTypes.size();
375 
376  for (unsigned i = 0, e = resultTypes.size(); i != e; ++i) {
377  auto type = resultTypes[i];
378  if (!type.isa<TokenType>() && !type.isa<ValueType>())
379  return emitOpError() << "result type must be async value type or async "
380  "token type, but got "
381  << type;
382  // We only allow AsyncToken appear as the first return value
383  if (type.isa<TokenType>() && i != 0) {
384  return emitOpError()
385  << " results' (optional) async token type is expected "
386  "to appear as the 1st return value, but got "
387  << i + 1;
388  }
389  }
390 
391  return success();
392 }
393 
394 //===----------------------------------------------------------------------===//
395 /// CallOp
396 //===----------------------------------------------------------------------===//
397 
398 LogicalResult CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
399  // Check that the callee attribute was specified.
400  auto fnAttr = (*this)->getAttrOfType<FlatSymbolRefAttr>("callee");
401  if (!fnAttr)
402  return emitOpError("requires a 'callee' symbol reference attribute");
403  FuncOp fn = symbolTable.lookupNearestSymbolFrom<FuncOp>(*this, fnAttr);
404  if (!fn)
405  return emitOpError() << "'" << fnAttr.getValue()
406  << "' does not reference a valid async function";
407 
408  // Verify that the operand and result types match the callee.
409  auto fnType = fn.getFunctionType();
410  if (fnType.getNumInputs() != getNumOperands())
411  return emitOpError("incorrect number of operands for callee");
412 
413  for (unsigned i = 0, e = fnType.getNumInputs(); i != e; ++i)
414  if (getOperand(i).getType() != fnType.getInput(i))
415  return emitOpError("operand type mismatch: expected operand type ")
416  << fnType.getInput(i) << ", but provided "
417  << getOperand(i).getType() << " for operand number " << i;
418 
419  if (fnType.getNumResults() != getNumResults())
420  return emitOpError("incorrect number of results for callee");
421 
422  for (unsigned i = 0, e = fnType.getNumResults(); i != e; ++i)
423  if (getResult(i).getType() != fnType.getResult(i)) {
424  auto diag = emitOpError("result type mismatch at index ") << i;
425  diag.attachNote() << " op result types: " << getResultTypes();
426  diag.attachNote() << "function result types: " << fnType.getResults();
427  return diag;
428  }
429 
430  return success();
431 }
432 
433 FunctionType CallOp::getCalleeType() {
434  return FunctionType::get(getContext(), getOperandTypes(), getResultTypes());
435 }
436 
437 //===----------------------------------------------------------------------===//
438 /// ReturnOp
439 //===----------------------------------------------------------------------===//
440 
442  auto funcOp = (*this)->getParentOfType<FuncOp>();
443  ArrayRef<Type> resultTypes = funcOp.isStateful()
444  ? funcOp.getResultTypes().drop_front()
445  : funcOp.getResultTypes();
446  // Get the underlying value types from async types returned from the
447  // parent `async.func` operation.
448  auto types = llvm::map_range(resultTypes, [](const Type &result) {
449  return result.cast<ValueType>().getValueType();
450  });
451 
452  if (getOperandTypes() != types)
453  return emitOpError("operand types do not match the types returned from "
454  "the parent FuncOp");
455 
456  return success();
457 }
458 
459 //===----------------------------------------------------------------------===//
460 // TableGen'd op method definitions
461 //===----------------------------------------------------------------------===//
462 
463 #define GET_OP_CLASSES
464 #include "mlir/Dialect/Async/IR/AsyncOps.cpp.inc"
465 
466 //===----------------------------------------------------------------------===//
467 // TableGen'd type method definitions
468 //===----------------------------------------------------------------------===//
469 
470 #define GET_TYPEDEF_CLASSES
471 #include "mlir/Dialect/Async/IR/AsyncOpsTypes.cpp.inc"
472 
473 void ValueType::print(AsmPrinter &printer) const {
474  printer << "<";
475  printer.printType(getValueType());
476  printer << '>';
477 }
478 
479 Type ValueType::parse(mlir::AsmParser &parser) {
480  Type ty;
481  if (parser.parseLess() || parser.parseType(ty) || parser.parseGreater()) {
482  parser.emitError(parser.getNameLoc(), "failed to parse async value type");
483  return Type();
484  }
485  return ValueType::get(ty);
486 }
static ParseResult parseAwaitResultType(OpAsmParser &parser, Type &operandType, Type &resultType)
Definition: Async.cpp:292
constexpr char kOperandSegmentSizesAttr[]
ExecuteOp.
Definition: Async.cpp:64
static void printAwaitResultType(OpAsmPrinter &p, Operation *op, Type operandType, Type resultType)
Definition: Async.cpp:304
static std::string diag(const llvm::Value &value)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
@ OptionalParen
Parens supporting zero or more operands, or nothing.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseRSquare()=0
Parse a ] token.
ParseResult addTypeToList(Type type, SmallVectorImpl< Type > &result)
Add the specified type to the end of the specified type list and return success.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual ParseResult parseColonType(Type &result)=0
Parse a colon followed by a type.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
ParseResult addTypesToList(ArrayRef< Type > types, SmallVectorImpl< Type > &result)
Add the specified types to the end of the specified type list and return success.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseOptionalArrowTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional arrow followed by a type list.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printType(Type type)
void printOptionalArrowTypeList(TypeRange &&types)
Print an optional arrow followed by a type list.
Block represents an ordered list of Operations.
Definition: Block.h:30
bool empty()
Definition: Block.h:137
BlockArgument getArgument(unsigned i)
Definition: Block.h:118
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition: Block.cpp:141
BlockArgListType getArguments()
Definition: Block.h:76
This class is a general helper class for creating context-global objects like types,...
Definition: Builders.h:50
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
Definition: Builders.cpp:165
FunctionType getFunctionType(TypeRange inputs, TypeRange results)
Definition: Builders.cpp:93
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:255
A symbol reference with a reference path containing a single element.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
This class provides a mutable adaptor for a range of operands.
Definition: ValueRange.h:115
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region &region, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult parseArgument(Argument &result, bool allowType=false, bool allowAttrs=false)=0
Parse a single argument with the following syntax:
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printOptionalAttrDictWithKeyword(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary prefixed with 'attribute...
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
RAII guard to reset the insertion point of the builder when destroyed.
Definition: Builders.h:329
This class helps build Operations.
Definition: Builders.h:202
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Definition: Builders.h:412
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:432
This is a value defined by a result of an operation.
Definition: Value.h:442
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:42
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:75
This class represents success/failure for parsing-like operations that find it important to chain tog...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Definition: PatternMatch.h:668
This class represents a successor of a region.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
void push_back(Block *block)
Definition: Region.h:61
Block & front()
Definition: Region.h:65
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
This class represents a collection of SymbolTables.
Definition: SymbolTable.h:248
Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
Definition: SymbolTable.h:59
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
U cast() const
Definition: Types.h:321
U dyn_cast() const
Definition: Types.h:311
bool isa() const
Definition: Types.h:301
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:370
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
A named class for passing around the variadic flag.
void addArgAndResultAttrs(Builder &builder, OperationState &result, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< DictionaryAttr > resultAttrs, StringAttr argAttrsName, StringAttr resAttrsName)
Adds argument and result attributes, provided as argAttrs and resultAttrs arguments,...
void printFunctionOp(OpAsmPrinter &p, FunctionOpInterface op, bool isVariadic, StringRef typeAttrName, StringAttr argAttrsName, StringAttr resAttrsName)
Printer implementation for function-like operations.
ParseResult parseFunctionOp(OpAsmParser &parser, OperationState &result, bool allowVariadic, StringAttr typeAttrName, FuncTypeBuilder funcTypeBuilder, StringAttr argAttrsName, StringAttr resAttrsName)
Parser implementation for function-like operations.
This header declares functions that assit transformations in the MemRef dialect.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:68
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:374
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
This represents an operation in an abstracted form, suitable for use with the builder APIs.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addTypes(ArrayRef< Type > newTypes)
NamedAttrList attributes
MLIRContext * getContext() const
Get the context held by this operation state.
SmallVector< Type, 4 > types
Types of the results of this operation.
Region * addRegion()
Create a region that should be attached to the operation.