20#include "llvm/ADT/APSInt.h"
21#include "llvm/Support/Debug.h"
22#include "llvm/Support/DebugLog.h"
23#include "llvm/Support/Endian.h"
26#define DEBUG_TYPE "builtinattributes"
35#define GET_ATTRDEF_CLASSES
36#include "mlir/IR/BuiltinAttributes.cpp.inc"
42void BuiltinDialect::registerAttributes() {
44#define GET_ATTRDEF_LIST
45#include "mlir/IR/BuiltinAttributes.cpp.inc"
47 addAttributes<DistinctAttr>();
58template <
bool inPlace>
62 switch (value.size()) {
71 storage.assign({value[0]});
74 bool isSorted = value[0] < value[1];
77 std::swap(storage[0], storage[1]);
78 }
else if (isSorted) {
79 storage.assign({value[0], value[1]});
81 storage.assign({value[1], value[0]});
87 storage.assign(value.begin(), value.end());
89 bool isSorted = llvm::is_sorted(value);
92 llvm::array_pod_sort(storage.begin(), storage.end());
100static std::optional<NamedAttribute>
102 const std::optional<NamedAttribute> none{std::nullopt};
103 if (value.size() < 2)
106 if (value.size() == 2)
107 return value[0].getName() == value[1].getName() ? value[0] : none;
109 const auto *it = std::adjacent_find(value.begin(), value.end(),
111 return l.getName() == r.getName();
113 return it != value.end() ? *it : none;
120 "DictionaryAttr element names must be unique");
127 "DictionaryAttr element names must be unique");
131std::optional<NamedAttribute>
139DictionaryAttr DictionaryAttr::get(
MLIRContext *context,
142 return DictionaryAttr::getEmpty(context);
145 SmallVector<NamedAttribute, 8> storage;
149 "DictionaryAttr element names must be unique");
150 return Base::get(context, value);
154DictionaryAttr DictionaryAttr::getWithSorted(
MLIRContext *context,
157 return DictionaryAttr::getEmpty(context);
159 assert(llvm::is_sorted(
160 value, [](NamedAttribute l, NamedAttribute r) {
return l < r; }) &&
161 "expected attribute values to be sorted");
163 "DictionaryAttr element names must be unique");
164 return Base::get(context, value);
168Attribute DictionaryAttr::get(StringRef name)
const {
169 auto it = impl::findAttrSorted(begin(), end(), name);
170 return it.second ? it.first->getValue() : Attribute();
172Attribute DictionaryAttr::get(StringAttr name)
const {
173 auto it = impl::findAttrSorted(begin(), end(), name);
174 return it.second ? it.first->getValue() : Attribute();
178std::optional<NamedAttribute> DictionaryAttr::getNamed(StringRef name)
const {
179 auto it = impl::findAttrSorted(begin(), end(), name);
180 return it.second ? *it.first : std::optional<NamedAttribute>();
182std::optional<NamedAttribute> DictionaryAttr::getNamed(StringAttr name)
const {
183 auto it = impl::findAttrSorted(begin(), end(), name);
184 return it.second ? *it.first : std::optional<NamedAttribute>();
188bool DictionaryAttr::contains(StringRef name)
const {
189 return impl::findAttrSorted(begin(), end(), name).second;
191bool DictionaryAttr::contains(StringAttr name)
const {
192 return impl::findAttrSorted(begin(), end(), name).second;
195DictionaryAttr::iterator DictionaryAttr::begin()
const {
196 return getValue().begin();
198DictionaryAttr::iterator DictionaryAttr::end()
const {
199 return getValue().end();
201size_t DictionaryAttr::size()
const {
return getValue().size(); }
203DictionaryAttr DictionaryAttr::getEmptyUnchecked(
MLIRContext *context) {
204 return Base::get(context, ArrayRef<NamedAttribute>());
212void StridedLayoutAttr::print(llvm::raw_ostream &os)
const {
213 auto printIntOrQuestion = [&](
int64_t value) {
214 if (ShapedType::isDynamic(value))
221 llvm::interleaveComma(getStrides(), os, printIntOrQuestion);
224 if (getOffset() != 0) {
226 printIntOrQuestion(getOffset());
233bool StridedLayoutAttr::hasStaticLayout()
const {
234 return ShapedType::isStatic(getOffset()) &&
235 ShapedType::isStaticShape(getStrides());
239AffineMap StridedLayoutAttr::getAffineMap()
const {
251LogicalResult StridedLayoutAttr::verifyLayout(
254 if (
shape.size() != getStrides().size())
255 return emitError() <<
"expected the number of strides to match the rank";
264 llvm::append_range(strides, getStrides());
265 offset = getOffset();
273StringAttr StringAttr::getEmptyStringAttrUnchecked(
MLIRContext *context) {
274 return Base::get(context,
"", NoneType::get(context));
278StringAttr StringAttr::get(
MLIRContext *context,
const Twine &twine) {
280 if (twine.isTriviallyEmpty())
282 SmallVector<char, 32> tempStr;
283 return Base::get(context, twine.toStringRef(tempStr), NoneType::get(context));
287StringAttr StringAttr::get(
const Twine &twine,
Type type) {
288 SmallVector<char, 32> tempStr;
289 return Base::get(type.
getContext(), twine.toStringRef(tempStr), type);
292StringRef StringAttr::getValue()
const {
return getImpl()->value; }
294Type StringAttr::getType()
const {
return getImpl()->type; }
296Dialect *StringAttr::getReferencedDialect()
const {
297 return getImpl()->referencedDialect;
304double FloatAttr::getValueAsDouble()
const {
305 return getValueAsDouble(getValue());
307double FloatAttr::getValueAsDouble(APFloat value) {
308 if (&value.getSemantics() != &APFloat::IEEEdouble()) {
309 bool losesInfo =
false;
310 value.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
313 return value.convertToDouble();
317 Type type, APFloat value) {
319 if (!llvm::isa<FloatType>(type))
320 return emitError() <<
"expected floating point type";
323 if (&llvm::cast<FloatType>(type).getFloatSemantics() !=
324 &value.getSemantics()) {
326 <<
"FloatAttr type doesn't match the type implied by its value";
335SymbolRefAttr SymbolRefAttr::get(
MLIRContext *ctx, StringRef value,
337 return get(StringAttr::get(ctx, value), nestedRefs);
341 return llvm::cast<FlatSymbolRefAttr>(
get(ctx, value, {}));
345 return llvm::cast<FlatSymbolRefAttr>(
get(value, {}));
351 assert(symName &&
"value does not have a valid symbol name");
352 return SymbolRefAttr::get(symName);
355StringAttr SymbolRefAttr::getLeafReference()
const {
356 ArrayRef<FlatSymbolRefAttr> nestedRefs = getNestedReferences();
357 return nestedRefs.empty() ? getRootReference() : nestedRefs.back().getAttr();
364int64_t IntegerAttr::getInt()
const {
366 "must be signless integer");
367 return getValue().getSExtValue();
370int64_t IntegerAttr::getSInt()
const {
371 assert(
getType().isSignedInteger() &&
"must be signed integer");
372 return getValue().getSExtValue();
375uint64_t IntegerAttr::getUInt()
const {
376 assert(
getType().isUnsignedInteger() &&
"must be unsigned integer");
377 return getValue().getZExtValue();
382APSInt IntegerAttr::getAPSInt()
const {
383 assert(!
getType().isSignlessInteger() &&
384 "Signless integers don't carry a sign for APSInt");
385 return APSInt(getValue(),
getType().isUnsignedInteger());
389 Type type, APInt value) {
390 if (IntegerType integerType = llvm::dyn_cast<IntegerType>(type)) {
391 if (integerType.getWidth() != value.getBitWidth())
392 return emitError() <<
"integer type bit width (" << integerType.getWidth()
393 <<
") doesn't match value bit width ("
394 << value.getBitWidth() <<
")";
397 if (llvm::isa<IndexType>(type)) {
398 if (value.getBitWidth() != IndexType::kInternalStorageBitWidth)
400 <<
"value bit width (" << value.getBitWidth()
401 <<
") doesn't match index type internal storage bit width ("
402 << IndexType::kInternalStorageBitWidth <<
")";
405 return emitError() <<
"expected integer or index type";
408BoolAttr IntegerAttr::getBoolAttrUnchecked(IntegerType type,
bool value) {
409 auto attr = Base::get(type.getContext(), type, APInt(1, value));
410 return llvm::cast<BoolAttr>(attr);
418 auto *storage =
reinterpret_cast<IntegerAttrStorage *
>(
impl);
419 return storage->value.getBoolValue();
423 IntegerAttr intAttr = llvm::dyn_cast<IntegerAttr>(attr);
424 return intAttr && intAttr.getType().isSignlessInteger(1);
432 StringAttr dialect, StringRef attrData,
435 return emitError() <<
"invalid dialect namespace '" << dialect <<
"'";
442 <<
"#" << dialect <<
"<\"" << attrData <<
"\"> : " << type
443 <<
" attribute created with unregistered dialect. If this is "
444 "intended, please call allowUnregisteredDialects() on the "
445 "MLIRContext, or use -allow-unregistered-dialect with "
446 "the MLIR opt tool used";
462 return origWidth == 1 ? origWidth : llvm::alignTo<8>(origWidth);
469static void setBit(
char *rawData,
size_t bitPos,
bool value) {
471 rawData[bitPos / CHAR_BIT] |= (1 << (bitPos % CHAR_BIT));
473 rawData[bitPos / CHAR_BIT] &= ~(1 << (bitPos % CHAR_BIT));
477static bool getBit(
const char *rawData,
size_t bitPos) {
478 return (rawData[bitPos / CHAR_BIT] & (1 << (bitPos % CHAR_BIT))) != 0;
485 assert(llvm::endianness::native == llvm::endianness::big);
486 assert(value.getNumWords() * APInt::APINT_WORD_SIZE >= numBytes);
491 size_t numFilledWords = (value.getNumWords() - 1) * APInt::APINT_WORD_SIZE;
492 std::copy_n(
reinterpret_cast<const char *
>(value.getRawData()),
497 size_t lastWordPos = numFilledWords;
499 DenseIntOrFPElementsAttr::convertEndianOfCharForBEmachine(
500 reinterpret_cast<const char *
>(value.getRawData()) + lastWordPos,
501 valueLE.begin(), APInt::APINT_BITS_PER_WORD, 1);
505 DenseIntOrFPElementsAttr::convertEndianOfCharForBEmachine(
506 valueLE.begin(),
result + lastWordPos,
507 (numBytes - lastWordPos) * CHAR_BIT, 1);
514 assert(llvm::endianness::native == llvm::endianness::big);
515 assert(
result.getNumWords() * APInt::APINT_WORD_SIZE >= numBytes);
522 size_t numFilledWords = (
result.getNumWords() - 1) * APInt::APINT_WORD_SIZE;
524 inArray, numFilledWords,
525 const_cast<char *
>(
reinterpret_cast<const char *
>(
result.getRawData())));
530 size_t lastWordPos = numFilledWords;
532 DenseIntOrFPElementsAttr::convertEndianOfCharForBEmachine(
533 inArray + lastWordPos, inArrayLE.begin(),
534 (numBytes - lastWordPos) * CHAR_BIT, 1);
538 DenseIntOrFPElementsAttr::convertEndianOfCharForBEmachine(
540 const_cast<char *
>(
reinterpret_cast<const char *
>(
result.getRawData())) +
542 APInt::APINT_BITS_PER_WORD, 1);
546static void writeBits(
char *rawData,
size_t bitPos, APInt value) {
547 size_t bitWidth = value.getBitWidth();
551 return setBit(rawData, bitPos, value.isOne());
554 assert((bitPos % CHAR_BIT) == 0 &&
"expected bitPos to be 8-bit aligned");
555 if (llvm::endianness::native == llvm::endianness::big) {
562 rawData + (bitPos / CHAR_BIT));
564 std::copy_n(
reinterpret_cast<const char *
>(value.getRawData()),
565 llvm::divideCeil(bitWidth, CHAR_BIT),
566 rawData + (bitPos / CHAR_BIT));
572static APInt
readBits(
const char *rawData,
size_t bitPos,
size_t bitWidth) {
575 return APInt(1,
getBit(rawData, bitPos) ? 1 : 0);
578 assert((bitPos % CHAR_BIT) == 0 &&
"expected bitPos to be 8-bit aligned");
579 APInt
result(bitWidth, 0);
580 if (llvm::endianness::native == llvm::endianness::big) {
587 llvm::divideCeil(bitWidth, CHAR_BIT),
result);
589 std::copy_n(rawData + (bitPos / CHAR_BIT),
590 llvm::divideCeil(bitWidth, CHAR_BIT),
592 reinterpret_cast<const char *
>(
result.getRawData())));
599template <
typename Values>
601 return (values.size() == 1) ||
602 (type.getNumElements() ==
static_cast<int64_t>(values.size()));
613DenseElementsAttr::AttributeElementIterator::AttributeElementIterator(
615 : llvm::indexed_accessor_iterator<AttributeElementIterator, const void *,
617 attr.getAsOpaquePointer(),
index) {}
621 Type eltTy = owner.getElementType();
622 if (llvm::dyn_cast<IntegerType>(eltTy))
624 if (llvm::isa<IndexType>(eltTy))
626 if (
auto floatEltTy = llvm::dyn_cast<FloatType>(eltTy)) {
629 return FloatAttr::get(eltTy, *floatIt);
631 if (
auto complexTy = llvm::dyn_cast<ComplexType>(eltTy)) {
632 auto complexEltTy = complexTy.getElementType();
634 if (llvm::isa<IntegerType>(complexEltTy)) {
635 auto value = *complexIntIt;
636 auto real = IntegerAttr::get(complexEltTy, value.real());
637 auto imag = IntegerAttr::get(complexEltTy, value.imag());
638 return ArrayAttr::get(complexTy.getContext(),
643 llvm::cast<FloatType>(complexEltTy).getFloatSemantics(), complexIntIt);
644 auto value = *complexFloatIt;
645 auto real = FloatAttr::get(complexEltTy, value.real());
646 auto imag = FloatAttr::get(complexEltTy, value.imag());
647 return ArrayAttr::get(complexTy.getContext(),
650 if (llvm::isa<DenseStringElementsAttr>(owner)) {
652 return StringAttr::get(owner.isSplat() ? vals.front() : vals[
index], eltTy);
654 llvm_unreachable(
"unexpected element type");
661DenseElementsAttr::BoolElementIterator::BoolElementIterator(
674DenseElementsAttr::IntElementIterator::IntElementIterator(
690DenseElementsAttr::ComplexIntElementIterator::ComplexIntElementIterator(
696 auto complexType = llvm::cast<ComplexType>(attr.
getElementType());
716 return emitError() <<
"expected integer or floating point element type";
717 int64_t dataSize = rawData.size();
720 if (
size * elementSize != dataSize) {
721 return emitError() <<
"expected data size (" <<
size <<
" elements, "
723 <<
" bytes each) does not match: " << dataSize
732template <
size_t width,
733 IntegerType::SignednessSemantics signedness = IntegerType::Signless>
734struct DenseArrayAttrIntUtil {
735 static bool checkElementType(
Type eltType) {
736 auto type = llvm::dyn_cast<IntegerType>(eltType);
737 if (!type || type.getWidth() != width)
739 return type.getSignedness() == signedness;
743 return IntegerType::get(ctx, width, signedness);
746 template <
typename T>
747 static void printElement(
raw_ostream &os, T value) {
751 template <
typename T>
752 static ParseResult parseElement(
AsmParser &parser, T &value) {
757struct DenseArrayAttrUtil;
762struct DenseArrayAttrUtil<
bool> :
public DenseArrayAttrIntUtil<1> {
763 static void printElement(
raw_ostream &os,
bool value) {
764 os << (value ?
"true" :
"false");
771struct DenseArrayAttrUtil<int8_t> :
public DenseArrayAttrIntUtil<8> {
772 static void printElement(
raw_ostream &os, int8_t value) {
773 os << static_cast<int>(value);
777struct DenseArrayAttrUtil<int16_t> :
public DenseArrayAttrIntUtil<16> {};
779struct DenseArrayAttrUtil<int32_t> :
public DenseArrayAttrIntUtil<32> {};
781struct DenseArrayAttrUtil<int64_t> :
public DenseArrayAttrIntUtil<64> {};
785struct DenseArrayAttrUtil<float> {
786 static bool checkElementType(Type eltType) {
return eltType.
isF32(); }
787 static Type
getElementType(MLIRContext *ctx) {
return Float32Type::get(ctx); }
788 static void printElement(raw_ostream &os,
float value) { os << value; }
791 static ParseResult parseElement(AsmParser &parser,
float &value) {
802struct DenseArrayAttrUtil<double> {
803 static bool checkElementType(Type eltType) {
return eltType.
isF64(); }
804 static Type
getElementType(MLIRContext *ctx) {
return Float64Type::get(ctx); }
805 static void printElement(raw_ostream &os,
float value) { os << value; }
806 static ParseResult parseElement(AsmParser &parser,
double &value) {
819 llvm::interleaveComma(
asArrayRef(), os, [&](T value) {
820 DenseArrayAttrUtil<T>::printElement(os, value);
838 if (DenseArrayAttrUtil<T>::parseElement(parser, value))
840 data.push_back(value);
865 assert((raw.size() %
sizeof(T)) == 0);
866 return ArrayRef<T>(
reinterpret_cast<const T *
>(raw.data()),
867 raw.size() /
sizeof(T));
874 Type elementType = DenseArrayAttrUtil<T>::getElementType(context);
875 auto rawArray =
ArrayRef<char>(
reinterpret_cast<const char *
>(content.data()),
876 content.size() *
sizeof(T));
877 return llvm::cast<DenseArrayAttrImpl<T>>(
878 Base::get(context, elementType, content.size(), rawArray));
883 if (
auto denseArray = llvm::dyn_cast<DenseArrayAttr>(attr))
884 return DenseArrayAttrUtil<T>::checkElementType(denseArray.getElementType());
907 return llvm::isa<DenseIntOrFPElementsAttr, DenseStringElementsAttr>(attr);
914 Type eltType = type.getElementType();
917 if (
auto complexType = llvm::dyn_cast<ComplexType>(eltType)) {
918 if (complexType.getElementType().isIntOrIndex()) {
920 complexValues.reserve(values.size());
922 assert(llvm::isa<ArrayAttr>(attr) &&
"expected ArrayAttr for complex");
923 auto arrayAttr = llvm::cast<ArrayAttr>(attr);
924 assert(arrayAttr.size() == 2 &&
"expected 2 element for complex");
925 auto attr0 = arrayAttr[0];
926 auto attr1 = arrayAttr[1];
927 complexValues.push_back(
928 std::complex<APInt>(llvm::cast<IntegerAttr>(attr0).getValue(),
929 llvm::cast<IntegerAttr>(attr1).getValue()));
935 complexValues.reserve(values.size());
937 assert(llvm::isa<ArrayAttr>(attr) &&
"expected ArrayAttr for complex");
938 auto arrayAttr = llvm::cast<ArrayAttr>(attr);
939 assert(arrayAttr.size() == 2 &&
"expected 2 element for complex");
940 auto attr0 = arrayAttr[0];
941 auto attr1 = arrayAttr[1];
942 complexValues.push_back(
943 std::complex<APFloat>(llvm::cast<FloatAttr>(attr0).getValue(),
944 llvm::cast<FloatAttr>(attr1).getValue()));
953 stringValues.reserve(values.size());
955 assert(llvm::isa<StringAttr>(attr) &&
956 "expected string value for non integer/index/float element");
957 stringValues.push_back(llvm::cast<StringAttr>(attr).getValue());
959 return get(type, stringValues);
968 llvm::divideCeil(storageBitWidth * values.size(), CHAR_BIT));
970 for (
unsigned i = 0, e = values.size(); i < e; ++i) {
971 if (
auto floatAttr = llvm::dyn_cast<FloatAttr>(values[i])) {
972 assert(floatAttr.getType() == eltType &&
973 "expected float attribute type to equal element type");
974 intVal = floatAttr.getValue().bitcastToAPInt();
976 auto intAttr = llvm::cast<IntegerAttr>(values[i]);
977 assert(intAttr.getType() == eltType &&
978 "expected integer attribute type to equal element type");
979 intVal = intAttr.getValue();
982 assert(intVal.getBitWidth() == bitWidth &&
983 "expected value to have same bitwidth as element type");
984 writeBits(data.data(), i * storageBitWidth, intVal);
988 if (values.size() == 1 && eltType.
isInteger(1))
989 data[0] = data[0] ? -1 : 0;
991 return DenseIntOrFPElementsAttr::getRaw(type, data);
997 assert(type.getElementType().isInteger(1));
1001 if (!values.empty()) {
1003 bool firstValue = values[0];
1004 for (
int i = 0, e = values.size(); i != e; ++i) {
1005 isSplat &= values[i] == firstValue;
1006 setBit(buff.data(), i, values[i]);
1012 buff[0] = values[0] ? -1 : 0;
1016 return DenseIntOrFPElementsAttr::getRaw(type, buff);
1021 assert(!type.getElementType().isIntOrFloat());
1022 return DenseStringElementsAttr::get(type, values);
1030 assert(type.getElementType().isIntOrIndex());
1033 return DenseIntOrFPElementsAttr::getRaw(type, storageBitWidth, values);
1036 ArrayRef<std::complex<APInt>> values) {
1037 ComplexType
complex = llvm::cast<ComplexType>(type.getElementType());
1038 assert(llvm::isa<IntegerType>(
complex.getElementType()));
1041 ArrayRef<APInt> intVals(
reinterpret_cast<const APInt *
>(values.data()),
1043 return DenseIntOrFPElementsAttr::getRaw(type, storageBitWidth, intVals);
1051 assert(llvm::isa<FloatType>(type.getElementType()));
1054 return DenseIntOrFPElementsAttr::getRaw(type, storageBitWidth, values);
1058 ArrayRef<std::complex<APFloat>> values) {
1059 ComplexType
complex = llvm::cast<ComplexType>(type.getElementType());
1060 assert(llvm::isa<FloatType>(
complex.getElementType()));
1065 return DenseIntOrFPElementsAttr::getRaw(type, storageBitWidth, apVals);
1073 return DenseIntOrFPElementsAttr::getRaw(type, rawBuffer);
1079 bool &detectedSplat) {
1081 size_t rawBufferWidth = rawBuffer.size() * CHAR_BIT;
1082 int64_t numElements = type.getNumElements();
1085 detectedSplat = numElements == 1;
1088 if (storageWidth == 1) {
1091 if (rawBuffer.size() == 1) {
1092 auto rawByte =
static_cast<uint8_t
>(rawBuffer[0]);
1093 if (rawByte == 0 || rawByte == 0xff) {
1094 detectedSplat =
true;
1100 return rawBufferWidth == llvm::alignTo<8>(numElements);
1105 if (rawBufferWidth == storageWidth) {
1106 detectedSplat =
true;
1111 return rawBufferWidth == storageWidth * numElements;
1121 auto dataSize =
static_cast<size_t>(dataEltSize * CHAR_BIT);
1122 if (denseEltBitWidth != dataSize) {
1123 LDBG() <<
"expected dense element bit width " << denseEltBitWidth
1124 <<
" to match data size " << dataSize <<
" for type " << type;
1130 bool valid = llvm::isa<FloatType>(type);
1132 LDBG() <<
"expected float type when isInt is false, but found " << type;
1138 auto intType = llvm::dyn_cast<IntegerType>(type);
1140 LDBG() <<
"expected integer type when isInt is true, but found " << type;
1145 if (intType.isSignless())
1148 bool valid = intType.isSigned() == isSigned;
1150 LDBG() <<
"expected signedness " << isSigned <<
" to match type " << type;
1158 bool isInt,
bool isSigned) {
1159 return DenseIntOrFPElementsAttr::getRawComplex(type, data, dataEltSize, isInt,
1167 return DenseIntOrFPElementsAttr::getRawIntOrFloat(type, data, dataEltSize,
1172 bool isSigned)
const {
1173 return ::isValidIntOrFloat(
getElementType(), dataEltSize, isInt, isSigned);
1176 bool isSigned)
const {
1177 return ::isValidIntOrFloat(
1179 dataEltSize / 2, isInt, isSigned);
1190 return llvm::isa<IntegerType>(llvm::cast<ComplexType>(type).
getElementType());
1207 const auto &elementSemantics = eltTy.getFloatSemantics();
1218 auto eltTy = llvm::dyn_cast<FloatType>(complexTy.getElementType());
1221 const auto &semantics = eltTy.getFloatSemantics();
1223 getType(), {semantics, {*
this, 0}},
1240 ShapedType curType =
getType();
1241 if (curType == newType)
1244 assert(newType.getElementType() == curType.getElementType() &&
1245 "expected the same element type");
1246 assert(newType.getNumElements() == curType.getNumElements() &&
1247 "expected the same number of elements");
1248 return DenseIntOrFPElementsAttr::getRaw(newType,
getRawData());
1252 assert(
isSplat() &&
"expected a splat type");
1254 ShapedType curType =
getType();
1255 if (curType == newType)
1258 assert(newType.getElementType() == curType.getElementType() &&
1259 "expected the same element type");
1260 return DenseIntOrFPElementsAttr::getRaw(newType,
getRawData());
1268 ShapedType curType =
getType();
1269 Type curElType = curType.getElementType();
1270 if (curElType == newElType)
1275 "expected element types with the same bitwidth");
1276 return DenseIntOrFPElementsAttr::getRaw(curType.clone(newElType),
1283 return llvm::cast<DenseIntElementsAttr>(*this).
mapValues(newElementType,
1289 return llvm::cast<DenseFPElementsAttr>(*this).
mapValues(newElementType,
1298 return getType().getElementType();
1302 return getType().getNumElements();
1310template <
typename APRangeT>
1313 APRangeT &&values) {
1314 size_t numValues = llvm::size(values);
1315 data.resize(llvm::divideCeil(storageWidth * numValues, CHAR_BIT));
1317 for (
auto it = values.begin(), e = values.end(); it != e;
1318 ++it, offset += storageWidth) {
1319 assert((*it).getBitWidth() <= storageWidth);
1324 if (numValues == 1 && (*values.begin()).getBitWidth() == 1)
1325 data[0] = data[0] ? -1 : 0;
1331DenseElementsAttr DenseIntOrFPElementsAttr::getRaw(ShapedType type,
1332 size_t storageWidth,
1333 ArrayRef<APFloat> values) {
1334 SmallVector<char> data;
1335 auto unwrapFloat = [](
const APFloat &val) {
return val.bitcastToAPInt(); };
1337 return DenseIntOrFPElementsAttr::getRaw(type, data);
1343DenseElementsAttr DenseIntOrFPElementsAttr::getRaw(ShapedType type,
1344 size_t storageWidth,
1345 ArrayRef<APInt> values) {
1346 SmallVector<char> data;
1348 return DenseIntOrFPElementsAttr::getRaw(type, data);
1351DenseElementsAttr DenseIntOrFPElementsAttr::getRaw(ShapedType type,
1352 ArrayRef<char> data) {
1353 assert(type.hasStaticShape() &&
"type must have static shape");
1354 bool isSplat =
false;
1355 bool isValid = isValidRawBuffer(type, data, isSplat);
1358 return Base::get(type.getContext(), type, data, isSplat);
1364DenseElementsAttr DenseIntOrFPElementsAttr::getRawComplex(ShapedType type,
1365 ArrayRef<char> data,
1366 int64_t dataEltSize,
1370 llvm::cast<ComplexType>(type.getElementType()).getElementType(),
1371 dataEltSize / 2, isInt, isSigned) &&
1372 "Try re-running with -debug-only=builtinattributes");
1374 int64_t numElements = data.size() / dataEltSize;
1376 assert(numElements == 1 || numElements == type.getNumElements());
1377 return getRaw(type, data);
1384DenseIntOrFPElementsAttr::getRawIntOrFloat(ShapedType type, ArrayRef<char> data,
1385 int64_t dataEltSize,
bool isInt,
1389 "Try re-running with -debug-only=builtinattributes");
1391 int64_t numElements = data.size() / dataEltSize;
1392 assert(numElements == 1 || numElements == type.getNumElements());
1394 return getRaw(type, data);
1397void DenseIntOrFPElementsAttr::convertEndianOfCharForBEmachine(
1398 const char *inRawData,
char *outRawData,
size_t elementBitWidth,
1399 size_t numElements) {
1400 using llvm::support::ulittle16_t;
1401 using llvm::support::ulittle32_t;
1402 using llvm::support::ulittle64_t;
1404 assert(llvm::endianness::native == llvm::endianness::big);
1408 switch (elementBitWidth) {
1410 const ulittle16_t *inRawDataPos =
1411 reinterpret_cast<const ulittle16_t *
>(inRawData);
1412 uint16_t *outDataPos =
reinterpret_cast<uint16_t *
>(outRawData);
1413 std::copy_n(inRawDataPos, numElements, outDataPos);
1417 const ulittle32_t *inRawDataPos =
1418 reinterpret_cast<const ulittle32_t *
>(inRawData);
1419 uint32_t *outDataPos =
reinterpret_cast<uint32_t *
>(outRawData);
1420 std::copy_n(inRawDataPos, numElements, outDataPos);
1424 const ulittle64_t *inRawDataPos =
1425 reinterpret_cast<const ulittle64_t *
>(inRawData);
1426 uint64_t *outDataPos =
reinterpret_cast<uint64_t *
>(outRawData);
1427 std::copy_n(inRawDataPos, numElements, outDataPos);
1431 size_t nBytes = elementBitWidth / CHAR_BIT;
1432 for (
size_t i = 0; i < nBytes; i++)
1433 std::copy_n(inRawData + (nBytes - 1 - i), 1, outRawData + i);
1439void DenseIntOrFPElementsAttr::convertEndianOfArrayRefForBEmachine(
1440 ArrayRef<char> inRawData, MutableArrayRef<char> outRawData,
1442 size_t numElements = type.getNumElements();
1443 Type elementType = type.getElementType();
1444 if (ComplexType complexTy = llvm::dyn_cast<ComplexType>(elementType)) {
1445 elementType = complexTy.getElementType();
1446 numElements = numElements * 2;
1449 assert(numElements * elementBitWidth == inRawData.size() * CHAR_BIT &&
1450 inRawData.size() <= outRawData.size());
1451 if (elementBitWidth <= CHAR_BIT)
1452 std::memcpy(outRawData.begin(), inRawData.begin(), inRawData.size());
1454 convertEndianOfCharForBEmachine(inRawData.begin(), outRawData.begin(),
1455 elementBitWidth, numElements);
1462template <
typename Fn,
typename Attr>
1464 Type newElementType,
1469 ShapedType newArrayType = inType.cloneWith(inType.getShape(), newElementType);
1471 size_t numRawElements = attr.isSplat() ? 1 : newArrayType.getNumElements();
1472 data.resize(llvm::divideCeil(storageBitWidth * numRawElements, CHAR_BIT));
1475 auto processElt = [&](
decltype(*attr.begin()) value,
size_t index) {
1476 auto newInt = mapping(value);
1477 assert(newInt.getBitWidth() == bitWidth);
1482 if (attr.isSplat()) {
1483 if (bitWidth == 1) {
1485 data[0] = mapping(*attr.begin()).isZero() ? 0 : -1;
1487 processElt(*attr.begin(), 0);
1489 return newArrayType;
1493 uint64_t elementIdx = 0;
1494 for (
auto value : attr)
1495 processElt(value, elementIdx++);
1496 return newArrayType;
1505 return getRaw(newArrayType, elementData);
1510 if (
auto denseAttr = llvm::dyn_cast<DenseElementsAttr>(attr))
1511 return llvm::isa<FloatType>(denseAttr.getType().getElementType());
1524 return getRaw(newArrayType, elementData);
1529 if (
auto denseAttr = llvm::dyn_cast<DenseElementsAttr>(attr))
1530 return denseAttr.getType().getElementType().isIntOrIndex();
1538DenseResourceElementsAttr
1539DenseResourceElementsAttr::get(ShapedType type,
1541 return Base::get(type.getContext(), type, handle);
1544DenseResourceElementsAttr DenseResourceElementsAttr::get(ShapedType type,
1551 return get(type, manager.insert(blobName, std::move(blob)));
1554ArrayRef<char> DenseResourceElementsAttr::getData() {
1555 if (AsmResourceBlob *blob = this->getRawHandle().getBlob())
1556 return blob->getDataAs<
char>();
1567template <
typename T>
1568struct DenseResourceAttrUtil;
1569template <
size_t w
idth,
bool isSigned>
1570struct DenseResourceElementsAttrIntUtil {
1571 static bool checkElementType(Type eltType) {
1572 IntegerType type = llvm::dyn_cast<IntegerType>(eltType);
1573 if (!type || type.getWidth() != width)
1575 return isSigned ? !type.isUnsigned() : !type.isSigned();
1579struct DenseResourceAttrUtil<bool> {
1580 static bool checkElementType(Type eltType) {
1585struct DenseResourceAttrUtil<int8_t>
1586 :
public DenseResourceElementsAttrIntUtil<8, true> {};
1588struct DenseResourceAttrUtil<uint8_t>
1589 :
public DenseResourceElementsAttrIntUtil<8, false> {};
1591struct DenseResourceAttrUtil<int16_t>
1592 :
public DenseResourceElementsAttrIntUtil<16, true> {};
1594struct DenseResourceAttrUtil<uint16_t>
1595 :
public DenseResourceElementsAttrIntUtil<16, false> {};
1597struct DenseResourceAttrUtil<int32_t>
1598 :
public DenseResourceElementsAttrIntUtil<32, true> {};
1600struct DenseResourceAttrUtil<uint32_t>
1601 :
public DenseResourceElementsAttrIntUtil<32, false> {};
1603struct DenseResourceAttrUtil<int64_t>
1604 :
public DenseResourceElementsAttrIntUtil<64, true> {};
1606struct DenseResourceAttrUtil<uint64_t>
1607 :
public DenseResourceElementsAttrIntUtil<64, false> {};
1609struct DenseResourceAttrUtil<float> {
1610 static bool checkElementType(Type eltType) {
return eltType.
isF32(); }
1613struct DenseResourceAttrUtil<double> {
1614 static bool checkElementType(Type eltType) {
return eltType.
isF64(); }
1618template <
typename T>
1619DenseResourceElementsAttrBase<T>
1624 "alignment mismatch between expected alignment and blob alignment");
1625 assert(((blob.
getData().size() %
sizeof(T)) == 0) &&
1626 "size mismatch between expected element width and blob size");
1627 assert(DenseResourceAttrUtil<T>::checkElementType(type.getElementType()) &&
1628 "invalid shape element type for provided type `T`");
1629 return llvm::cast<DenseResourceElementsAttrBase<T>>(
1630 DenseResourceElementsAttr::get(type, blobName, std::move(blob)));
1633template <
typename T>
1634std::optional<ArrayRef<T>>
1637 return blob->template getDataAs<T>();
1638 return std::nullopt;
1641template <
typename T>
1643 auto resourceAttr = llvm::dyn_cast<DenseResourceElementsAttr>(attr);
1644 return resourceAttr && DenseResourceAttrUtil<T>::checkElementType(
1645 resourceAttr.getElementType());
1670APFloat SparseElementsAttr::getZeroAPFloat()
const {
1672 return APFloat(eltType.getFloatSemantics());
1676APInt SparseElementsAttr::getZeroAPInt()
const {
1678 return APInt::getZero(eltType.getWidth());
1682Attribute SparseElementsAttr::getZeroAttr()
const {
1686 if (llvm::isa<FloatType>(eltType))
1687 return FloatAttr::get(eltType, 0);
1690 if (
auto complexTy = llvm::dyn_cast<ComplexType>(eltType)) {
1691 auto eltType = complexTy.getElementType();
1693 if (llvm::isa<FloatType>(eltType))
1694 zero = FloatAttr::get(eltType, 0);
1696 zero = IntegerAttr::get(eltType, 0);
1697 return ArrayAttr::get(complexTy.getContext(),
1698 ArrayRef<Attribute>{zero, zero});
1702 if (llvm::isa<DenseStringElementsAttr>(getValues()))
1703 return StringAttr::get(
"", eltType);
1706 return IntegerAttr::get(eltType, 0);
1711SmallVector<ptrdiff_t> SparseElementsAttr::getFlattenedSparseIndices()
const {
1712 SmallVector<ptrdiff_t> flatSparseIndices;
1717 auto sparseIndexValues = sparseIndices.getValues<uint64_t>();
1718 if (sparseIndices.isSplat()) {
1720 *sparseIndexValues.begin());
1721 flatSparseIndices.push_back(getFlattenedIndex(
indices));
1722 return flatSparseIndices;
1726 auto numSparseIndices = sparseIndices.getType().getDimSize(0);
1727 size_t rank =
getType().getRank();
1728 for (
size_t i = 0, e = numSparseIndices; i != e; ++i)
1729 flatSparseIndices.push_back(getFlattenedIndex(
1730 {&*std::next(sparseIndexValues.begin(), i * rank), rank}));
1731 return flatSparseIndices;
1736 ShapedType type, DenseIntElementsAttr sparseIndices,
1737 DenseElementsAttr values) {
1738 ShapedType valuesType = values.
getType();
1739 if (valuesType.getRank() != 1)
1740 return emitError() <<
"expected 1-d tensor for sparse element values";
1743 ShapedType indicesType = sparseIndices.getType();
1744 auto emitShapeError = [&]() {
1745 return emitError() <<
"expected shape ([" << type.getShape()
1746 <<
"]); inferred shape of indices literal (["
1747 << indicesType.getShape()
1748 <<
"]); inferred shape of values literal (["
1749 << valuesType.getShape() <<
"])";
1752 size_t rank = type.getRank(), indicesRank = indicesType.getRank();
1753 if (indicesRank == 2) {
1754 if (indicesType.getDimSize(1) !=
static_cast<int64_t
>(rank))
1755 return emitShapeError();
1756 }
else if (indicesRank != 1 || rank != 1) {
1757 return emitShapeError();
1760 int64_t numSparseIndices = indicesType.getDimSize(0);
1761 if (numSparseIndices != valuesType.getDimSize(0))
1762 return emitShapeError();
1765 auto emitIndexError = [&](
unsigned indexNum, ArrayRef<uint64_t> index) {
1767 <<
"sparse index #" << indexNum
1768 <<
" is not contained within the value shape, with index=[" << index
1769 <<
"], and type=" << type;
1773 auto sparseIndexValues = sparseIndices.getValues<uint64_t>();
1774 if (sparseIndices.isSplat()) {
1775 SmallVector<uint64_t>
indices(rank, *sparseIndexValues.begin());
1776 if (!ElementsAttr::isValidIndex(type,
indices))
1777 return emitIndexError(0,
indices);
1782 for (
size_t i = 0, e = numSparseIndices; i != e; ++i) {
1783 ArrayRef<uint64_t> index(&*std::next(sparseIndexValues.begin(), i * rank),
1785 if (!ElementsAttr::isValidIndex(type, index))
1786 return emitIndexError(i, index);
1801 return getImpl()->referencedAttr;
1812 unsigned nSymbols = 0;
1816 if (ShapedType::isStatic(offset)) {
1826 for (
const auto &en : llvm::enumerate(strides)) {
1827 auto dim = en.index();
1828 auto stride = en.value();
1832 if (ShapedType::isStatic(stride))
1837 expr = expr + d * mult;
static bool isValidIntOrFloat(Type type, int64_t dataEltSize, bool isInt, bool isSigned)
Check the information for a C++ data type, check if this type is valid for the current attribute.
static void copyAPIntToArrayForBEmachine(APInt value, size_t numBytes, char *result)
Copy actual numBytes data from value (APInt) to char array(result) for BE format.
static ShapedType mappingHelper(Fn mapping, Attr &attr, ShapedType inType, Type newElementType, llvm::SmallVectorImpl< char > &data)
static void setBit(char *rawData, size_t bitPos, bool value)
Set a bit to a specific value.
static bool hasSameNumElementsOrSplat(ShapedType type, const Values &values)
Returns true if 'values' corresponds to a splat, i.e.
static void writeAPIntsToBuffer(size_t storageWidth, SmallVectorImpl< char > &data, APRangeT &&values)
Utility method to write a range of APInt values to a buffer.
static void writeBits(char *rawData, size_t bitPos, APInt value)
Writes value to the bit position bitPos in array rawData.
static bool dictionaryAttrSort(ArrayRef< NamedAttribute > value, SmallVectorImpl< NamedAttribute > &storage)
Helper function that does either an in place sort or sorts from source array into destination.
static std::optional< NamedAttribute > findDuplicateElement(ArrayRef< NamedAttribute > value)
Returns an entry with a duplicate name from the given sorted array of named attributes.
static size_t getDenseElementStorageWidth(size_t origWidth)
Get the bitwidth of a dense element type within the buffer.
static void copyArrayToAPIntForBEmachine(const char *inArray, size_t numBytes, APInt &result)
Copy numBytes data from inArray(char array) to result(APINT) for BE format.
static bool getBit(const char *rawData, size_t bitPos)
Return the value of the specified bit.
static bool isComplexOfIntType(Type type)
Return if the given complex type has an integer element type.
static APInt readBits(const char *rawData, size_t bitPos, size_t bitWidth)
Reads the next bitWidth bits from the bit position bitPos in array rawData.
static Type getElementType(Type type)
Determine the element type of type.
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
Base type for affine expression.
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
This base class exposes generic asm parser hooks, usable across the various derived parsers.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
MLIRContext * getContext() const
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseFloat(double &result)=0
Parse a floating point value from the stream.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual raw_ostream & getStream() const
Return the raw output stream used by this printer.
This class represents a processed binary blob of data.
size_t getDataAlignment() const
Return the alignment of the underlying data.
ArrayRef< char > getData() const
Return the raw underlying data of this blob.
Attributes are known-constant values of operations.
void print(raw_ostream &os, bool elideType=false) const
Print the attribute.
MLIRContext * getContext() const
Return the context this attribute belongs to.
static Attribute getFromOpaquePointer(const void *ptr)
Construct an attribute from the opaque pointer representation.
Special case of IntegerAttr to represent boolean integers, i.e., signless i1 integers.
static bool classof(Attribute attr)
Methods for support type inquiry through isa, cast, and dyn_cast.
constexpr Attribute()=default
bool getValue() const
Return the boolean value of this attribute.
Attribute operator*() const
Accesses the Attribute value at this iterator position.
A utility iterator that allows walking over the internal bool values.
bool operator*() const
Accesses the bool value at this iterator position.
Iterator for walking over complex APFloat values.
A utility iterator that allows walking over the internal raw complex APInt values.
std::complex< APInt > operator*() const
Accesses the raw std::complex<APInt> value at this iterator position.
Iterator for walking over APFloat values.
A utility iterator that allows walking over the internal raw APInt values.
APInt operator*() const
Accesses the raw APInt value at this iterator position.
An attribute that represents a reference to a dense vector or tensor object.
ArrayRef< StringRef > getRawStringData() const
Return the raw StringRef data held by this attribute.
IntElementIterator raw_int_begin() const
Iterators to various elements that require out-of-line definition.
static DenseElementsAttr getRawIntOrFloat(ShapedType type, ArrayRef< char > data, int64_t dataEltSize, bool isInt, bool isSigned)
Overload of the raw 'get' method that asserts that the given type is of integer or floating-point typ...
static DenseElementsAttr getRawComplex(ShapedType type, ArrayRef< char > data, int64_t dataEltSize, bool isInt, bool isSigned)
Overload of the raw 'get' method that asserts that the given type is of complex type.
static bool classof(Attribute attr)
Method for support type inquiry through isa, cast and dyn_cast.
bool isValidComplex(int64_t dataEltSize, bool isInt, bool isSigned) const
DenseElementsAttr resizeSplat(ShapedType newType)
Return a new DenseElementsAttr that has the same data as the current attribute, but with a different ...
detail::ElementsAttrRange< IteratorT > iterator_range_impl
The iterator range over the given iterator type T.
int64_t getNumElements() const
Returns the number of elements held by this attribute.
static DenseElementsAttr getFromRawBuffer(ShapedType type, ArrayRef< char > rawBuffer)
Construct a dense elements attribute from a raw buffer representing the data for this attribute.
int64_t size() const
Returns the number of elements held by this attribute.
bool isSplat() const
Returns true if this attribute corresponds to a splat, i.e.
ArrayRef< char > getRawData() const
Return the raw storage data held by this attribute.
constexpr Attribute()=default
DenseElementsAttr mapValues(Type newElementType, function_ref< APInt(const APInt &)> mapping) const
Generates a new DenseElementsAttr by mapping each int value to a new underlying APInt.
Type getElementType() const
Return the element type of this DenseElementsAttr.
FailureOr< iterator_range_impl< ComplexFloatElementIterator > > tryGetComplexFloatValues() const
IntElementIterator raw_int_end() const
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
ShapedType getType() const
Return the type of this ElementsAttr, guaranteed to be a vector or tensor with static shape.
FailureOr< iterator_range_impl< FloatElementIterator > > tryGetFloatValues() const
static bool isValidRawBuffer(ShapedType type, ArrayRef< char > rawBuffer, bool &detectedSplat)
Returns true if the given buffer is a valid raw buffer for the given type.
DenseElementsAttr bitcast(Type newElType)
Return a new DenseElementsAttr that has the same data as the current attribute, but has bitcast eleme...
bool isValidIntOrFloat(int64_t dataEltSize, bool isInt, bool isSigned) const
DenseElementsAttr reshape(ShapedType newType)
Return a new DenseElementsAttr that has the same data as the current attribute, but has been reshaped...
FailureOr< iterator_range_impl< ComplexIntElementIterator > > tryGetComplexIntValues() const
static bool classof(Attribute attr)
Method for supporting type inquiry through isa, cast and dyn_cast.
DenseElementsAttr mapValues(Type newElementType, function_ref< APInt(const APFloat &)> mapping) const
Generates a new DenseElementsAttr by mapping each value attribute, and constructing the DenseElements...
static bool classof(Attribute attr)
Method for supporting type inquiry through isa, cast and dyn_cast.
DenseElementsAttr mapValues(Type newElementType, function_ref< APInt(const APInt &)> mapping) const
Generates a new DenseElementsAttr by mapping each value attribute, and constructing the DenseElements...
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
static bool isValidNamespace(StringRef str)
Utility function that returns if the given string is a valid dialect namespace.
An attribute that associates a referenced attribute with a unique identifier.
static DistinctAttr create(Attribute referencedAttr)
Creates a distinct attribute that associates a referenced attribute with a unique identifier.
Attribute getReferencedAttr() const
Returns the referenced attribute.
A symbol reference with a reference path containing a single element.
This class represents a diagnostic that is inflight and set to be reported.
MLIRContext is the top-level object for a collection of MLIR operations.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
bool allowsUnregisteredDialects()
Return true if we allow to create operation for unregistered dialects.
NamedAttribute represents a combination of a name and an Attribute value.
Operation is the basic unit of execution within MLIR.
AttrClass getAttrOfType(StringAttr name)
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
bool isSignlessInteger() const
Return true if this is a signless integer type (with the specified width).
bool isIntOrIndexOrFloat() const
Return true if this is an integer (of any signedness), index, or float type.
bool isInteger() const
Return true if this is an integer type (with the specified width).
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
Base class for DenseArrayAttr that is instantiated and specialized for each supported element type be...
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< T > content)
Builder from ArrayRef<T>.
static bool classof(Attribute attr)
Support for isa<>/cast<>.
ArrayRef< T > asArrayRef() const
void print(AsmPrinter &printer) const
Print the short form [42, 100, -1] without any type prefix.
static Attribute parse(AsmParser &parser, Type type)
Parse the short form [42, 100, -1] without any type prefix.
static Attribute parseWithoutBraces(AsmParser &parser, Type type)
Parse the short form 42, 100, -1 without any type prefix or braces.
void printWithoutBraces(raw_ostream &os) const
Print the short form 42, 100, -1 without any braces or type prefix.
Impl iterator for indexed DenseElementsAttr iterators that records a data pointer and data index that...
ptrdiff_t getDataIndex() const
const char * getData() const
Base class for DenseResourceElementsAttr that is instantiated and specialized for each supported elem...
static bool classof(Attribute attr)
Support for isa<>/cast<>.
static DenseResourceElementsAttrBase< T > get(ShapedType type, StringRef blobName, AsmResourceBlob blob)
A builder that inserts a new resource using the provided blob.
std::optional< ArrayRef< T > > tryGetAsArrayRef() const
Return the data of this attribute as an ArrayRef<T> if it is present, returns std::nullopt otherwise.
static ConcreteT get(MLIRContext *ctx, Args &&...args)
Get or create a new ConcreteT instance within the ctx.
ImplType * getImpl() const
size_t getDenseElementBitWidth(Type eltType)
Return the bit width which DenseElementsAttr should use for this type.
Operation::operand_range getIndices(Operation *op)
Get the indices that the given load/store operation is operating on.
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
DialectResourceBlobHandle< BuiltinDialect > DenseResourceElementsHandle
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
AffineMap makeStridedLinearLayoutMap(ArrayRef< int64_t > strides, int64_t offset, MLIRContext *context)
Given a list of strides (in which ShapedType::kDynamic represents a dynamic value),...
AffineExpr getAffineConstantExpr(int64_t constant, MLIRContext *context)
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
AffineExpr getAffineDimExpr(unsigned position, MLIRContext *context)
These free functions allow clients of the API to not use classes in detail.
llvm::function_ref< Fn > function_ref
AffineExpr getAffineSymbolExpr(unsigned position, MLIRContext *context)
static ManagerInterface & getManagerInterface(MLIRContext *ctx)
An attribute representing a reference to a dense vector or tensor object.
An attribute representing a reference to a dense vector or tensor object.
static const char kSplatTrue
The values used to denote a boolean splat value.
static const char kSplatFalse
An attribute representing a reference to a dense vector or tensor object containing strings.