2018-10-26 06:46:10 +08:00
|
|
|
//===- AttributeDetail.h - MLIR Affine Map details Class --------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// Copyright 2019 The MLIR Authors.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
// =============================================================================
|
|
|
|
//
|
|
|
|
// This holds implementation details of Attribute.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef ATTRIBUTEDETAIL_H_
|
|
|
|
#define ATTRIBUTEDETAIL_H_
|
|
|
|
|
2018-10-26 13:39:14 +08:00
|
|
|
#include "mlir/IR/AffineMap.h"
|
2018-10-26 06:46:10 +08:00
|
|
|
#include "mlir/IR/Attributes.h"
|
2019-02-27 10:01:46 +08:00
|
|
|
#include "mlir/IR/Identifier.h"
|
2018-10-26 13:39:14 +08:00
|
|
|
#include "mlir/IR/IntegerSet.h"
|
2018-10-26 06:46:10 +08:00
|
|
|
#include "mlir/IR/MLIRContext.h"
|
2019-01-04 06:29:52 +08:00
|
|
|
#include "mlir/IR/StandardTypes.h"
|
2019-05-01 01:31:29 +08:00
|
|
|
#include "mlir/Support/StorageUniquer.h"
|
2018-11-16 09:53:51 +08:00
|
|
|
#include "llvm/ADT/APFloat.h"
|
2018-10-26 13:39:14 +08:00
|
|
|
#include "llvm/Support/TrailingObjects.h"
|
2018-10-26 06:46:10 +08:00
|
|
|
|
|
|
|
namespace mlir {
|
|
|
|
namespace detail {
|
|
|
|
/// Base storage class appearing in an attribute.
|
2019-05-01 01:31:29 +08:00
|
|
|
struct AttributeStorage : public StorageUniquer::BaseStorage {
|
|
|
|
AttributeStorage(bool isOrContainsFunctionCache = false)
|
|
|
|
: isOrContainsFunctionCache(isOrContainsFunctionCache) {}
|
2018-10-26 06:46:10 +08:00
|
|
|
|
|
|
|
/// This field is true if this is, or contains, a function attribute.
|
|
|
|
bool isOrContainsFunctionCache : 1;
|
|
|
|
};
|
|
|
|
|
2019-05-01 01:31:29 +08:00
|
|
|
// A utility class to get, or create, unique instances of attributes within an
|
|
|
|
// MLIRContext. This class manages all creation and uniquing of attributes.
|
|
|
|
class AttributeUniquer {
|
|
|
|
public:
|
|
|
|
/// Get an uniqued instance of attribute T. This overload is used for
|
|
|
|
/// derived attributes that have complex storage or uniquing constraints.
|
|
|
|
template <typename T, typename... Args>
|
|
|
|
static typename std::enable_if<
|
|
|
|
!std::is_same<typename T::ImplType, AttributeStorage>::value, T>::type
|
|
|
|
get(MLIRContext *ctx, Attribute::Kind kind, Args &&... args) {
|
|
|
|
return ctx->getAttributeUniquer().getComplex<typename T::ImplType>(
|
|
|
|
/*initFn=*/{}, static_cast<unsigned>(kind),
|
|
|
|
std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get an uniqued instance of attribute T. This overload is used for
|
|
|
|
/// derived attributes that use the AttributeStorage directly and thus need no
|
|
|
|
/// additional storage or uniquing.
|
|
|
|
template <typename T, typename... Args>
|
|
|
|
static typename std::enable_if<
|
|
|
|
std::is_same<typename T::ImplType, AttributeStorage>::value, T>::type
|
|
|
|
get(MLIRContext *ctx, Attribute::Kind kind) {
|
|
|
|
return ctx->getAttributeUniquer().getSimple<AttributeStorage>(
|
|
|
|
/*initFn=*/{}, static_cast<unsigned>(kind));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Erase a uniqued instance of attribute T. This overload is used for
|
|
|
|
/// derived attributes that have complex storage or uniquing constraints.
|
|
|
|
template <typename T, typename... Args>
|
|
|
|
static typename std::enable_if<
|
|
|
|
!std::is_same<typename T::ImplType, AttributeStorage>::value>::type
|
|
|
|
erase(MLIRContext *ctx, Attribute::Kind kind, Args &&... args) {
|
|
|
|
return ctx->getAttributeUniquer().eraseComplex<typename T::ImplType>(
|
|
|
|
static_cast<unsigned>(kind), std::forward<Args>(args)...);
|
|
|
|
}
|
2019-04-26 00:56:09 +08:00
|
|
|
};
|
|
|
|
|
2019-05-01 01:31:29 +08:00
|
|
|
using AttributeStorageAllocator = StorageUniquer::StorageAllocator;
|
|
|
|
|
2018-10-26 06:46:10 +08:00
|
|
|
/// An attribute representing a boolean value.
|
|
|
|
struct BoolAttributeStorage : public AttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = std::pair<MLIRContext *, bool>;
|
|
|
|
|
|
|
|
BoolAttributeStorage(Type type, bool value) : type(type), value(value) {}
|
|
|
|
|
|
|
|
/// We only check equality for and hash with the boolean key parameter.
|
|
|
|
bool operator==(const KeyTy &key) const { return key.second == value; }
|
|
|
|
static unsigned hashKey(const KeyTy &key) {
|
|
|
|
return llvm::hash_value(key.second);
|
|
|
|
}
|
|
|
|
|
|
|
|
static BoolAttributeStorage *construct(AttributeStorageAllocator &allocator,
|
|
|
|
const KeyTy &key) {
|
|
|
|
return new (allocator.allocate<BoolAttributeStorage>())
|
|
|
|
BoolAttributeStorage(IntegerType::get(1, key.first), key.second);
|
|
|
|
}
|
|
|
|
|
|
|
|
Type type;
|
2018-10-26 06:46:10 +08:00
|
|
|
bool value;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// An attribute representing a integral value.
|
2018-11-12 22:33:22 +08:00
|
|
|
struct IntegerAttributeStorage final
|
|
|
|
: public AttributeStorage,
|
|
|
|
public llvm::TrailingObjects<IntegerAttributeStorage, uint64_t> {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = std::pair<Type, APInt>;
|
|
|
|
|
2019-03-23 15:40:25 +08:00
|
|
|
IntegerAttributeStorage(Type type, size_t numObjects)
|
2019-05-01 01:31:29 +08:00
|
|
|
: type(type), numObjects(numObjects) {
|
2018-11-16 09:53:51 +08:00
|
|
|
assert((type.isIndex() || type.isa<IntegerType>()) && "invalid type");
|
|
|
|
}
|
|
|
|
|
2019-05-01 01:31:29 +08:00
|
|
|
/// Key equality and hash functions.
|
|
|
|
bool operator==(const KeyTy &key) const {
|
|
|
|
return key == KeyTy(type, getValue());
|
|
|
|
}
|
|
|
|
static unsigned hashKey(const KeyTy &key) {
|
|
|
|
return llvm::hash_combine(key.first, llvm::hash_value(key.second));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static IntegerAttributeStorage *
|
|
|
|
construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
|
|
|
|
Type type;
|
|
|
|
APInt value;
|
|
|
|
std::tie(type, value) = key;
|
|
|
|
|
|
|
|
auto elements = ArrayRef<uint64_t>(value.getRawData(), value.getNumWords());
|
|
|
|
auto size =
|
|
|
|
IntegerAttributeStorage::totalSizeToAlloc<uint64_t>(elements.size());
|
|
|
|
auto rawMem = allocator.allocate(size, alignof(IntegerAttributeStorage));
|
|
|
|
auto result = ::new (rawMem) IntegerAttributeStorage(type, elements.size());
|
|
|
|
std::uninitialized_copy(elements.begin(), elements.end(),
|
|
|
|
result->getTrailingObjects<uint64_t>());
|
|
|
|
return result;
|
|
|
|
}
|
2018-11-12 22:33:22 +08:00
|
|
|
|
|
|
|
/// Returns an APInt representing the stored value.
|
|
|
|
APInt getValue() const {
|
2018-11-16 09:53:51 +08:00
|
|
|
if (type.isIndex())
|
|
|
|
return APInt(64, {getTrailingObjects<uint64_t>(), numObjects});
|
2018-12-18 02:05:56 +08:00
|
|
|
return APInt(type.getIntOrFloatBitWidth(),
|
2018-11-16 09:53:51 +08:00
|
|
|
{getTrailingObjects<uint64_t>(), numObjects});
|
2018-11-12 22:33:22 +08:00
|
|
|
}
|
2019-05-01 01:31:29 +08:00
|
|
|
|
|
|
|
Type type;
|
|
|
|
size_t numObjects;
|
2018-10-26 06:46:10 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/// An attribute representing a floating point value.
|
|
|
|
struct FloatAttributeStorage final
|
|
|
|
: public AttributeStorage,
|
|
|
|
public llvm::TrailingObjects<FloatAttributeStorage, uint64_t> {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = std::pair<Type, APFloat>;
|
|
|
|
|
2019-03-23 15:40:25 +08:00
|
|
|
FloatAttributeStorage(const llvm::fltSemantics &semantics, Type type,
|
2018-11-16 09:53:51 +08:00
|
|
|
size_t numObjects)
|
2019-05-01 01:31:29 +08:00
|
|
|
: semantics(semantics), type(type.cast<FloatType>()),
|
|
|
|
numObjects(numObjects) {}
|
|
|
|
|
|
|
|
/// Key equality and hash functions.
|
|
|
|
bool operator==(const KeyTy &key) const {
|
|
|
|
return key.first == type && key.second.bitwiseIsEqual(getValue());
|
|
|
|
}
|
|
|
|
static unsigned hashKey(const KeyTy &key) {
|
|
|
|
return llvm::hash_combine(key.first, llvm::hash_value(key.second));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static FloatAttributeStorage *construct(AttributeStorageAllocator &allocator,
|
|
|
|
const KeyTy &key) {
|
|
|
|
const auto &apint = key.second.bitcastToAPInt();
|
|
|
|
|
|
|
|
// Here one word's bitwidth equals to that of uint64_t.
|
|
|
|
auto elements = ArrayRef<uint64_t>(apint.getRawData(), apint.getNumWords());
|
|
|
|
|
|
|
|
auto byteSize =
|
|
|
|
FloatAttributeStorage::totalSizeToAlloc<uint64_t>(elements.size());
|
|
|
|
auto rawMem = allocator.allocate(byteSize, alignof(FloatAttributeStorage));
|
|
|
|
auto result = ::new (rawMem) FloatAttributeStorage(
|
|
|
|
key.second.getSemantics(), key.first, elements.size());
|
|
|
|
std::uninitialized_copy(elements.begin(), elements.end(),
|
|
|
|
result->getTrailingObjects<uint64_t>());
|
|
|
|
return result;
|
|
|
|
}
|
2018-10-26 06:46:10 +08:00
|
|
|
|
|
|
|
/// Returns an APFloat representing the stored value.
|
|
|
|
APFloat getValue() const {
|
|
|
|
auto val = APInt(APFloat::getSizeInBits(semantics),
|
|
|
|
{getTrailingObjects<uint64_t>(), numObjects});
|
|
|
|
return APFloat(semantics, val);
|
|
|
|
}
|
2019-05-01 01:31:29 +08:00
|
|
|
|
|
|
|
const llvm::fltSemantics &semantics;
|
|
|
|
FloatType type;
|
|
|
|
size_t numObjects;
|
2018-10-26 06:46:10 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/// An attribute representing a string value.
|
|
|
|
struct StringAttributeStorage : public AttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = StringRef;
|
|
|
|
|
|
|
|
StringAttributeStorage(StringRef value) : value(value) {}
|
|
|
|
|
|
|
|
/// Key equality function.
|
|
|
|
bool operator==(const KeyTy &key) const { return key == value; }
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static StringAttributeStorage *construct(AttributeStorageAllocator &allocator,
|
|
|
|
const KeyTy &key) {
|
|
|
|
return new (allocator.allocate<StringAttributeStorage>())
|
|
|
|
StringAttributeStorage(allocator.copyInto(key));
|
|
|
|
}
|
|
|
|
|
2018-10-26 06:46:10 +08:00
|
|
|
StringRef value;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// An attribute representing an array of other attributes.
|
|
|
|
struct ArrayAttributeStorage : public AttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = ArrayRef<Attribute>;
|
|
|
|
|
2019-03-23 15:40:25 +08:00
|
|
|
ArrayAttributeStorage(bool hasFunctionAttr, ArrayRef<Attribute> value)
|
2019-05-01 01:31:29 +08:00
|
|
|
: AttributeStorage(hasFunctionAttr), value(value) {}
|
|
|
|
|
|
|
|
/// Key equality function.
|
|
|
|
bool operator==(const KeyTy &key) const { return key == value; }
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static ArrayAttributeStorage *construct(AttributeStorageAllocator &allocator,
|
|
|
|
const KeyTy &key) {
|
|
|
|
// Check to see if any of the elements have a function attr.
|
|
|
|
bool hasFunctionAttr = llvm::any_of(
|
|
|
|
key, [](Attribute elt) { return elt.isOrContainsFunction(); });
|
|
|
|
|
|
|
|
// Initialize the memory using placement new.
|
|
|
|
return new (allocator.allocate<ArrayAttributeStorage>())
|
|
|
|
ArrayAttributeStorage(hasFunctionAttr, allocator.copyInto(key));
|
|
|
|
}
|
|
|
|
|
2018-10-26 06:46:10 +08:00
|
|
|
ArrayRef<Attribute> value;
|
|
|
|
};
|
|
|
|
|
|
|
|
// An attribute representing a reference to an affine map.
|
|
|
|
struct AffineMapAttributeStorage : public AttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = AffineMap;
|
|
|
|
|
|
|
|
AffineMapAttributeStorage(AffineMap value) : value(value) {}
|
|
|
|
|
|
|
|
/// Key equality function.
|
|
|
|
bool operator==(const KeyTy &key) const { return key == value; }
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static AffineMapAttributeStorage *
|
|
|
|
construct(AttributeStorageAllocator &allocator, KeyTy key) {
|
|
|
|
return new (allocator.allocate<AffineMapAttributeStorage>())
|
|
|
|
AffineMapAttributeStorage(key);
|
|
|
|
}
|
|
|
|
|
2018-10-26 06:46:10 +08:00
|
|
|
AffineMap value;
|
|
|
|
};
|
|
|
|
|
2018-10-26 13:13:03 +08:00
|
|
|
// An attribute representing a reference to an integer set.
|
|
|
|
struct IntegerSetAttributeStorage : public AttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = IntegerSet;
|
|
|
|
|
|
|
|
IntegerSetAttributeStorage(IntegerSet value) : value(value) {}
|
|
|
|
|
|
|
|
/// Key equality function.
|
|
|
|
bool operator==(const KeyTy &key) const { return key == value; }
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static IntegerSetAttributeStorage *
|
|
|
|
construct(AttributeStorageAllocator &allocator, KeyTy key) {
|
|
|
|
return new (allocator.allocate<IntegerSetAttributeStorage>())
|
|
|
|
IntegerSetAttributeStorage(key);
|
|
|
|
}
|
|
|
|
|
2018-10-26 13:13:03 +08:00
|
|
|
IntegerSet value;
|
|
|
|
};
|
|
|
|
|
2018-10-26 06:46:10 +08:00
|
|
|
/// An attribute representing a reference to a type.
|
|
|
|
struct TypeAttributeStorage : public AttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = Type;
|
|
|
|
|
|
|
|
TypeAttributeStorage(Type value) : value(value) {}
|
|
|
|
|
|
|
|
/// Key equality function.
|
|
|
|
bool operator==(const KeyTy &key) const { return key == value; }
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static TypeAttributeStorage *construct(AttributeStorageAllocator &allocator,
|
|
|
|
KeyTy key) {
|
|
|
|
return new (allocator.allocate<TypeAttributeStorage>())
|
|
|
|
TypeAttributeStorage(key);
|
|
|
|
}
|
|
|
|
|
2018-10-31 05:59:22 +08:00
|
|
|
Type value;
|
2018-10-26 06:46:10 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/// An attribute representing a reference to a function.
|
|
|
|
struct FunctionAttributeStorage : public AttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = Function *;
|
|
|
|
|
2019-03-23 15:40:25 +08:00
|
|
|
FunctionAttributeStorage(Function *value)
|
2019-05-01 01:31:29 +08:00
|
|
|
: AttributeStorage(/*isOrContainsFunctionCache=*/true), value(value) {}
|
|
|
|
|
|
|
|
/// Key equality function.
|
|
|
|
bool operator==(const KeyTy &key) const { return key == value; }
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static FunctionAttributeStorage *
|
|
|
|
construct(AttributeStorageAllocator &allocator, KeyTy key) {
|
|
|
|
return new (allocator.allocate<FunctionAttributeStorage>())
|
|
|
|
FunctionAttributeStorage(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Storage cleanup function.
|
|
|
|
void cleanup() {
|
|
|
|
// Null out the function reference in the attribute to avoid dangling
|
|
|
|
// pointers.
|
|
|
|
value = nullptr;
|
|
|
|
}
|
|
|
|
|
2018-10-26 06:46:10 +08:00
|
|
|
Function *value;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// A base attribute representing a reference to a vector or tensor constant.
|
|
|
|
struct ElementsAttributeStorage : public AttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
ElementsAttributeStorage(VectorOrTensorType type) : type(type) {}
|
2018-10-31 05:59:22 +08:00
|
|
|
VectorOrTensorType type;
|
2018-10-26 06:46:10 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/// An attribute representing a reference to a vector or tensor constant,
|
|
|
|
/// inwhich all elements have the same value.
|
|
|
|
struct SplatElementsAttributeStorage : public ElementsAttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = std::pair<VectorOrTensorType, Attribute>;
|
|
|
|
|
2019-03-23 15:40:25 +08:00
|
|
|
SplatElementsAttributeStorage(VectorOrTensorType type, Attribute elt)
|
2019-05-01 01:31:29 +08:00
|
|
|
: ElementsAttributeStorage(type), elt(elt) {}
|
|
|
|
|
|
|
|
/// Key equality and hash functions.
|
|
|
|
bool operator==(const KeyTy &key) const {
|
|
|
|
return key == std::make_pair(type, elt);
|
|
|
|
}
|
|
|
|
static unsigned hashKey(const KeyTy &key) {
|
|
|
|
return llvm::hash_combine(key.first, key.second);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static SplatElementsAttributeStorage *
|
|
|
|
construct(AttributeStorageAllocator &allocator, KeyTy key) {
|
|
|
|
return new (allocator.allocate<SplatElementsAttributeStorage>())
|
|
|
|
SplatElementsAttributeStorage(key.first, key.second);
|
|
|
|
}
|
|
|
|
|
2018-10-26 06:46:10 +08:00
|
|
|
Attribute elt;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// An attribute representing a reference to a dense vector or tensor object.
|
|
|
|
struct DenseElementsAttributeStorage : public ElementsAttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = std::pair<VectorOrTensorType, ArrayRef<char>>;
|
|
|
|
|
|
|
|
DenseElementsAttributeStorage(VectorOrTensorType ty, ArrayRef<char> data)
|
|
|
|
: ElementsAttributeStorage(ty), data(data) {}
|
|
|
|
|
|
|
|
/// Key equality and hash functions.
|
|
|
|
bool operator==(const KeyTy &key) const { return key == KeyTy(type, data); }
|
|
|
|
static unsigned hashKey(const KeyTy &key) {
|
|
|
|
return llvm::hash_combine(key.first, key.second);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static DenseElementsAttributeStorage *
|
|
|
|
construct(AttributeStorageAllocator &allocator, KeyTy key) {
|
|
|
|
// If the data buffer is non-empty, we copy it into the allocator.
|
|
|
|
ArrayRef<char> data = key.second;
|
|
|
|
if (!data.empty()) {
|
|
|
|
// Rounding up the allocate size to multiples of APINT_WORD_SIZE, so
|
|
|
|
// the `readBits` will not fail when it accesses multiples of
|
|
|
|
// APINT_WORD_SIZE each time.
|
|
|
|
size_t sizeToAllocate =
|
|
|
|
llvm::alignTo(data.size(), APInt::APINT_WORD_SIZE);
|
|
|
|
auto *rawCopy = (char *)allocator.allocate(sizeToAllocate, 64);
|
|
|
|
std::uninitialized_copy(data.begin(), data.end(), rawCopy);
|
|
|
|
data = {rawCopy, data.size()};
|
|
|
|
}
|
|
|
|
return new (allocator.allocate<DenseElementsAttributeStorage>())
|
|
|
|
DenseElementsAttributeStorage(key.first, data);
|
|
|
|
}
|
|
|
|
|
2018-10-26 06:46:10 +08:00
|
|
|
ArrayRef<char> data;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// An attribute representing a reference to a tensor constant with opaque
|
|
|
|
/// content.
|
|
|
|
struct OpaqueElementsAttributeStorage : public ElementsAttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy = std::tuple<VectorOrTensorType, Dialect *, StringRef>;
|
|
|
|
|
2019-03-23 15:40:25 +08:00
|
|
|
OpaqueElementsAttributeStorage(VectorOrTensorType type, Dialect *dialect,
|
|
|
|
StringRef bytes)
|
2019-05-01 01:31:29 +08:00
|
|
|
: ElementsAttributeStorage(type), dialect(dialect), bytes(bytes) {}
|
|
|
|
|
|
|
|
/// Key equality and hash functions.
|
|
|
|
bool operator==(const KeyTy &key) const {
|
|
|
|
return key == std::make_tuple(type, dialect, bytes);
|
|
|
|
}
|
|
|
|
static unsigned hashKey(const KeyTy &key) {
|
|
|
|
return llvm::hash_combine(std::get<0>(key), std::get<1>(key),
|
|
|
|
std::get<2>(key));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static OpaqueElementsAttributeStorage *
|
|
|
|
construct(AttributeStorageAllocator &allocator, KeyTy key) {
|
|
|
|
// TODO(b/131468830): Provide a way to avoid copying content of large opaque
|
|
|
|
// tensors This will likely require a new reference attribute kind.
|
|
|
|
return new (allocator.allocate<OpaqueElementsAttributeStorage>())
|
|
|
|
OpaqueElementsAttributeStorage(std::get<0>(key), std::get<1>(key),
|
|
|
|
allocator.copyInto(std::get<2>(key)));
|
|
|
|
}
|
|
|
|
|
2019-02-12 14:51:34 +08:00
|
|
|
Dialect *dialect;
|
2018-10-26 06:46:10 +08:00
|
|
|
StringRef bytes;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// An attribute representing a reference to a sparse vector or tensor object.
|
|
|
|
struct SparseElementsAttributeStorage : public ElementsAttributeStorage {
|
2019-05-01 01:31:29 +08:00
|
|
|
using KeyTy =
|
|
|
|
std::tuple<VectorOrTensorType, DenseIntElementsAttr, DenseElementsAttr>;
|
|
|
|
|
2019-03-23 15:40:25 +08:00
|
|
|
SparseElementsAttributeStorage(VectorOrTensorType type,
|
2019-03-19 23:45:06 +08:00
|
|
|
DenseIntElementsAttr indices,
|
|
|
|
DenseElementsAttr values)
|
2019-05-01 01:31:29 +08:00
|
|
|
: ElementsAttributeStorage(type), indices(indices), values(values) {}
|
|
|
|
|
|
|
|
/// Key equality and hash functions.
|
|
|
|
bool operator==(const KeyTy &key) const {
|
|
|
|
return key == std::make_tuple(type, indices, values);
|
|
|
|
}
|
|
|
|
static unsigned hashKey(const KeyTy &key) {
|
|
|
|
return llvm::hash_combine(std::get<0>(key), std::get<1>(key),
|
|
|
|
std::get<2>(key));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct a new storage instance.
|
|
|
|
static SparseElementsAttributeStorage *
|
|
|
|
construct(AttributeStorageAllocator &allocator, KeyTy key) {
|
|
|
|
return new (allocator.allocate<SparseElementsAttributeStorage>())
|
|
|
|
SparseElementsAttributeStorage(std::get<0>(key), std::get<1>(key),
|
|
|
|
std::get<2>(key));
|
|
|
|
}
|
|
|
|
|
2018-10-26 06:46:10 +08:00
|
|
|
DenseIntElementsAttr indices;
|
|
|
|
DenseElementsAttr values;
|
|
|
|
};
|
|
|
|
|
2019-02-27 10:01:46 +08:00
|
|
|
/// A raw list of named attributes stored as a trailing array.
|
|
|
|
class AttributeListStorage final
|
|
|
|
: private llvm::TrailingObjects<AttributeListStorage, NamedAttribute> {
|
|
|
|
friend class llvm::TrailingObjects<AttributeListStorage, NamedAttribute>;
|
|
|
|
|
|
|
|
public:
|
|
|
|
/// Given a list of NamedAttribute's, canonicalize the list (sorting
|
|
|
|
/// by name) and return the unique'd result. Note that the empty list is
|
|
|
|
/// represented with a null pointer.
|
|
|
|
static AttributeListStorage *get(ArrayRef<NamedAttribute> attrs,
|
|
|
|
MLIRContext *context);
|
|
|
|
|
|
|
|
/// Return the element constants for this aggregate constant. These are
|
|
|
|
/// known to all be constants.
|
|
|
|
ArrayRef<NamedAttribute> getElements() const {
|
|
|
|
return {getTrailingObjects<NamedAttribute>(), numElements};
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// This is used by the llvm::TrailingObjects base class.
|
|
|
|
size_t numTrailingObjects(OverloadToken<NamedAttribute>) const {
|
|
|
|
return numElements;
|
|
|
|
}
|
|
|
|
AttributeListStorage() = delete;
|
|
|
|
AttributeListStorage(const AttributeListStorage &) = delete;
|
|
|
|
AttributeListStorage(unsigned numElements) : numElements(numElements) {}
|
|
|
|
|
|
|
|
/// This is the number of attributes.
|
|
|
|
const unsigned numElements;
|
|
|
|
};
|
2018-10-26 06:46:10 +08:00
|
|
|
} // namespace detail
|
|
|
|
} // namespace mlir
|
|
|
|
|
|
|
|
#endif // ATTRIBUTEDETAIL_H_
|