19#include "llvm/ADT/STLExtras.h"
20#include "llvm/Support/SHA1.h"
30 attrs.emplace_back(name, attr);
42 operands.push_back(operand);
54 types.push_back(type);
64 StringRef name = attr.getName().getValue();
65 if (llvm::is_contained(inherentNames, name))
66 inherentAttributes.push_back(attr);
70 if (inherentAttributes.empty())
72 if (failed(setProperties(
73 DictionaryAttr::get(state.
getContext(), inherentAttributes))))
74 llvm::report_fatal_error(
"Property conversion failed.");
82 assign(attributes.begin(), attributes.end());
88 dictionarySorted.setPointerAndInt(attributes,
true);
98 std::optional<NamedAttribute> duplicate =
99 DictionaryAttr::findDuplicate(attrs, isSorted());
103 dictionarySorted.setPointerAndInt(
nullptr,
true);
109 DictionaryAttr::sortInPlace(attrs);
110 dictionarySorted.setPointerAndInt(
nullptr,
true);
112 if (!dictionarySorted.getPointer())
113 dictionarySorted.setPointer(DictionaryAttr::getWithSorted(context, attrs));
114 return llvm::cast<DictionaryAttr>(dictionarySorted.getPointer());
120 dictionarySorted.setPointerAndInt(
nullptr,
true);
125 dictionarySorted.setInt(attrs.empty() || attrs.back() < newAttribute);
126 dictionarySorted.setPointer(
nullptr);
127 attrs.push_back(newAttribute);
132 auto it = findAttr(*
this, name);
133 return it.second ? it.first->getValue() :
Attribute();
136 auto it = findAttr(*
this, name);
137 return it.second ? it.first->getValue() :
Attribute();
142 auto it = findAttr(*
this, name);
143 return it.second ? *it.first : std::optional<NamedAttribute>();
146 auto it = findAttr(*
this, name);
147 return it.second ? *it.first : std::optional<NamedAttribute>();
153 assert(value &&
"attributes may never be null");
157 auto it = findAttr(*
this, name);
161 Attribute oldValue = it.first->getValue();
162 if (it.first->getValue() != value) {
163 it.first->setValue(value);
166 dictionarySorted.setPointer(
nullptr);
173 it = findAttr(*
this, name.strref());
174 attrs.insert(it.first, {name, value});
176 dictionarySorted.setPointer(
nullptr);
181 assert(value &&
"attributes may never be null");
182 return set(mlir::StringAttr::get(value.
getContext(), name), value);
190 dictionarySorted.setPointer(
nullptr);
195 auto it = findAttr(*
this, name);
196 return it.second ? eraseImpl(it.first) :
Attribute();
200 auto it = findAttr(*
this, name);
201 return it.second ? eraseImpl(it.first) :
Attribute();
206 assign(rhs.begin(), rhs.end());
232 for (std::unique_ptr<Region> &r :
regions)
233 this->regions.push_back(std::move(r));
245 propertiesDeleter(properties);
260 operands.append(newOperands.begin(), newOperands.end());
264 successors.append(newSuccessors.begin(), newSuccessors.end());
273 regions.push_back(std::move(region));
278 for (std::unique_ptr<Region> ®ion :
regions)
289 : isStorageDynamic(
false), operandStorage(trailingOperands) {
290 numOperands = capacity = values.size();
291 for (
unsigned i = 0; i < numOperands; ++i)
292 new (&operandStorage[i])
OpOperand(owner, values[i]);
297 operand.~OpOperand();
300 if (isStorageDynamic)
301 free(operandStorage);
308 for (
unsigned i = 0, e = values.size(); i != e; ++i)
309 storageOperands[i].set(values[i]);
318 unsigned newSize = operands.size();
319 if (newSize == length) {
321 for (
unsigned i = 0, e = length; i != e; ++i)
322 storageOperands[start + i].set(operands[i]);
327 if (newSize < length) {
333 auto storageOperands = resize(owner,
size() + (newSize - length));
336 unsigned rotateSize = storageOperands.size() - (start + length);
337 auto rbegin = storageOperands.rbegin();
338 std::rotate(rbegin, std::next(rbegin, newSize - length), rbegin + rotateSize);
341 for (
unsigned i = 0, e = operands.size(); i != e; ++i)
342 storageOperands[start + i].set(operands[i]);
348 assert((start + length) <= operands.size());
349 numOperands -= length;
352 if (start != numOperands) {
353 auto *indexIt = std::next(operands.begin(), start);
354 std::rotate(indexIt, std::next(indexIt, length), operands.end());
356 for (
unsigned i = 0; i != length; ++i)
362 assert(eraseIndices.size() == operands.size());
365 int firstErasedIndice = eraseIndices.find_first();
366 if (firstErasedIndice == -1)
370 numOperands = firstErasedIndice;
371 for (
unsigned i = firstErasedIndice + 1, e = operands.size(); i < e; ++i)
372 if (!eraseIndices.test(i))
373 operands[numOperands++] = std::move(operands[i]);
374 for (
OpOperand &operand : operands.drop_front(numOperands))
375 operand.~OpOperand();
385 if (newSize <= numOperands) {
388 for (
unsigned i = newSize; i != numOperands; ++i)
390 numOperands = newSize;
391 return origOperands.take_front(newSize);
395 if (newSize <= capacity) {
396 OpOperand *opBegin = origOperands.data();
397 for (
unsigned e = newSize; numOperands != e; ++numOperands)
398 new (&opBegin[numOperands])
OpOperand(owner);
403 unsigned newCapacity =
404 std::max(
unsigned(llvm::NextPowerOf2(capacity + 2)), newSize);
410 std::uninitialized_move(origOperands.begin(), origOperands.end(),
411 newOperands.begin());
414 for (
auto &operand : origOperands)
415 operand.~OpOperand();
418 for (
unsigned e = newSize; numOperands != e; ++numOperands)
419 new (&newOperands[numOperands])
OpOperand(owner);
422 if (isStorageDynamic)
423 free(operandStorage);
426 operandStorage = newOperandStorage;
427 capacity = newCapacity;
428 isStorageDynamic =
true;
441 assert(!empty() &&
"range must not be empty");
442 return base->getOperandNumber();
460 const OwnerT &owner =
getBase();
462 return OperandRange(owner.first, llvm::sum_of(sizeData));
465OperandRange OperandRangeRange::dereference(
const OwnerT &
object,
468 uint32_t startIndex = llvm::sum_of(sizeData.take_front(
index));
479 Operation *owner,
unsigned start,
unsigned length,
481 : owner(owner), start(start), length(length),
482 operandSegments(operandSegments) {
483 assert((start + length) <= owner->getNumOperands() &&
"invalid range");
491 opOperand.getOperandNumber(),
497 std::optional<OperandSegment> segment)
const {
498 assert((subStart + subLen) <= length &&
"invalid sub-range");
502 subSlice.operandSegments.push_back(*segment);
510 owner->insertOperands(start + length, values);
511 updateLength(length + values.size());
516 owner->setOperands(start, length, values);
517 if (length != values.size())
518 updateLength(values.size());
524 owner->setOperand(start, value);
526 owner->setOperands(start, length, value);
533 assert((subStart + subLen) <= length &&
"invalid sub-range");
536 owner->eraseOperands(start + subStart, subLen);
537 updateLength(length - subLen);
543 owner->eraseOperands(start, length);
550 return owner->getOperands().slice(start, length);
559 return owner->getOpOperands().slice(start, length);
568void MutableOperandRange::updateLength(
unsigned newLength) {
569 int32_t diff = int32_t(newLength) - int32_t(length);
574 auto attr = llvm::cast<DenseI32ArrayAttr>(segment.second.getValue());
576 segments[segment.first] += diff;
577 segment.second.setValue(
579 owner->
setInherentAttr(segment.second.getName(), segment.second.getValue());
584 assert(
index < length &&
"index is out of bounds");
585 return owner->getOpOperand(start +
index);
589 return owner->getOpOperands().slice(start, length).begin();
593 return owner->getOpOperands().slice(start, length).end();
603 OwnerT(operands, operandSegmentAttr), 0,
618 llvm::cast<DenseI32ArrayAttr>(
object.second.getValue());
619 uint32_t startIndex = llvm::sum_of(sizeData.take_front(
index));
620 return object.first.slice(
621 startIndex, *(sizeData.begin() +
index),
653 : it(end ? results.end() : results.begin()), endIt(results.end()) {
656 skipOverResultsWithNoUsers();
662 if (use != (*it).use_end())
664 if (use == (*it).use_end()) {
666 skipOverResultsWithNoUsers();
671void ResultRange::UseIterator::skipOverResultsWithNoUsers() {
672 while (it != endIt && (*it).use_empty())
680 use = (*it).use_begin();
706 if (
const auto *value = llvm::dyn_cast_if_present<const Value *>(owner))
707 return {value + index};
708 if (
auto *operand = llvm::dyn_cast_if_present<OpOperand *>(owner))
709 return {operand + index};
711 if (llvm::isa<
const Repeated<Value> *>(owner))
713 return cast<detail::OpResultImpl *>(owner)->getNextResultAtOffset(index);
716Value ValueRange::dereference_iterator(
const OwnerT &owner, ptrdiff_t
index) {
717 if (
const auto *value = llvm::dyn_cast_if_present<const Value *>(owner))
719 if (
auto *operand = llvm::dyn_cast_if_present<OpOperand *>(owner))
720 return operand[index].get();
722 llvm::dyn_cast_if_present<
const Repeated<Value> *>(owner))
723 return repeated->value();
724 return cast<detail::OpResultImpl *>(owner)->getNextResultAtOffset(index);
738 DictionaryAttr dictAttrs;
741 llvm::hash_code
hash =
754 size_t operandHash = hashOperands(op->
getOperand(0));
755 for (
auto operand : op->
getOperands().drop_front())
756 operandHash += hashOperands(operand);
757 hash = llvm::hash_combine(
hash, operandHash);
760 hash = llvm::hash_combine(
hash, hashOperands(operand));
775 checkCommutativeEquivalent) {
777 auto blocksEquivalent = [&](
Block &lBlock,
Block &rBlock) {
783 auto insertion = blocksMap.insert({&lBlock, &rBlock});
784 if (insertion.first->getSecond() != &rBlock)
788 llvm::zip(lBlock.
getArguments(), rBlock.getArguments())) {
789 Value curArg = std::get<0>(argPair);
790 Value otherArg = std::get<1>(argPair);
798 markEquivalent(curArg, otherArg);
804 markEquivalent, flags,
805 checkCommutativeEquivalent))
808 for (
auto successorsPair :
810 Block *curSuccessor = std::get<0>(successorsPair);
811 Block *otherSuccessor = std::get<1>(successorsPair);
812 auto insertion = blocksMap.insert({curSuccessor, otherSuccessor});
813 if (insertion.first->getSecond() != otherSuccessor)
818 return llvm::all_of_zip(lBlock, rBlock, opsEquivalent);
820 return llvm::all_of_zip(*lhs, *rhs, blocksEquivalent);
828 return success(lhsValue == rhsValue ||
834 if (lhsRange.size() != rhsRange.size())
838 auto lhsIt = lhsRange.begin();
839 auto rhsIt = rhsRange.begin();
840 for (; lhsIt != lhsRange.end(); ++lhsIt, ++rhsIt) {
844 if (lhsIt == lhsRange.end())
858 auto lhsSorted = sortValues({lhsIt, lhsRange.end()});
859 auto rhsSorted = sortValues({rhsIt, rhsRange.end()});
860 return success(lhsSorted == rhsSorted);
867 assert(insertion.first->second == rhsResult &&
868 "inconsistent OperationEquivalence state");
878 [&](
Value lhsValue,
Value rhsValue) -> LogicalResult {
895 checkCommutativeEquivalent) {
901 lhs->getRawDictionaryAttrs() != rhs->getRawDictionaryAttrs())
904 if (lhs->getName() != rhs->getName() ||
905 lhs->getNumRegions() != rhs->getNumRegions() ||
906 lhs->getNumSuccessors() != rhs->getNumSuccessors() ||
907 lhs->getNumOperands() != rhs->getNumOperands() ||
908 lhs->getNumResults() != rhs->getNumResults())
911 !(lhs->getName().compareOpProperties(lhs->getPropertiesStorage(),
912 rhs->getPropertiesStorage())))
920 auto lhsRange = lhs->getOperands();
921 auto rhsRange = rhs->getOperands();
922 if (failed(checkCommutativeEquivalent(lhsRange, rhsRange)))
926 for (
auto operandPair : llvm::zip(lhs->getOperands(), rhs->getOperands())) {
927 Value curArg = std::get<0>(operandPair);
928 Value otherArg = std::get<1>(operandPair);
929 if (curArg == otherArg)
933 if (failed(checkEquivalent(curArg, otherArg)))
939 for (
auto resultPair : llvm::zip(lhs->getResults(), rhs->getResults())) {
940 Value curArg = std::get<0>(resultPair);
941 Value otherArg = std::get<1>(resultPair);
945 markEquivalent(curArg, otherArg);
949 for (
auto regionPair : llvm::zip(lhs->getRegions(), rhs->getRegions()))
951 &std::get<0>(regionPair), &std::get<1>(regionPair), checkEquivalent,
952 markEquivalent, flags, checkCommutativeEquivalent))
964 [&](
Value lhsValue,
Value rhsValue) -> LogicalResult {
987 bool includeNested) {
991 auto addOperationToHash = [&](
Operation *op) {
1003 for (
Block &block : region) {
1023 topOp->
walk(addOperationToHash);
1025 addOperationToHash(topOp);
1027 hash = hasher.result();
getNumOperands() - 1))) return failure()
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
static size_t hash(const T &value)
Local helper to compute std::hash for a value.
false
Parses a map_entries map type from a string format back into its numeric value.
static void addDataToHash(llvm::SHA1 &hasher, const T &data)
#define MLIR_DEFINE_EXPLICIT_TYPE_ID(CLASS_NAME)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
virtual OptionalParseResult parseOptionalType(Type &result)=0
Parse an optional type.
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
This class represents an argument of a Block.
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
unsigned getNumArguments()
BlockArgListType getArguments()
This class represents a diagnostic that is inflight and set to be reported.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
const void * getAsOpaquePointer() const
Methods for supporting PointerLikeTypeTraits.
MLIRContext is the top-level object for a collection of MLIR operations.
This class represents a contiguous range of mutable operand ranges, e.g.
MutableOperandRange join() const
Flatten all of the sub ranges into a single contiguous mutable operand range.
MutableOperandRangeRange(const MutableOperandRange &operands, NamedAttribute operandSegmentAttr)
Construct a range given a parent set of operands, and an I32 tensor elements attribute containing the...
This class provides a mutable adaptor for a range of operands.
Operation * getOwner() const
Returns the owning operation.
OperandRange getAsOperandRange() const
Explicit conversion to an OperandRange.
void assign(ValueRange values)
Assign this range to the given values.
MutableOperandRange slice(unsigned subStart, unsigned subLen, std::optional< OperandSegment > segment=std::nullopt) const
Slice this range into a sub range, with the additional operand segment.
MutableArrayRef< OpOperand >::iterator end() const
void erase(unsigned subStart, unsigned subLen=1)
Erase the operands within the given sub-range.
void append(ValueRange values)
Append the given values to the range.
void clear()
Clear this range and erase all of the operands.
MutableArrayRef< OpOperand >::iterator begin() const
Iterators enumerate OpOperands.
MutableOperandRange(Operation *owner, unsigned start, unsigned length, ArrayRef< OperandSegment > operandSegments={})
Construct a new mutable range from the given operand, operand start index, and range length.
std::pair< unsigned, NamedAttribute > OperandSegment
A pair of a named attribute corresponding to an operand segment attribute, and the index within that ...
MutableOperandRangeRange split(NamedAttribute segmentSizes) const
Split this range into a set of contiguous subranges using the given elements attribute,...
OpOperand & operator[](unsigned index) const
Returns the OpOperand at the given index.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
std::optional< NamedAttribute > getNamed(StringRef name) const
Return the specified named attribute if present, std::nullopt otherwise.
void assign(const_iterator inStart, const_iterator inEnd)
Replaces the attributes with new list of attributes.
SmallVectorImpl< NamedAttribute >::const_iterator const_iterator
ArrayRef< NamedAttribute > getAttrs() const
Return all of the attributes on this operation.
DictionaryAttr getDictionary(MLIRContext *context) const
Return a dictionary attribute for the underlying dictionary.
void push_back(NamedAttribute newAttribute)
Add an attribute with the specified name.
Attribute get(StringAttr name) const
Return the specified attribute if present, null otherwise.
Attribute erase(StringAttr name)
Erase the attribute with the given name from the list.
std::optional< NamedAttribute > findDuplicate() const
Returns an entry with a duplicate name the list, if it exists, else returns std::nullopt.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
NamedAttrList & operator=(const SmallVectorImpl< NamedAttribute > &rhs)
NamedAttribute represents a combination of a name and an Attribute value.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual OptionalParseResult parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
This class represents an operand of an operation.
This is a value defined by a result of an operation.
This class adds property that the operation is commutative.
This class represents a contiguous range of operand ranges, e.g.
OperandRangeRange(OperandRange operands, Attribute operandSegments)
Construct a range given a parent set of operands, and an I32 elements attribute containing the sizes ...
OperandRange join() const
Flatten all of the sub ranges into a single contiguous operand range.
This class implements the operand iterators for the Operation class.
unsigned getBeginOperandIndex() const
Return the operand index of the first element of this range.
OperandRangeRange split(DenseI32ArrayAttr segmentSizes) const
Split this range into a set of contiguous subranges using the given elements attribute,...
OperationFingerPrint(Operation *topOp, bool includeNested=true)
Operation is the basic unit of execution within MLIR.
PropertyRef getPropertiesStorage()
Return a generic (but typed) reference to the property type storage.
void setInherentAttr(StringAttr name, Attribute value)
Set an inherent attribute by name.
Value getOperand(unsigned idx)
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
unsigned getNumSuccessors()
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
DictionaryAttr getRawDictionaryAttrs()
Return all attributes that are not stored as properties.
unsigned getNumOperands()
OperationName getName()
The name of an operation is the key identifier for it.
LogicalResult setPropertiesFromAttribute(Attribute attr, function_ref< InFlightDiagnostic()> emitError)
Set the properties from the provided attribute.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
result_type_range getResultTypes()
operand_range getOperands()
Returns an iterator on the underlying Value's.
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),...
Block * getSuccessor(unsigned index)
SuccessorRange getSuccessors()
result_range getResults()
llvm::hash_code hashProperties()
Compute a hash for the op properties (if any).
This class implements Optional functionality for ParseResult.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
This class implements a use iterator for a range of operation results.
UseIterator(ResultRange results, bool end=false)
Initialize the UseIterator.
UseIterator & operator++()
This class implements the result iterators for the Operation class.
std::enable_if_t<!std::is_convertible< ValuesT, Operation * >::value > replaceUsesWithIf(ValuesT &&values, function_ref< bool(OpOperand &)> shouldReplace)
Replace uses of results of this range with the provided 'values' if the given callback returns true.
iterator_range< user_iterator > user_range
use_range getUses() const
Returns a range of all uses of results within this range, which is useful for iterating over all uses...
use_iterator use_begin() const
user_range getUsers()
Returns a range of all users.
ValueUserIterator< use_iterator, OpOperand > user_iterator
ResultRange(OpResult result)
use_iterator use_end() const
user_iterator user_begin()
iterator_range< use_iterator > use_range
std::enable_if_t<!std::is_convertible< ValuesT, Operation * >::value > replaceAllUsesWith(ValuesT &&values)
Replace all uses of results of this range with the provided 'values'.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
PointerUnion< const Value *, OpOperand *, detail::OpResultImpl *, const Repeated< Value > * > OwnerT
The type representing the owner of a ValueRange.
ValueRange(Arg &&arg LLVM_LIFETIME_BOUND)
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
void * getAsOpaquePointer() const
Methods for supporting PointerLikeTypeTraits.
Location getLoc() const
Return the location of this value.
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
void eraseOperands(unsigned start, unsigned length)
Erase the operands held by the storage within the given range.
MutableArrayRef< OpOperand > getOperands()
Get the operation operands held by the storage.
unsigned size()
Return the number of operands held in the storage.
void setOperands(Operation *owner, ValueRange values)
Replace the operands contained in the storage with the ones provided in 'values'.
OperandStorage(Operation *owner, OpOperand *trailingOperands, ValueRange values)
The OpAsmOpInterface, see OpAsmInterface.td for more details.
void appendAttributeProperty(llvm::SmallVectorImpl< NamedAttribute > &attrs, StringRef name, Attribute attr)
Append a present attribute-backed property to a dictionary's attributes.
ParseResult parseOptionalTypeInto(AsmParser &parser, SmallVectorImpl< Type > &types)
void splitPropertiesAndDiscardableAttributes(OperationState &state, ArrayRef< NamedAttribute > attributes, ArrayRef< StringRef > inherentNames, llvm::function_ref< LogicalResult(DictionaryAttr)> setProperties)
Route legacy builder attributes to either the operation's properties or its discardable attribute dic...
ParseResult parseOptionalOperandInto(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands)
Parse an optional operand or type into a generated parser's storage.
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
detail::DenseArrayAttrImpl< int32_t > DenseI32ArrayAttr
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
llvm::function_ref< Fn > function_ref
LogicalResult checkEquivalent(Value lhsValue, Value rhsValue)
void markEquivalent(Value lhsResult, Value rhsResult)
LogicalResult checkCommutativeEquivalent(ValueRange lhsRange, ValueRange rhsRange)
DenseMap< Value, Value > equivalentValues
Structure used by default as a "marker" when no "Properties" are set on an Operation.
This is the representation of an operand reference.
static bool isRegionEquivalentTo(Region *lhs, Region *rhs, function_ref< LogicalResult(Value, Value)> checkEquivalent, function_ref< void(Value, Value)> markEquivalent, OperationEquivalence::Flags flags, function_ref< LogicalResult(ValueRange, ValueRange)> checkCommutativeEquivalent=nullptr)
Compare two regions (including their subregions) and return if they are equivalent.
static bool isEquivalentTo(Operation *lhs, Operation *rhs, function_ref< LogicalResult(Value, Value)> checkEquivalent, function_ref< void(Value, Value)> markEquivalent=nullptr, Flags flags=Flags::None, function_ref< LogicalResult(ValueRange, ValueRange)> checkCommutativeEquivalent=nullptr)
Compare two operations (including their regions) and return if they are equivalent.
static llvm::hash_code computeHash(Operation *op, function_ref< llvm::hash_code(Value)> hashOperands=[](Value v) { return hash_value(v);}, function_ref< llvm::hash_code(Value)> hashResults=[](Value v) { return hash_value(v);}, Flags flags=Flags::None)
Compute a hash for the given operation.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
SmallVector< Block *, 1 > successors
Successors of this operation and their respective operands.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.
void addRegions(MutableArrayRef< std::unique_ptr< Region > > regions)
Take ownership of a set of regions that should be attached to the Operation.
MLIRContext * getContext() const
Get the context held by this operation state.
SmallVector< std::unique_ptr< Region >, 1 > regions
Regions that the op will hold.
OperationState(Location location, StringRef name)
Attribute propertiesAttr
This Attribute is used to opaquely construct the properties of the operation.
SmallVector< Type, 4 > types
Types of the results of this operation.
Region * addRegion()
Create a region that should be attached to the operation.
LogicalResult setProperties(Operation *op, function_ref< InFlightDiagnostic()> emitError) const