13 #ifndef ATTRIBUTEDETAIL_H_ 14 #define ATTRIBUTEDETAIL_H_ 22 #include "llvm/ADT/APFloat.h" 23 #include "llvm/ADT/PointerIntPair.h" 24 #include "llvm/Support/TrailingObjects.h" 36 if (ComplexType comp = eltType.
dyn_cast<ComplexType>())
39 return IndexType::kInternalStorageBitWidth;
47 : type(type), isSplat(isSplat) {}
86 if (key.
type.getElementType().isInteger(1)) {
90 return (key.
data.front() & 1) == data.front();
94 return key.
data == data;
104 return KeyTy(ty, data, 0);
114 size_t numElements = ty.getNumElements();
115 assert(numElements != 1 &&
"splat of 1 element should already be detected");
118 if (ty.getElementType().isInteger(1) == 1)
119 return getKeyForBoolData(ty, data, numElements);
123 size_t storageSize = llvm::divideCeil(elementWidth, CHAR_BIT);
124 assert(((data.size() / storageSize) == numElements) &&
125 "data does not hold expected number of elements");
128 auto firstElt = data.take_front(storageSize);
133 for (
size_t i = storageSize, e = data.size(); i != e; i += storageSize)
134 if (memcmp(data.data(), &data[i], storageSize))
135 return KeyTy(ty, data, llvm::hash_combine(hashVal, data.drop_front(i)));
138 return KeyTy(ty, firstElt, hashVal,
true);
143 size_t numElements) {
145 bool splatValue = splatData.front() & 1;
148 auto generateSplatKey = [=] {
149 return KeyTy(ty, data.take_front(1),
156 size_t numOddElements = numElements % CHAR_BIT;
157 if (splatValue && numOddElements != 0) {
159 char lastElt = splatData.back();
160 if (lastElt != llvm::maskTrailingOnes<unsigned char>(numOddElements))
164 if (splatData.size() == 1)
165 return generateSplatKey();
166 splatData = splatData.drop_back();
170 char mask = splatValue ? ~0 : 0;
171 return llvm::all_of(splatData, [mask](
char c) {
return c == mask; })
188 char *rawData =
reinterpret_cast<char *
>(
189 allocator.
allocate(data.size(),
alignof(uint64_t)));
190 std::memcpy(rawData, data.data(), data.size());
193 if (key.
isSplat && key.
type.getElementType().isInteger(1))
237 return key.
data == data;
248 return KeyTy(ty, data, 0);
256 assert(ty.getNumElements() != 1 &&
257 "splat of 1 element should already be detected");
260 const auto &firstElt = data.front();
265 for (
size_t i = 1, e = data.size(); i != e; i++)
266 if (!firstElt.equals(data[i]))
267 return KeyTy(ty, data, llvm::hash_combine(hashVal, data.drop_front(i)));
270 return KeyTy(ty, data.take_front(), hashVal,
true);
289 int numEntries = key.
isSplat ? 1 : data.size();
293 size_t dataSize =
sizeof(StringRef) * numEntries;
294 for (
int i = 0; i < numEntries; i++)
295 dataSize += data[i].size();
297 char *rawData =
reinterpret_cast<char *
>(
298 allocator.
allocate(dataSize,
alignof(uint64_t)));
303 reinterpret_cast<StringRef *
>(rawData), numEntries);
304 auto *stringData = rawData + numEntries *
sizeof(StringRef);
306 for (
int i = 0; i < numEntries; i++) {
307 memcpy(stringData, data[i].data(), data[i].size());
308 mutableCopy[i] = StringRef(stringData, data[i].size());
309 stringData += data[i].size();
328 : type(type), value(value), referencedDialect(nullptr) {}
331 using KeyTy = std::pair<StringRef, Type>;
333 return value == key.first &&
type == key.second;
362 #endif // ATTRIBUTEDETAIL_H_ Include the generated interface declarations.
ArrayRef< char > data
The raw buffer for the data storage.
Dialect * referencedDialect
If the string value contains a dialect namespace prefix (e.g.
StringRef value
The raw string value.
KeyTy(ShapedType type, ArrayRef< StringRef > data, llvm::hash_code hashCode, bool isSplat=false)
static llvm::hash_code hashKey(const KeyTy &key)
Hash the key for the storage.
static void copy(Location loc, Value dst, Value src, Value size, OpBuilder &builder)
Copies the given number of bytes from src to dst pointers.
This is a utility allocator used to allocate memory for instances of derived types.
static KeyTy getKey(ShapedType ty, ArrayRef< char > data, bool isKnownSplat)
Construct a key from a shaped type, raw data buffer, and a flag that signals if the data is already k...
bool isSplat
A boolean that indicates if this data is a splat or not.
llvm::hash_code hash_value(const MPInt &x)
Redeclarations of friend declaration above to make it discoverable by lookups.
bool isSplat
A boolean that indicates if this data is a splat or not.
static KeyTy getKeyForBoolData(ShapedType ty, ArrayRef< char > data, size_t numElements)
Construct a key with a set of boolean data.
static constexpr const bool value
static DenseIntOrFPElementsAttrStorage * construct(AttributeStorageAllocator &allocator, KeyTy key)
Construct a new storage instance.
bool operator==(const KeyTy &key) const
T * allocate()
Allocate an instance of the provided type.
::llvm::hash_code hashKey(const KeyTy &key)
An attribute representing a reference to a dense vector or tensor object containing strings...
An attribute representing a reference to a dense vector or tensor object.
An attribute representing a reference to a dense vector or tensor object.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
std::pair< StringRef, Type > KeyTy
The hash key is a tuple of the parameter types.
static KeyTy getKey(ShapedType ty, ArrayRef< StringRef > data, bool isKnownSplat)
Construct a key from a shaped type, StringRef data buffer, and a flag that signals if the data is alr...
bool operator==(const KeyTy &key) const
Compare this storage instance with the provided key.
void initialize(MLIRContext *context)
Default initialization for attribute storage classes that require no additional initialization.
DenseElementsAttributeStorage(ShapedType type, bool isSplat)
ShapedType type
The type of the dense elements.
llvm::hash_code hashCode
The computed hash code for the storage data.
size_t getDenseElementBitWidth(Type eltType)
Return the bit width which DenseElementsAttr should use for this type.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
ArrayRef< StringRef > data
static DenseStringElementsAttrStorage * construct(AttributeStorageAllocator &allocator, KeyTy key)
Construct a new storage instance.
MLIRContext is the top-level object for a collection of MLIR operations.
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
bool operator==(const KeyTy &key) const
Compare this storage instance with the provided key.
StringAttrStorage(StringRef value, Type type)
Base storage class appearing in an attribute.
ArrayRef< T > copyInto(ArrayRef< T > elements)
Copy the specified array of elements into memory managed by our bump pointer allocator.
static StringAttrStorage * construct(AttributeStorageAllocator &allocator, const KeyTy &key)
Define a construction method for creating a new instance of this storage.
llvm::hash_code hashCode
The computed hash code for the storage data.
DenseIntOrFPElementsAttrStorage(ShapedType ty, ArrayRef< char > data, bool isSplat=false)
Type type
The type of the string.
static llvm::hash_code hashKey(const KeyTy &key)
Hash the key for the storage.
ArrayRef< StringRef > data
The raw buffer for the data storage.
KeyTy(ShapedType type, ArrayRef< char > data, llvm::hash_code hashCode, bool isSplat=false)
ShapedType type
The type of the dense elements.
DenseStringElementsAttrStorage(ShapedType ty, ArrayRef< StringRef > data, bool isSplat=false)