18 #include "llvm/ADT/BitVector.h" 28 assign(attributes.begin(), attributes.end());
34 dictionarySorted.setPointerAndInt(attributes,
true);
45 DictionaryAttr::findDuplicate(attrs, isSorted());
49 dictionarySorted.setPointerAndInt(
nullptr,
true);
55 DictionaryAttr::sortInPlace(attrs);
56 dictionarySorted.setPointerAndInt(
nullptr,
true);
58 if (!dictionarySorted.getPointer())
59 dictionarySorted.setPointer(DictionaryAttr::getWithSorted(context, attrs));
60 return dictionarySorted.getPointer().cast<DictionaryAttr>();
71 dictionarySorted.setPointerAndInt(
nullptr,
true);
76 dictionarySorted.setInt(attrs.empty() || attrs.back() < newAttribute);
77 dictionarySorted.setPointer(
nullptr);
78 attrs.push_back(newAttribute);
83 auto it = findAttr(*
this, name);
84 return it.second ? it.first->getValue() :
Attribute();
87 auto it = findAttr(*
this, name);
88 return it.second ? it.first->getValue() :
Attribute();
93 auto it = findAttr(*
this, name);
97 auto it = findAttr(*
this, name);
104 assert(value &&
"attributes may never be null");
108 auto it = findAttr(*
this, name);
112 Attribute oldValue = it.first->getValue();
113 if (it.first->getValue() !=
value) {
114 it.first->setValue(value);
117 dictionarySorted.setPointer(
nullptr);
124 it = findAttr(*
this, name.strref());
125 attrs.insert(it.first, {name, value});
127 dictionarySorted.setPointer(
nullptr);
132 assert(value &&
"attributes may never be null");
133 return set(mlir::StringAttr::get(value.
getContext(), name), value);
141 dictionarySorted.setPointer(
nullptr);
146 auto it = findAttr(*
this, name);
147 return it.second ? eraseImpl(it.first) :
Attribute();
151 auto it = findAttr(*
this, name);
152 return it.second ? eraseImpl(it.first) :
Attribute();
157 assign(rhs.begin(), rhs.end());
168 : location(location), name(name, location->getContext()) {}
171 : location(location), name(name) {}
178 : location(location), name(name),
179 operands(operands.begin(), operands.end()),
180 types(types.begin(), types.end()),
181 attributes(attributes.begin(), attributes.end()),
182 successors(successors.begin(), successors.end()) {
183 for (std::unique_ptr<Region> &r :
regions)
184 this->regions.push_back(std::move(r));
192 operands, types, attributes, successors,
regions) {}
195 operands.append(newOperands.begin(), newOperands.end());
199 successors.append(newSuccessors.begin(), newSuccessors.end());
208 regions.push_back(std::move(region));
213 for (std::unique_ptr<Region> ®ion :
regions)
224 : isStorageDynamic(false), operandStorage(trailingOperands) {
225 numOperands = capacity = values.size();
226 for (
unsigned i = 0; i < numOperands; ++i)
227 new (&operandStorage[i])
OpOperand(owner, values[i]);
232 operand.~OpOperand();
235 if (isStorageDynamic)
236 free(operandStorage);
243 for (
unsigned i = 0, e = values.size(); i != e; ++i)
244 storageOperands[i].
set(values[i]);
253 unsigned newSize = operands.size();
254 if (newSize == length) {
256 for (
unsigned i = 0, e = length; i != e; ++i)
257 storageOperands[start + i].
set(operands[i]);
262 if (newSize < length) {
268 auto storageOperands = resize(owner,
size() + (newSize - length));
271 unsigned rotateSize = storageOperands.size() - (start + length);
272 auto rbegin = storageOperands.rbegin();
273 std::rotate(rbegin, std::next(rbegin, newSize - length), rbegin + rotateSize);
276 for (
unsigned i = 0, e = operands.size(); i != e; ++i)
277 storageOperands[start + i].
set(operands[i]);
283 assert((start + length) <= operands.size());
284 numOperands -= length;
287 if (start != numOperands) {
288 auto *indexIt = std::next(operands.begin(), start);
289 std::rotate(indexIt, std::next(indexIt, length), operands.end());
291 for (
unsigned i = 0; i != length; ++i)
296 const BitVector &eraseIndices) {
298 assert(eraseIndices.size() == operands.size());
301 int firstErasedIndice = eraseIndices.find_first();
302 if (firstErasedIndice == -1)
306 numOperands = firstErasedIndice;
307 for (
unsigned i = firstErasedIndice + 1, e = operands.size(); i < e; ++i)
308 if (!eraseIndices.test(i))
309 operands[numOperands++] = std::move(operands[i]);
310 for (
OpOperand &operand : operands.drop_front(numOperands))
311 operand.~OpOperand();
321 if (newSize <= numOperands) {
324 for (
unsigned i = newSize; i != numOperands; ++i)
326 numOperands = newSize;
327 return origOperands.take_front(newSize);
331 if (newSize <= capacity) {
332 OpOperand *opBegin = origOperands.data();
333 for (
unsigned e = newSize; numOperands != e; ++numOperands)
334 new (&opBegin[numOperands])
OpOperand(owner);
339 unsigned newCapacity =
340 std::max(
unsigned(llvm::NextPowerOf2(capacity + 2)), newSize);
346 std::uninitialized_copy(std::make_move_iterator(origOperands.begin()),
347 std::make_move_iterator(origOperands.end()),
348 newOperands.begin());
351 for (
auto &operand : origOperands)
352 operand.~OpOperand();
355 for (
unsigned e = newSize; numOperands != e; ++numOperands)
356 new (&newOperands[numOperands])
OpOperand(owner);
359 if (isStorageDynamic)
360 free(operandStorage);
363 operandStorage = newOperandStorage;
364 capacity = newCapacity;
365 isStorageDynamic =
true;
377 assert(!empty() &&
"range must not be empty");
378 return base->getOperandNumber();
394 const OwnerT &owner = getBase();
397 std::accumulate(sizeData.begin(), sizeData.end(), 0));
400 OperandRange OperandRangeRange::dereference(
const OwnerT &
object,
403 uint32_t startIndex =
404 std::accumulate(sizeData.begin(), sizeData.begin() + index, 0);
405 return OperandRange(
object.first + startIndex, *(sizeData.begin() + index));
414 Operation *owner,
unsigned start,
unsigned length,
416 : owner(owner), start(start), length(length),
417 operandSegments(operandSegments.begin(), operandSegments.end()) {
418 assert((start + length) <= owner->
getNumOperands() &&
"invalid range");
427 assert((subStart + subLen) <= length &&
"invalid sub-range");
431 subSlice.operandSegments.push_back(*segment);
440 updateLength(length + values.size());
446 if (length != values.size())
447 updateLength(values.size());
462 assert((subStart + subLen) <= length &&
"invalid sub-range");
466 updateLength(length - subLen);
488 void MutableOperandRange::updateLength(
unsigned newLength) {
489 int32_t diff = int32_t(newLength) - int32_t(length);
496 segments[segment.first] += diff;
497 segment.second.setValue(
499 owner->
setAttr(segment.second.getName(), segment.second.getValue());
509 OwnerT(operands, operandSegmentAttr), 0,
513 return getBase().first;
525 uint32_t startIndex =
526 std::accumulate(sizeData.begin(), sizeData.begin() + index, 0);
527 return object.first.slice(
528 startIndex, *(sizeData.begin() + index),
559 : it(end ? results.end() : results.begin()), endIt(results.end()) {
562 skipOverResultsWithNoUsers();
568 if (use != (*it).use_end())
570 if (use == (*it).use_end()) {
572 skipOverResultsWithNoUsers();
577 void ResultRange::UseIterator::skipOverResultsWithNoUsers() {
578 while (it != endIt && (*it).use_empty())
586 use = (*it).use_begin();
599 :
ValueRange(values.begin().getBase(), values.size()) {}
601 :
ValueRange(values.getBase(), values.size()) {}
606 if (
const auto *
value = owner.dyn_cast<
const Value *>())
607 return {
value + index};
608 if (
auto *operand = owner.dyn_cast<
OpOperand *>())
609 return {operand + index};
613 Value ValueRange::dereference_iterator(
const OwnerT &owner, ptrdiff_t index) {
614 if (
const auto *
value = owner.dyn_cast<
const Value *>())
616 if (
auto *operand = owner.dyn_cast<
OpOperand *>())
617 return operand[index].get();
632 llvm::hash_code hash = llvm::hash_combine(
639 operandStorage.append(operands.begin(), operands.end());
640 llvm::sort(operandStorage, [](
Value a,
Value b) ->
bool {
643 operands = operandStorage;
645 for (
Value operand : operands)
646 hash = llvm::hash_combine(hash, hashOperands(operand));
650 hash = llvm::hash_combine(hash, hashResults(result));
660 auto blocksEquivalent = [&](
Block &lBlock,
Block &rBlock) {
666 auto insertion = blocksMap.insert({&lBlock, &rBlock});
667 if (insertion.first->getSecond() != &rBlock)
671 llvm::zip(lBlock.
getArguments(), rBlock.getArguments())) {
672 Value curArg = std::get<0>(argPair);
673 Value otherArg = std::get<1>(argPair);
674 if (curArg.
getType() != otherArg.getType())
677 curArg.
getLoc() != otherArg.getLoc())
680 if (
failed(mapOperands(curArg, otherArg)))
690 for (
auto successorsPair :
692 Block *curSuccessor = std::get<0>(successorsPair);
693 Block *otherSuccessor = std::get<1>(successorsPair);
694 auto insertion = blocksMap.insert({curSuccessor, otherSuccessor});
695 if (insertion.first->getSecond() != otherSuccessor)
700 return llvm::all_of_zip(lBlock, rBlock, opsEquivalent);
702 return llvm::all_of_zip(*lhs, *rhs, blocksEquivalent);
720 if (!(flags & IgnoreLocations) && lhs->
getLoc() != rhs->
getLoc())
726 lhsOperandStorage.append(lhsOperands.begin(), lhsOperands.end());
727 llvm::sort(lhsOperandStorage, [](
Value a,
Value b) ->
bool {
730 lhsOperands = lhsOperandStorage;
732 rhsOperandStorage.append(rhsOperands.begin(), rhsOperands.end());
733 llvm::sort(rhsOperandStorage, [](
Value a,
Value b) ->
bool {
736 rhsOperands = rhsOperandStorage;
738 auto checkValueRangeMapping =
741 for (
auto operandPair : llvm::zip(lhs, rhs)) {
742 Value curArg = std::get<0>(operandPair);
743 Value otherArg = std::get<1>(operandPair);
744 if (curArg.
getType() != otherArg.getType())
746 if (
failed(mapValues(curArg, otherArg)))
752 if (!checkValueRangeMapping(lhsOperands, rhsOperands, mapOperands))
754 if (!checkValueRangeMapping(lhs->getResults(), rhs->getResults(), mapResults))
756 for (
auto regionPair : llvm::zip(lhs->getRegions(), rhs->getRegions()))
758 &std::get<1>(regionPair), mapOperands, mapResults,
OperandRange join() const
Flatten all of the sub ranges into a single contiguous operand range.
TODO: Remove this file when SCCP and integer range analysis have been ported to the new framework...
This class contains a list of basic blocks and a link to the parent operation it is attached to...
use_iterator use_begin() const
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
Operation is a basic unit of execution within MLIR.
SmallVector< Block *, 1 > successors
Successors of this operation and their respective operands.
This class adds property that the operation is commutative.
This is a value defined by a result of an operation.
operand_range getOperands()
Returns an iterator on the underlying Value's.
unsigned getNumRegions()
Returns the number of regions held by this operation.
void setOperands(ValueRange operands)
Replace the current operands of this operation with the ones provided in 'operands'.
Block represents an ordered list of Operations.
OperandStorage(Operation *owner, OpOperand *trailingOperands, ValueRange values)
SmallVectorImpl< NamedAttribute >::const_iterator const_iterator
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
static bool isEquivalentTo(Operation *lhs, Operation *rhs, function_ref< LogicalResult(Value, Value)> mapOperands, function_ref< LogicalResult(Value, Value)> mapResults, Flags flags=Flags::None)
Compare two operations and return if they are equivalent.
unsigned getNumOperands()
ValueUserIterator< use_iterator, OpOperand > user_iterator
static bool isRegionEquivalentTo(Region *lhs, Region *rhs, function_ref< LogicalResult(Value, Value)> mapOperands, function_ref< LogicalResult(Value, Value)> mapResults, OperationEquivalence::Flags flags)
DictionaryAttr getDictionary(MLIRContext *context) const
Return a dictionary attribute for the underlying dictionary.
This class implements the result iterators for the Operation class.
void append(ValueRange values)
Append the given values to the range.
unsigned getNumSuccessors()
An iterator over the users of an IRObject.
user_range getUsers()
Returns a range of all users.
Attribute erase(StringAttr name)
Erase the attribute with the given name from the list.
void insertOperands(unsigned index, ValueRange operands)
Insert the given operands into the operand list at the given 'index'.
void assign(const_iterator inStart, const_iterator inEnd)
Replaces the attributes with new list of attributes.
static constexpr const bool value
SmallVector< Value, 4 > operands
void * getAsOpaquePointer() const
Methods for supporting PointerLikeTypeTraits.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
NamedAttribute represents a combination of a name and an Attribute value.
unsigned getBeginOperandIndex() const
Return the operand index of the first element of this 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'.
void eraseOperands(unsigned idx, unsigned length=1)
Erase the operands starting at position idx and ending at position 'idx'+'length'.
This class represents an efficient way to signal success or failure.
This class represents a contiguous range of mutable operand ranges, e.g.
void erase(unsigned subStart, unsigned subLen=1)
Erase the operands within the given sub-range.
Attribute get(StringAttr name) const
Return the specified attribute if present, null otherwise.
An attribute that represents a reference to a dense vector or tensor object.
MLIRContext * getContext() const
Return the context this attribute belongs to.
void addOperands(ValueRange newOperands)
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.
MutableOperandRangeRange(const MutableOperandRange &operands, NamedAttribute operandSegmentAttr)
Construct a range given a parent set of operands, and an I32 tensor elements attribute containing the...
OperationState(Location location, StringRef name)
void setOperands(Operation *owner, ValueRange values)
Replace the operands contained in the storage with the ones provided in 'values'. ...
unsigned getNumArguments()
Attributes are known-constant values of operations.
user_iterator user_begin()
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
UseIterator(ResultRange results, bool end=false)
Initialize the UseIterator.
static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseIntElementsAttr with the given arguments.
This class provides an abstraction over the various different ranges of value types.
void clear()
Clear this range and erase all of the operands.
This class provides a mutable adaptor for a range of operands.
Location getLoc()
The source location the operation was defined or derived from.
This represents an operation in an abstracted form, suitable for use with the builder APIs...
This class represents a contiguous range of operand ranges, e.g.
BlockArgListType getArguments()
void setOperand(unsigned idx, Value value)
Location getLoc() const
Return the location of this value.
DictionaryAttr getAttrDictionary()
Return all of the attributes on this operation as a DictionaryAttr.
void assign(ValueRange values)
Assign this range to the given values.
MutableOperandRange join() const
Flatten all of the sub ranges into a single contiguous mutable operand range.
void addSuccessors(Block *successor)
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
OperandRangeRange split(ElementsAttr segmentSizes) const
Split this range into a set of contiguous subranges using the given elements attribute, which contains the sizes of the sub ranges.
This class implements a use iterator for a range of operation results.
void addRegions(MutableArrayRef< std::unique_ptr< Region >> regions)
Take ownership of a set of regions that should be attached to the Operation.
unsigned size()
Return the number of operands held in the storage.
MutableOperandRange(Operation *owner, unsigned start, unsigned length, ArrayRef< OperandSegment > operandSegments=llvm::None)
Construct a new mutable range from the given operand, operand start index, and range length...
MLIRContext * getContext() const
Get the context held by this operation state.
SuccessorRange getSuccessors()
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
Region * addRegion()
Create a region that should be attached to the operation.
ResultRange(OpResult result)
use_range getUses() const
Returns a range of all uses of results within this range, which is useful for iterating over all uses...
Type getType() const
Return the type of this value.
Optional< NamedAttribute > findDuplicate() const
Returns an entry with a duplicate name the list, if it exists, else returns llvm::None.
MutableOperandRange slice(unsigned subStart, unsigned subLen, Optional< OperandSegment > segment=llvm::None) const
Slice this range into a sub range, with the additional operand segment.
unsigned size() const
Returns the current size of the range.
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
MLIRContext is the top-level object for a collection of MLIR operations.
This class represents an operand of an operation.
This class provides an abstraction over the different types of ranges over Blocks.
This class implements the operand iterators for the Operation class.
This class provides the implementation for an operation result.
std::pair< unsigned, NamedAttribute > OperandSegment
A pair of a named attribute corresponding to an operand segment attribute, and the index within that ...
use_iterator use_end() const
NamedAttrList & operator=(const SmallVectorImpl< NamedAttribute > &rhs)
unsigned getNumResults()
Return the number of results held by this operation.
MutableArrayRef< OpOperand > getOperands()
Get the operation operands held by the storage.
SmallVector< std::unique_ptr< Region >, 1 > regions
Regions that the op will hold.
OperationName getName()
The name of an operation is the key identifier for it.
MutableOperandRangeRange split(NamedAttribute segmentSizes) const
Split this range into a set of contiguous subranges using the given elements attribute, which contains the sizes of the sub ranges.
result_range getResults()
This class provides an abstraction over the different types of ranges over Values.
void push_back(NamedAttribute newAttribute)
Add an attribute with the specified name.
ArrayRef< NamedAttribute > getAttrs() const
Return all of the attributes on this operation.
Optional< NamedAttribute > getNamed(StringRef name) const
Return the specified named attribute if present, None otherwise.
result_type_range getResultTypes()
UseIterator & operator++()
void eraseOperands(unsigned start, unsigned length)
Erase the operands held by the storage within the given range.
OperandRangeRange(OperandRange operands, Attribute operandSegments)
Construct a range given a parent set of operands, and an I32 elements attribute containing the sizes ...
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
An attribute that represents a reference to a dense integer vector or tensor object.
SmallVector< Type, 4 > types
Types of the results of this operation.